Fix a compilation error (did not implement a MemStore method)
[aquarium] / src / test / scala / gr / grnet / aquarium / user / UserStateComputationsTest.scala
index 3417a6e..7fe30b2 100644 (file)
 
 package gr.grnet.aquarium.user
 
-import gr.grnet.aquarium.store.memory.MemStore
+import gr.grnet.aquarium.store.memory.MemStoreProvider
 import gr.grnet.aquarium.logic.accounting.dsl._
-import gr.grnet.aquarium.logic.accounting.Policy
 import gr.grnet.aquarium.util.{Loggable, ContextualLogger}
 import gr.grnet.aquarium.simulation._
 import gr.grnet.aquarium.uid.{UIDGenerator, ConcurrentVMLocalUIDGenerator}
 import org.junit.{Assert, Ignore, Test}
-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.logic.accounting.algorithm.{ExecutableChargingBehaviorAlgorithm, CostPolicyAlgorithmCompiler}
+import gr.grnet.aquarium.{Timespan, Aquarium, ResourceLocator, AquariumBuilder, AquariumException}
 import gr.grnet.aquarium.computation.reason.{NoSpecificChangeReason, MonthlyBillingCalculation}
-import gr.grnet.aquarium.computation.{TimeslotComputations, UserStateBootstrappingData, UserState, BillingMonthInfo}
-import gr.grnet.aquarium.util.date.{TimeHelpers, MutableDateCalc}
+import gr.grnet.aquarium.util.date.MutableDateCalc
+import gr.grnet.aquarium.computation.BillingMonthInfo
+import gr.grnet.aquarium.computation.state.{UserStateBootstrap, UserState}
+import gr.grnet.aquarium.charging._
+import gr.grnet.aquarium.policy.{PolicyDefinedFullPriceTableRef, StdUserAgreement, EffectiveUnitPrice, EffectivePriceTable, FullPriceTable, ResourceType, StdPolicy, PolicyModel}
+import gr.grnet.aquarium.Timespan
+import scala.Some
+import gr.grnet.aquarium.computation.state.UserStateBootstrap
+import gr.grnet.aquarium.simulation.AquariumSim
+import gr.grnet.aquarium.simulation.ClientSim
 
 
 /**
@@ -57,134 +63,93 @@ import gr.grnet.aquarium.util.date.{TimeHelpers, MutableDateCalc}
 class UserStateComputationsTest extends Loggable {
   final val DoubleDelta = 0.001
 
-  final val BandwidthPriceUnit = 3.3 //
-  final val VMTimePriceUnit    = 1.5 //
-  final val DiskspacePriceUnit = 2.7 //
-
-  final val OnOffPriceUnit = VMTimePriceUnit
-  final val ContinuousPriceUnit = DiskspacePriceUnit
-  final val DiscretePriceUnit = BandwidthPriceUnit
-
-  final val PolicyYAML = """
-aquariumpolicy:
-  resources:
-    - resource:
-      name: bandwidth
-      unit: MB/Hr
-      complex: false
-      costpolicy: discrete
-    - resource:
-      name: vmtime
-      unit: Hr
-      complex: true
-      costpolicy: onoff
-      descriminatorfield: vmid
-    - resource:
-      name: diskspace
-      unit: MB/hr
-      complex: false
-      costpolicy: continuous
-
-  implicitvars:
-    - price
-    - volume
-
-  algorithms:
-    - algorithm:
-      name: default
-      bandwidth: function bandwidth() {return 1;}
-      vmtime: function vmtime() {return 1;}
-      diskspace: function diskspace() {return 1;}
-      effective:
-        from: 0
-
-  pricelists:
-    - pricelist:
-      name: default
-      bandwidth: %s
-      vmtime: %s
-      diskspace: %s
-      effective:
-        from: 0
-
-  creditplans:
-    - creditplan:
-      name: default
-      credits: 100
-      at: "00 00 1 * *"
-      effective:
-        from: 0
-
-  agreements:
-    - agreement:
-      name: default
-      algorithm: default
-      pricelist: default
-      creditplan: default
-  """.format(
-    BandwidthPriceUnit,
-    VMTimePriceUnit,
-    DiskspacePriceUnit
+  final val BandwidthUnitPrice = 3.3 //
+  final val VMTimeUnitPrice    = 1.5 //
+  final val DiskspaceUnitPrice = 2.7 //
+
+  final val OnOffUnitPrice = VMTimeUnitPrice
+  final val ContinuousUnitPrice = DiskspaceUnitPrice
+  final val DiscreteUnitPrice = BandwidthUnitPrice
+
+  final val DefaultPolicy: PolicyModel = StdPolicy(
+    id = "policy-1",
+    parentID = None,
+    validityTimespan = Timespan(0),
+    resourceTypes = Set(
+      ResourceType("bandwidth", "MB/Hr", DiscreteChargingBehavior),
+      ResourceType("vmtime",    "Hr",    OnOffChargingBehavior),
+      ResourceType("diskspace", "MB/Hr", ContinuousChargingBehavior)
+    ),
+    chargingBehaviorClasses = Set(
+      DiscreteChargingBehavior.getClass.getName,
+      OnOffChargingBehavior.getClass.getName,
+      ContinuousChargingBehavior.getClass.getName
+    ),
+    roleMapping = Map(
+      "default" -> FullPriceTable(Map(
+        "bandwidth" -> EffectivePriceTable(EffectiveUnitPrice(BandwidthUnitPrice, None) :: Nil),
+        "vmtime"    -> EffectivePriceTable(EffectiveUnitPrice(VMTimeUnitPrice, None) :: Nil),
+        "diskspace" -> EffectivePriceTable(EffectiveUnitPrice(DiskspaceUnitPrice, None) :: Nil)
+      ))
+    )
   )
 
-  val aquarium = AquariumInstance.withStoreProviderClass(classOf[MemStore])
-  Policy.withConfigurator(aquarium)
-  val StoreProvider = aquarium.storeProvider
-  val ResourceEventStore = StoreProvider.resourceEventStore
+  val aquarium = new AquariumBuilder(ResourceLocator.AquariumProperties).
+    update(Aquarium.EnvKeys.storeProvider, new MemStoreProvider).
+    build()
 
-  val Computations = aquarium.userStateComputations
+  val ResourceEventStore = aquarium.resourceEventStore
 
-  val DSL = new DSL {}
-  val DefaultPolicy = DSL parse PolicyYAML
+  val Computations = aquarium.userStateComputations
 
-  val DefaultAlgorithm = new ExecutableCostPolicyAlgorithm {
+  val DefaultAlgorithm = new ExecutableChargingBehaviorAlgorithm {
     def creditsForContinuous(timeDelta: Double, oldTotalAmount: Double) =
-      hrs(timeDelta) * oldTotalAmount * ContinuousPriceUnit
+      hrs(timeDelta) * oldTotalAmount * ContinuousUnitPrice
 
     final val creditsForDiskspace = creditsForContinuous(_, _)
     
     def creditsForDiscrete(currentValue: Double) =
-      currentValue * DiscretePriceUnit
+      currentValue * DiscreteUnitPrice
 
     final val creditsForBandwidth = creditsForDiscrete(_)
 
     def creditsForOnOff(timeDelta: Double) =
-      hrs(timeDelta) * OnOffPriceUnit
+      hrs(timeDelta) * OnOffUnitPrice
 
     final val creditsForVMTime = creditsForOnOff(_)
 
     @inline private[this]
     def hrs(millis: Double) = millis / 1000 / 60 / 60
 
-    def apply(vars: Map[DSLCostPolicyVar, Any]): Double = {
-      vars.apply(DSLCostPolicyNameVar) match {
-        case DSLCostPolicyNames.continuous ⇒
-          val unitPrice = vars(DSLUnitPriceVar).asInstanceOf[Double]
-          val oldTotalAmount = vars(DSLOldTotalAmountVar).asInstanceOf[Double]
-          val timeDelta = vars(DSLTimeDeltaVar).asInstanceOf[Double]
+    def apply(vars: Map[ChargingInput, Any]): Double = {
+      vars.apply(ChargingBehaviorNameInput) match {
+        case ChargingBehaviorNames.continuous ⇒
+          val unitPrice = vars(UnitPriceInput).asInstanceOf[Double]
+          val oldTotalAmount = vars(OldTotalAmountInput).asInstanceOf[Double]
+          val timeDelta = vars(TimeDeltaInput).asInstanceOf[Double]
 
-          Assert.assertEquals(ContinuousPriceUnit, unitPrice, DoubleDelta)
+          Assert.assertEquals(ContinuousUnitPrice, unitPrice, DoubleDelta)
 
           creditsForContinuous(timeDelta, oldTotalAmount)
 
-        case DSLCostPolicyNames.discrete ⇒
-          val unitPrice = vars(DSLUnitPriceVar).asInstanceOf[Double]
-          val currentValue = vars(DSLCurrentValueVar).asInstanceOf[Double]
+        case ChargingBehaviorNames.discrete ⇒
+          val unitPrice = vars(UnitPriceInput).asInstanceOf[Double]
+          val currentValue = vars(CurrentValueInput).asInstanceOf[Double]
 
-          Assert.assertEquals(DiscretePriceUnit, unitPrice, DoubleDelta)
+          Assert.assertEquals(DiscreteUnitPrice, unitPrice, DoubleDelta)
 
           creditsForDiscrete(currentValue)
 
-        case DSLCostPolicyNames.onoff ⇒
-          val unitPrice = vars(DSLUnitPriceVar).asInstanceOf[Double]
-          val timeDelta = vars(DSLTimeDeltaVar).asInstanceOf[Double]
+        case ChargingBehaviorNames.onoff ⇒
+          val unitPrice = vars(UnitPriceInput).asInstanceOf[Double]
+          val timeDelta = vars(TimeDeltaInput).asInstanceOf[Double]
 
-          Assert.assertEquals(OnOffPriceUnit, unitPrice, DoubleDelta)
+          Assert.assertEquals(OnOffUnitPrice, unitPrice, DoubleDelta)
 
           creditsForOnOff(timeDelta)
 
-        case DSLCostPolicyNames.once ⇒
-          val currentValue = vars(DSLCurrentValueVar).asInstanceOf[Double]
+        case ChargingBehaviorNames.once ⇒
+          val currentValue = vars(CurrentValueInput).asInstanceOf[Double]
           currentValue
 
         case name ⇒
@@ -194,20 +159,20 @@ aquariumpolicy:
 
     override def toString = "DefaultAlgorithm(%s)".format(
       Map(
-        DSLCostPolicyNames.continuous -> "hrs(timeDelta) * oldTotalAmount * %s".format(ContinuousPriceUnit),
-        DSLCostPolicyNames.discrete   -> "currentValue * %s".format(DiscretePriceUnit),
-        DSLCostPolicyNames.onoff      -> "hrs(timeDelta) * %s".format(OnOffPriceUnit),
-        DSLCostPolicyNames.once       -> "currentValue"))
+        ChargingBehaviorNames.continuous -> "hrs(timeDelta) * oldTotalAmount * %s".format(ContinuousUnitPrice),
+        ChargingBehaviorNames.discrete   -> "currentValue * %s".format(DiscreteUnitPrice),
+        ChargingBehaviorNames.onoff      -> "hrs(timeDelta) * %s".format(OnOffUnitPrice),
+        ChargingBehaviorNames.once       -> "currentValue"))
   }
 
   val DefaultCompiler  = new CostPolicyAlgorithmCompiler {
-    def compile(definition: String): ExecutableCostPolicyAlgorithm = {
+    def compile(definition: String): ExecutableChargingBehaviorAlgorithm = {
       DefaultAlgorithm
     }
   }
   //val DefaultAlgorithm = justForSure(DefaultCompiler.compile("")).get // hardcoded since we know exactly what this is
 
-  val VMTimeDSLResource = DefaultPolicy.findResource("vmtime").get
+  val VMTimeDSLResource = DefaultPolicy.resourceTypesMap("vmtime")
 
   // For this to work, the definitions must match those in the YAML above.
   // Those StdXXXResourceSim are just for debugging convenience anyway, so they must match by design.
@@ -235,12 +200,13 @@ aquariumpolicy:
   val policyOccurredMillis  = policyDateCalc.toMillis
   val policyValidFromMillis = policyDateCalc.copy.goPreviousYear.toMillis
   val policyValidToMillis   = policyDateCalc.copy.goNextYear.toMillis
-  StoreProvider.policyStore.storePolicyEntry(DefaultPolicy.toPolicyEntry(policyOccurredMillis, policyValidFromMillis, policyValidToMillis))
 
-  val Aquarium = AquariumSim(List(VMTimeResourceSim, DiskspaceResourceSim, BandwidthResourceSim), StoreProvider.resourceEventStore)
-  val DefaultResourcesMap = Aquarium.resourcesMap
+  aquarium.policyStore.insertPolicy(DefaultPolicy)
+
+  val AquariumSim_ = AquariumSim(List(VMTimeResourceSim, DiskspaceResourceSim, BandwidthResourceSim), aquarium.resourceEventStore)
+  val DefaultResourcesMap = DefaultPolicy.resourceTypesMap//AquariumSim_.resourcesMap
 
-  val UserCKKL  = Aquarium.newUser("CKKL", UserCreationDate)
+  val UserCKKL  = AquariumSim_.newUser("CKKL", UserCreationDate)
 
 //  val InitialUserState = UserState.createInitialUserState(
 //    userID = UserCKKL.userID,
@@ -250,11 +216,10 @@ aquariumpolicy:
 //    initialAgreement = DSLAgreement.DefaultAgreementName
 //  )
 
-  val UserStateBootstrap = UserStateBootstrappingData(
+  val UserStateBootstrapper = UserStateBootstrap(
     userID = UserCKKL.userID,
     userCreationMillis = UserCreationDate.getTime(),
-    initialRole = "default",
-    initialAgreement = DSLAgreement.DefaultAgreementName,
+    initialAgreement = StdUserAgreement("", None, Timespan(0), "default", PolicyDefinedFullPriceTableRef),
     initialCredits = 0.0
   )
 
@@ -301,27 +266,30 @@ aquariumpolicy:
   def doFullMonthlyBilling(
       clog: ContextualLogger,
       billingMonthInfo: BillingMonthInfo,
-      isFullBillingMonthState: Boolean,
       billingTimeMillis: Long) = {
 
-    Computations.doBillingForMonth(
-      UserStateBootstrap,
+    Computations.doMonthBillingUpTo(
       billingMonthInfo,
-      isFullBillingMonthState,
       billingTimeMillis,
+      UserStateBootstrapper,
       DefaultResourcesMap,
       MonthlyBillingCalculation(NoSpecificChangeReason(), billingMonthInfo),
+      aquarium.userStateStore.insertUserState,
       Some(clog)
     )
   }
 
   private[this]
-  def expectCredits(clog: ContextualLogger,
-                    creditsConsumed: Double,
-                    userState: UserState,
-                    accuracy: Double = 0.001): Unit = {
+  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)
   }
 
@@ -353,7 +321,7 @@ aquariumpolicy:
 
     showResourceEvents(clog)
 
-    val userState = doFullMonthlyBilling(clog, BillingMonthInfoJan, false, TimeHelpers.nowMillis())
+    val userState = doFullMonthlyBilling(clog, BillingMonthInfoJan, BillingMonthInfoJan.monthStopMillis)
 
     showUserState(clog, userState)
 
@@ -382,7 +350,7 @@ aquariumpolicy:
 
     showResourceEvents(clog)
 
-    val userState = doFullMonthlyBilling(clog, BillingMonthInfoJan, false, TimeHelpers.nowMillis())
+    val userState = doFullMonthlyBilling(clog, BillingMonthInfoJan, BillingMonthInfoJan.monthStopMillis)
 
     showUserState(clog, userState)
 
@@ -412,7 +380,7 @@ aquariumpolicy:
 
     showResourceEvents(clog)
 
-    val userState = doFullMonthlyBilling(clog, BillingMonthInfoJan, false, TimeHelpers.nowMillis())
+    val userState = doFullMonthlyBilling(clog, BillingMonthInfoJan, BillingMonthInfoJan.monthStopMillis)
 
     showUserState(clog, userState)
 
@@ -461,9 +429,9 @@ aquariumpolicy:
 
     // Policy: from 2012-01-01 to Infinity
 
-    clog.debugMap("DefaultResourcesMap", DefaultResourcesMap.map, 1)
+    clog.debugMap("DefaultResourcesMap", DefaultResourcesMap, 1)
 
-    val userState = doFullMonthlyBilling(clog, BillingMonthInfoJan, false, TimeHelpers.nowMillis())
+    val userState = doFullMonthlyBilling(clog, BillingMonthInfoJan, BillingMonthInfoJan.monthStopMillis)
 
     showUserState(clog, userState)