8d607be3270479d4fc0a0c52376603d99ac57be1
[aquarium] / src / test / scala / gr / grnet / aquarium / BillTest.scala
1 package gr.grnet.aquarium
2
3 import com.ckkloverdos.resource.FileStreamResource
4 import converter.StdConverters
5 import event.model.im.StdIMEvent
6 import event.model.resource.StdResourceEvent
7 import java.io.{InputStreamReader, BufferedReader, File}
8 import com.ckkloverdos.props.Props
9 import store.memory.MemStoreProvider
10 import java.util.concurrent.atomic.AtomicLong
11 import java.text.SimpleDateFormat
12 import java.net.{URLConnection, URL}
13 import util.Loggable
14
15 /*
16 * Copyright 2011-2012 GRNET S.A. All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or
19 * without modification, are permitted provided that the following
20 * conditions are met:
21 *
22 *   1. Redistributions of source code must retain the above
23 *      copyright notice, this list of conditions and the following
24 *      disclaimer.
25 *
26 *   2. Redistributions in binary form must reproduce the above
27 *      copyright notice, this list of conditions and the following
28 *      disclaimer in the documentation and/or other materials
29 *      provided with the distribution.
30 *
31 * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
32 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
33 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
34 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
35 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
36 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
37 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
38 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
39 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
40 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
41 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGE.
43 *
44 * The views and conclusions contained in the software and
45 * documentation are those of the authors and should not be
46 * interpreted as representing official policies, either expressed
47 * or implied, of GRNET S.A.
48 */
49
50
51 /*
52 * @author Prodromos Gerakios <pgerakios@grnet.gr>
53 */
54 object BillTest extends Loggable {
55
56   type JSON = String
57   type UID  = Long
58   type DATE = String
59
60   private[this] val counter = new AtomicLong(0L)
61   private[this] def nextID() = counter.getAndIncrement
62
63   private [this] val format = new SimpleDateFormat("HH/mm/s/dd/MM/yyyy");
64
65   val propsfile = new FileStreamResource(new File("aquarium.properties"))
66
67   var props: Props = Props(propsfile)(StdConverters.AllConverters).getOr(Props()(StdConverters.AllConverters))
68
69   val (astakosExchangeName,astakosRoutingKey) = ("astakos","astakos.user")
70
71   val (pithosExchangeName,pithosRoutingKey) = ("pithos","pithos.resource.diskspace")
72
73   val aquarium = {
74       exec("mongo aquarium --eval db.resevents.remove();db.imevents.remove();db.policies.remove();db.userstates.remove()",
75            Console.err.println(_))
76       new AquariumBuilder(props, ResourceLocator.DefaultPolicyModel).
77       //update(Aquarium.EnvKeys.storeProvider, new MemStoreProvider).
78       update(Aquarium.EnvKeys.eventsStoreFolder,Some(new File(".."))).
79       build()
80   }
81
82
83   private[this] def exec(cmd : String,func : String=>Unit) : Unit = {
84     val commands = cmd.split(" ")
85     val proc = new ProcessBuilder(commands: _*).redirectErrorStream(true).start();
86     val ins = new java.io.BufferedReader(new java.io.InputStreamReader(proc.getInputStream))
87     val sb = new StringBuilder
88
89     //spin off a thread to read process output.
90     val outputReaderThread = new Thread(new Runnable(){
91       def run : Unit = {
92         var ln : String = null
93         while({ln = ins.readLine; ln != null})
94           func(ln)
95       }
96     })
97     outputReaderThread.start()
98
99     //suspense this main thread until sub process is done.
100     proc.waitFor
101
102     //wait until output is fully read/completed.
103     outputReaderThread.join()
104
105     ins.close()
106   }
107
108
109   private [this] def createUser(date:DATE) : (JSON,UID) = {
110     val mid = nextID
111     val id = "im.%d.create.user".format(mid)
112     val millis = format.parse(date).getTime
113     val occurredMillis = millis
114     val receivedMillis = millis
115     val userID = "user%d@grnet.gr".format(mid)
116     val clientID = "astakos"
117     val isActive = false
118     val role = "default"
119     val eventVersion = "1.0"
120     val eventType = "create"
121     (new StdIMEvent(id,occurredMillis,receivedMillis,userID,
122                    clientID,isActive,role,eventVersion,eventType,
123                    Map()).toJsonString,mid)
124   }
125
126   private [this] def addCredits(date:DATE,uid:UID,amount:Long) : JSON = {
127     val id = "im.%d.add.credits".format(nextID)
128     val millis = format.parse(date).getTime
129     val occurredMillis = millis
130     val receivedMillis = millis
131     val userID = "user%d@grnet.gr".format(uid)
132     val clientID = "astakos"
133     val isActive = false
134     val role = "default"
135     val eventVersion = "1.0"
136     val eventType = "addcredits"
137     new StdIMEvent(id,occurredMillis,receivedMillis,userID,
138                    clientID,isActive,role,eventVersion,eventType,
139                    Map("credits" -> amount.toString)).toJsonString
140   }
141
142   private [this] def makePithos(date:DATE,uid:UID,path:String,
143                                 value:Double,action:String) : JSON = {
144     val id = "rc.%d.object.%s".format(nextID,action)
145     val millis = format.parse(date).getTime
146     val occurredMillis = millis
147     val receivedMillis = millis
148     val userID = "user%d@grnet.gr".format(uid)
149     val clientID = "pithos"
150     val resource ="diskspace"
151     val instanceID = "1"
152     val eventVersion = "1.0"
153     val details = Map("action" -> "object %s".format(action),
154                       "total"  -> "0.0",
155                       "user"   -> userID,
156                       "path"   -> path)
157     new StdResourceEvent(id,occurredMillis,receivedMillis,userID,clientID,
158                          resource,instanceID,value,eventVersion,details).toJsonString
159   }
160
161   private[this] def sendCreate(date:DATE) : UID = {
162     val (json,uid) = createUser(date)
163     aquarium(Aquarium.EnvKeys.rabbitMQProducer).
164     sendMessage(astakosExchangeName,astakosRoutingKey,json)
165     Console.err.println("Sent message:\n%s\n".format(json))
166     uid
167   }
168
169   private[this] def sendAddCredits(date:DATE,uid:UID,amount:Long) = {
170     val json = addCredits(date,uid,amount)
171     aquarium(Aquarium.EnvKeys.rabbitMQProducer).
172     sendMessage(astakosExchangeName,astakosRoutingKey,
173                 json)
174     Console.err.println("Sent message:\n%s\n".format(json))
175   }
176
177   private[this] def sendPithos(date:DATE,uid:UID,path:String,
178                                value:Double,action:String) = {
179     val json = makePithos(date,uid,path,value,action)
180     aquarium(Aquarium.EnvKeys.rabbitMQProducer).
181     sendMessage(pithosExchangeName,pithosRoutingKey,
182                 json)
183     Console.err.println("Sent message:\n%s\n".format(json))
184   }
185
186   private[this] def jsonOf(url:String) : JSON = {
187      val in = new BufferedReader(
188                          new InputStreamReader(
189                          new URL(url).openConnection().
190                          getInputStream()))
191       var inputLine = ""
192       var ret = ""
193       while ({inputLine = in.readLine();inputLine} != null)
194         ret += (if(ret.isEmpty) "" else "\n")+ inputLine
195       in.close()
196       ret
197   }
198
199   private[this] def getBill(uid:Long,from:String,to:String) : JSON = {
200     val fromMillis = format.parse(from).getTime
201     val toMillis   = format.parse(to).getTime
202     val billURL = " http://localhost:8888/user/user%d@grnet.gr/bill/%d/%d".format(uid,fromMillis,toMillis)
203     try{
204       jsonOf(billURL)
205     } catch {
206       case e:Exception =>
207         ""
208     }
209   }
210
211   private[this] def sleep(l:Long) = {
212   try {
213       Thread.sleep(l)
214     } catch {
215       case ex:InterruptedException =>
216         Thread.currentThread().interrupt()
217     }
218   }
219
220   private[this] def testCase1() : JSON  = {
221     /* GET BILL FROM TO*/
222     val billFromDate = "00/00/00/01/08/2012"
223     val billToDate= "23/59/59/31/08/2012"
224     /* USER Creation */
225     val creationDate = "15/00/00/03/08/2012"
226     /* ADD CREDITS */
227     val addCreditsDate = "18/15/00/05/08/2012"
228     val creditsToAdd = 6000
229     /* Pithos STUFF */
230     val pithosPath = "/Papers/GOTO_HARMFUL.PDF"
231
232     val pithosDate1 = "20/30/00/05/08/2012"
233     val pithosAction1 = "update"
234     val pithosValue1 = 2000
235
236
237     val pithosDate2 = "21/05/00/15/08/2012"
238     val pithosAction2 = "update"
239     val pithosValue2 = 4000
240
241
242     val pithosDate3 = "08/05/00/20/08/2012"
243     val pithosAction3 = "update"
244     val pithosValue3 = 100
245
246     val id =
247       sendCreate(creationDate)
248       //Thread.sleep(5000)
249       sendAddCredits(addCreditsDate,id,creditsToAdd)
250       //Thread.sleep(5000)
251       sendPithos(pithosDate1,id,pithosPath,pithosValue1,pithosAction1)
252       //Thread.sleep(5000)
253       sendPithos(pithosDate2,id,pithosPath,pithosValue2,pithosAction2)
254       //
255       sendPithos(pithosDate3,id,pithosPath,pithosValue3,pithosAction3)
256
257
258     Console.err.println("Waiting for stuff to be processed")
259     Thread.sleep(5000)
260
261     var resp = ""
262     var count = 0
263     while(resp.isEmpty && count < 5){
264       if(count > 0) Console.err.println("Retrying for bill request.")
265       resp = getBill(id,billFromDate,billToDate)
266       if(resp.isEmpty) Thread.sleep(1000)
267       //sleep(1000L)
268       count += 1
269     }
270     Console.err.println("Sending URL done")
271     resp
272   }
273
274   def runTestCase(f: => JSON) = {
275     var json = ""
276     aquarium.start
277     Thread.sleep(2000)
278     try{
279       json = f
280     }  catch{
281       case e:Exception =>
282         e.printStackTrace
283     }
284     aquarium.stop
285     Thread.sleep(1000)
286     Console.err.println("Response : " + json )
287   }
288
289   def main(args: Array[String]) = {
290     //Console.err.println("JSON: " +  (new BillEntry).toJsonString)
291     runTestCase(testCase1)
292   }
293 }