51259c359f76d57aed0dbde390e5569a8b242008
[aquarium] / src / test / scala / gr / grnet / aquarium / user / UserStateComputationsTest.scala
1 package gr.grnet.aquarium.user
2
3 import org.junit.Test
4 import gr.grnet.aquarium.Configurator
5 import gr.grnet.aquarium.store.memory.MemStore
6 import gr.grnet.aquarium.util.date.DateCalculator
7 import gr.grnet.aquarium.logic.accounting.dsl._
8 import java.util.Date
9 import gr.grnet.aquarium.logic.accounting.Accounting
10 import com.ckkloverdos.maybe.NoVal
11 import simulation.{ConcurrentVMLocalUIDGenerator, ClientServiceSim, UserSim}
12
13
14 /**
15  *
16  * @author Christos KK Loverdos <loverdos@gmail.com>
17  */
18 class UserStateComputationsTest {
19   @Test
20   def testOne: Unit = {
21     val START_YEAR = 2012
22     val START_MONTH = 1
23     val START_DAY = 15
24
25     val START_OF_YEAR_DATECALC = new DateCalculator(START_YEAR, 1, 1)
26
27     // TODO: integrate this with the rest of the simulation stuff
28     // TODO: since, right now, the resource strings have to be given twice
29     val VMTIME_RESOURCE    = DSLComplexResource("vmtime",    "Hr",    OnOffCostPolicy,      "")
30     val DISKSPACE_RESOURCE = DSLComplexResource("diskspace", "MB/Hr", ContinuousCostPolicy, "")
31
32     val DEFAULT_RESOURCES_MAP = new DSLResourcesMap(VMTIME_RESOURCE :: DISKSPACE_RESOURCE :: Nil)
33
34     val FOR_EVER = DSLTimeFrame(new Date(0), None, Nil)
35     val THE_PRICES_MAP: Map[DSLResource, Double] = Map(VMTIME_RESOURCE -> 1.0, DISKSPACE_RESOURCE -> 1.0)
36
37     val THE_PRICE_LIST  = DSLPriceList("default", None, THE_PRICES_MAP, FOR_EVER)
38     val THE_CREDIT_PLAN = DSLCreditPlan("default", None, 100, Nil, "", FOR_EVER)
39     val THE_ALGORITHM   = DSLAlgorithm("default", None, Map(), FOR_EVER)
40     val THE_AGREEMENT   = DSLAgreement("default", None, THE_ALGORITHM, THE_PRICE_LIST, THE_CREDIT_PLAN)
41
42     val THE_RESOURCES = DEFAULT_RESOURCES_MAP.toResourcesList
43
44     val DEFAULT_POLICY = DSLPolicy(
45       Nil,
46       THE_PRICE_LIST :: Nil,
47       THE_RESOURCES,
48       THE_CREDIT_PLAN :: Nil,
49       THE_AGREEMENT :: Nil
50     )
51
52     val computer = new UserStateComputations
53
54     val userPolicyFinder = new UserPolicyFinder {
55       def findUserPolicyAt(userId: String, whenMillis: Long) = DEFAULT_POLICY
56     }
57
58     val fullStateFinder = new FullStateFinder {
59       def findFullState(userId: String, whenMillis: Long) = null
60     }
61
62     val userStateCache = new UserStateCache {
63       def findUserStateAtEndOfPeriod(userId: String, year: Int, month: Int) = NoVal
64
65       def findLatestUserStateForEndOfBillingMonth(userId: String, yearOfBillingMonth: Int, billingMonth: Int) = NoVal
66     }
67
68     val mc = Configurator.MasterConfigurator.withStoreProviderClass(classOf[MemStore])
69     val storeProvider = mc.storeProvider
70     val resourceEventStore = storeProvider.resourceEventStore
71 //    println("!! storeProvider = %s".format(storeProvider))
72
73     // A new user is created on 2012-01-15 00:00:00.000
74     val USER_START_DATECALC = new DateCalculator(START_YEAR, START_MONTH, START_DAY)
75     val christos  = UserSim("Christos", USER_START_DATECALC.toDate, storeProvider.resourceEventStore)
76
77     // There are two client services, synnefo and pithos.
78     val uidGenerator = new ConcurrentVMLocalUIDGenerator
79     val synnefo = ClientServiceSim("synnefo")(uidGenerator)
80     val pithos  = ClientServiceSim("pithos")(uidGenerator)
81
82     // By convention
83     // - synnefo is for VMTime and
84     // - pithos is for Diskspace
85     val vm   = synnefo.newVMTime(christos, "VM.1")
86     val disk = pithos.newDiskspace(christos, "DISK.1")
87
88     // Let's create our dates of interest
89     val vmStartDateCalc = USER_START_DATECALC.copy.goPlusDays(1).goPlusHours(1)
90     // 2012-01-16 01:00:00.000
91     val vmStartDate = vmStartDateCalc.toDate
92
93     // Within January, create one VM ON-OFF ...
94     val onOff1_M = vm.newONOFF(vmStartDate, 9)
95
96     val diskConsumptionDateCalc = USER_START_DATECALC.copy.goPlusHours(3)
97     // 2012-01-16 04:00:00.000
98     val diskConsumptionDate1 = diskConsumptionDateCalc.toDate
99     // 2012-01-17 05:00:00.000
100     val diskConsumptionDate2 = diskConsumptionDateCalc.copy.goPlusDays(1).goPlusHours(1).toDate
101
102     // ... and two diskspace changes
103     val consume1_M = disk.consumeMB(diskConsumptionDate1, 99)
104     val consume2_M = disk.consumeMB(diskConsumptionDate2, 23)
105
106     // ... and one "future" event
107     // 2012-02-07 07:07:07.007
108     disk.consumeMB(
109       START_OF_YEAR_DATECALC.copy.
110         goNextMonth.goPlusDays(6).
111         goPlusHours(7).
112         goPlusMinutes(7).
113         goPlusSeconds(7).
114         goPlusMillis(7).toDate,
115       777)
116
117     println("=============================")
118     for {
119       event <- christos.myResourceEventsByReceivedDate
120     } {
121       val when = new DateCalculator(event.receivedMillis)
122       val resource  = event.resource
123       val instanceId = event.instanceId
124       val value = event.beautifyValue(DEFAULT_RESOURCES_MAP)
125       println("%s [%s, %s] %s".format(when, resource, instanceId, value))
126     }
127     println("=============================")
128
129     val billing = computer.computeFullMonthlyBilling(
130       START_YEAR,
131       START_MONTH,
132       christos.userId,
133       userPolicyFinder,
134       fullStateFinder,
135       userStateCache,
136       resourceEventStore,
137       computer.createFirstUserState(christos.userId),
138       Nil,
139       DEFAULT_POLICY,
140       DEFAULT_RESOURCES_MAP,
141       new Accounting{}
142     )
143     
144     println("!! billing = %s".format(billing))
145   }
146 }