WIP Resource event handling
[aquarium] / src / test / scala / gr / grnet / aquarium / user / UserStateComputationsTest.scala
index 8731d86..7d9c28c 100644 (file)
 
 package gr.grnet.aquarium.user
 
-import gr.grnet.aquarium.Configurator
 import gr.grnet.aquarium.store.memory.MemStore
-import gr.grnet.aquarium.util.date.MutableDateCalc
 import gr.grnet.aquarium.logic.accounting.dsl._
-import gr.grnet.aquarium.logic.accounting.{Policy, Accounting}
-import gr.grnet.aquarium.util.{Loggable, ContextualLogger, justForSure}
+import gr.grnet.aquarium.logic.accounting.Policy
+import gr.grnet.aquarium.util.{Loggable, ContextualLogger}
 import gr.grnet.aquarium.simulation._
-import gr.grnet.aquarium.simulation.uid.{UIDGenerator, ConcurrentVMLocalUIDGenerator}
-import com.ckkloverdos.maybe.{Maybe, Just, NoVal}
+import gr.grnet.aquarium.uid.{UIDGenerator, ConcurrentVMLocalUIDGenerator}
 import org.junit.{Assert, Ignore, Test}
-import gr.grnet.aquarium.logic.accounting.algorithm.{ExecutableCostPolicyAlgorithm, CostPolicyAlgorithmCompiler, SimpleCostPolicyAlgorithmCompiler}
+import gr.grnet.aquarium.logic.accounting.algorithm.{ExecutableCostPolicyAlgorithm, CostPolicyAlgorithmCompiler}
+import gr.grnet.aquarium.AquariumException
+import gr.grnet.aquarium.Aquarium.{Instance ⇒ AquariumInstance}
+import gr.grnet.aquarium.computation.reason.{NoSpecificChangeReason, MonthlyBillingCalculation}
+import gr.grnet.aquarium.util.date.MutableDateCalc
+import gr.grnet.aquarium.computation.BillingMonthInfo
+import gr.grnet.aquarium.computation.state.{UserStateBootstrap, UserState}
 
 
 /**
@@ -125,11 +128,16 @@ aquariumpolicy:
     DiskspacePriceUnit
   )
 
-  val Computations = new UserStateComputations
+  val aquarium = AquariumInstance.withStoreProviderClass(classOf[MemStore])
+  Policy.withConfigurator(aquarium)
+  val StoreProvider = aquarium.storeProvider
+  val ResourceEventStore = StoreProvider.resourceEventStore
+
+  val Computations = aquarium.userStateComputations
+
+  val DSL = new DSL {}
+  val DefaultPolicy = DSL parse PolicyYAML
 
-  val DefaultPolicy = new DSL{} parse PolicyYAML
-  val DefaultAccounting = new Accounting{}
-  
   val DefaultAlgorithm = new ExecutableCostPolicyAlgorithm {
     def creditsForContinuous(timeDelta: Double, oldTotalAmount: Double) =
       hrs(timeDelta) * oldTotalAmount * ContinuousPriceUnit
@@ -149,7 +157,7 @@ aquariumpolicy:
     @inline private[this]
     def hrs(millis: Double) = millis / 1000 / 60 / 60
 
-    def apply(vars: Map[DSLCostPolicyVar, Any]): Maybe[Double] = Maybe {
+    def apply(vars: Map[DSLCostPolicyVar, Any]): Double = {
       vars.apply(DSLCostPolicyNameVar) match {
         case DSLCostPolicyNames.continuous ⇒
           val unitPrice = vars(DSLUnitPriceVar).asInstanceOf[Double]
@@ -181,7 +189,7 @@ aquariumpolicy:
           currentValue
 
         case name ⇒
-          throw new Exception("Unknown cost policy %s".format(name))
+          throw new AquariumException("Unknown cost policy %s".format(name))
       }
     }
 
@@ -194,8 +202,8 @@ aquariumpolicy:
   }
 
   val DefaultCompiler  = new CostPolicyAlgorithmCompiler {
-    def compile(definition: String): Maybe[ExecutableCostPolicyAlgorithm] = {
-      Just(DefaultAlgorithm)
+    def compile(definition: String): ExecutableCostPolicyAlgorithm = {
+      DefaultAlgorithm
     }
   }
   //val DefaultAlgorithm = justForSure(DefaultCompiler.compile("")).get // hardcoded since we know exactly what this is
@@ -209,15 +217,10 @@ aquariumpolicy:
   val BandwidthResourceSim = StdBandwidthResourceSim.fromPolicy(DefaultPolicy)
 
   // There are two client services, synnefo and pithos.
-  val TheUIDGenerator: UIDGenerator = new ConcurrentVMLocalUIDGenerator
+  val TheUIDGenerator: UIDGenerator[_] = new ConcurrentVMLocalUIDGenerator
   val Synnefo = ClientSim("synnefo")(TheUIDGenerator)
   val Pithos  = ClientSim("pithos" )(TheUIDGenerator)
 
-  val mc = Configurator.MasterConfigurator.withStoreProviderClass(classOf[MemStore])
-  Policy.withConfigurator(mc)
-  val StoreProvider = mc.storeProvider
-  val ResourceEventStore = StoreProvider.resourceEventStore
-
   val StartOfBillingYearDateCalc = new MutableDateCalc(2012,  1, 1)
   val UserCreationDate           = new MutableDateCalc(2011, 11, 1).toDate
 
@@ -240,13 +243,20 @@ aquariumpolicy:
 
   val UserCKKL  = Aquarium.newUser("CKKL", UserCreationDate)
 
-  val InitialUserState = Computations.createInitialUserState(
-    userId = UserCKKL.userId,
-    userCreationMillis = UserCreationDate.getTime,
-    isActive = true,
-    credits = 0.0,
-    roleNames = List("user"),
-    agreementName = DSLAgreement.DefaultAgreementName
+//  val InitialUserState = UserState.createInitialUserState(
+//    userID = UserCKKL.userID,
+//    userCreationMillis = UserCreationDate.getTime,
+//    totalCredits = 0.0,
+//    initialRole = "default",
+//    initialAgreement = DSLAgreement.DefaultAgreementName
+//  )
+
+  val UserStateBootstrapper = UserStateBootstrap(
+    userID = UserCKKL.userID,
+    userCreationMillis = UserCreationDate.getTime(),
+    initialRole = "default",
+    initialAgreement = DSLAgreement.DefaultAgreementName,
+    initialCredits = 0.0
   )
 
   // By convention
@@ -258,19 +268,17 @@ aquariumpolicy:
 
   private[this]
   def showUserState(clog: ContextualLogger, userState: UserState) {
-    val id = userState.id
-    val parentId = userState.parentUserStateId
-    val credits = userState.creditsSnapshot.creditAmount
+    val id = userState._id
+    val parentId = userState.parentUserStateIDInStore
+    val credits = userState.totalCredits
     val newWalletEntries = userState.newWalletEntries.map(_.toDebugString)
-    val changeReasonCode = userState.lastChangeReasonCode
     val changeReason = userState.lastChangeReason
-    val implicitlyIssued = userState.implicitlyIssuedSnapshot.implicitlyIssuedEvents.map(_.toDebugString())
-    val latestResourceEvents = userState.latestResourceEventsSnapshot.resourceEvents.map(_.toDebugString())
+    val implicitlyIssued = userState.implicitlyIssuedSnapshot.implicitlyIssuedEvents.map(_.toDebugString)
+    val latestResourceEvents = userState.latestResourceEventsSnapshot.resourceEvents.map(_.toDebugString)
 
     clog.debug("_id = %s", id)
     clog.debug("parentId = %s", parentId)
     clog.debug("credits = %s", credits)
-    clog.debug("changeReasonCode = %s", changeReasonCode)
     clog.debug("changeReason = %s", changeReason)
     clog.debugSeq("implicitlyIssued", implicitlyIssued, 0)
     clog.debugSeq("latestResourceEvents", latestResourceEvents, 0)
@@ -283,7 +291,7 @@ aquariumpolicy:
     clog.begin("Events by OccurredMillis")
     clog.withIndent {
       for(event <- UserCKKL.myResourceEventsByOccurredDate) {
-        clog.debug(event.toDebugString())
+        clog.debug(event.toDebugString)
       }
     }
     clog.end("Events by OccurredMillis")
@@ -291,35 +299,33 @@ aquariumpolicy:
   }
 
   private[this]
-  def doFullMonthlyBilling(clog: ContextualLogger, billingMonthInfo: BillingMonthInfo) = {
-    Computations.doFullMonthlyBilling(
-      UserCKKL.userId,
+  def doFullMonthlyBilling(
+      clog: ContextualLogger,
+      billingMonthInfo: BillingMonthInfo,
+      billingTimeMillis: Long) = {
+
+    Computations.doMonthBillingUpTo(
       billingMonthInfo,
-      StoreProvider,
-      InitialUserState,
+      billingTimeMillis,
+      UserStateBootstrapper,
       DefaultResourcesMap,
-      DefaultAccounting,
-      DefaultCompiler,
-      MonthlyBillingCalculation(billingMonthInfo),
-      Just(clog)
+      MonthlyBillingCalculation(NoSpecificChangeReason(), billingMonthInfo),
+      aquarium.userStateStore.insertUserState,
+      Some(clog)
     )
   }
-  
-  private[this]
-  def justUserState(userStateM: Maybe[UserState]): UserState = {
-    userStateM match {
-      case Just(userState) ⇒ userState
-      case _ ⇒ throw new Exception("Unexpected %s".format(userStateM))
-    }
-  }
-  
+
   private[this]
-  def expectCredits(clog: ContextualLogger,
-                    creditsConsumed: Double,
-                    userState: UserState,
-                    accuracy: Double = 0.001): Unit = {
-    val computed = userState.creditsSnapshot.creditAmount
+  def expectCredits(
+      clog: ContextualLogger,
+      creditsConsumed: Double,
+      userState: UserState,
+      accuracy: Double = 0.001
+  ): Unit = {
+
+    val computed = userState.totalCredits
     Assert.assertEquals(-creditsConsumed, computed, accuracy)
+
     clog.info("Consumed %.3f credits [accuracy = %f]", creditsConsumed, accuracy)
   }
 
@@ -335,7 +341,7 @@ aquariumpolicy:
   @Ignore
   @Test
   def testFullOnOff: Unit = {
-    val clog = ContextualLogger.fromOther(NoVal, logger, "testFullOnOff()")
+    val clog = ContextualLogger.fromOther(None, logger, "testFullOnOff()")
     clog.begin()
 
     ResourceEventStore.clearResourceEvents()
@@ -351,9 +357,8 @@ aquariumpolicy:
 
     showResourceEvents(clog)
 
-    val userStateM = doFullMonthlyBilling(clog, BillingMonthInfoJan)
-    val userState = justUserState(userStateM)
-    
+    val userState = doFullMonthlyBilling(clog, BillingMonthInfoJan, BillingMonthInfoJan.monthStopMillis)
+
     showUserState(clog, userState)
 
     expectCredits(clog, credits, userState)
@@ -364,7 +369,7 @@ aquariumpolicy:
   @Ignore
   @Test
   def testLonelyON: Unit = {
-    val clog = ContextualLogger.fromOther(NoVal, logger, "testLonelyON()")
+    val clog = ContextualLogger.fromOther(None, logger, "testLonelyON()")
     clog.begin()
 
     ResourceEventStore.clearResourceEvents()
@@ -381,8 +386,7 @@ aquariumpolicy:
 
     showResourceEvents(clog)
 
-    val userStateM = doFullMonthlyBilling(clog, BillingMonthInfoJan)
-    val userState = justUserState(userStateM)
+    val userState = doFullMonthlyBilling(clog, BillingMonthInfoJan, BillingMonthInfoJan.monthStopMillis)
 
     showUserState(clog, userState)
 
@@ -394,7 +398,7 @@ aquariumpolicy:
 //  @Ignore
   @Test
   def testOrphanOFF: Unit = {
-    val clog = ContextualLogger.fromOther(NoVal, logger, "testOrphanOFF()")
+    val clog = ContextualLogger.fromOther(None, logger, "testOrphanOFF()")
     clog.begin()
 
     ResourceEventStore.clearResourceEvents()
@@ -412,8 +416,7 @@ aquariumpolicy:
 
     showResourceEvents(clog)
 
-    val userStateM = doFullMonthlyBilling(clog, BillingMonthInfoJan)
-    val userState = justUserState(userStateM)
+    val userState = doFullMonthlyBilling(clog, BillingMonthInfoJan, BillingMonthInfoJan.monthStopMillis)
 
     showUserState(clog, userState)
 
@@ -425,7 +428,7 @@ aquariumpolicy:
   @Ignore
   @Test
   def testOne: Unit = {
-    val clog = ContextualLogger.fromOther(NoVal, logger, "testOne()")
+    val clog = ContextualLogger.fromOther(None, logger, "testOne()")
     clog.begin()
 
     // Let's create our dates of interest
@@ -464,8 +467,8 @@ aquariumpolicy:
 
     clog.debugMap("DefaultResourcesMap", DefaultResourcesMap.map, 1)
 
-    val userStateM = doFullMonthlyBilling(clog, BillingMonthInfoJan)
-    val userState = justUserState(userStateM)
+    val userState = doFullMonthlyBilling(clog, BillingMonthInfoJan, BillingMonthInfoJan.monthStopMillis)
+
     showUserState(clog, userState)
 
     clog.end()