Flat project hierarchy
[aquarium] / src / test / scala / gr / grnet / aquarium / logic / test / DSLUtilsTest.scala
1 /*
2  * Copyright 2011 GRNET S.A. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or
5  * without modification, are permitted provided that the following
6  * conditions are met:
7  *
8  *   1. Redistributions of source code must retain the above
9  *      copyright notice, this list of conditions and the following
10  *      disclaimer.
11  *
12  *   2. Redistributions in binary form must reproduce the above
13  *      copyright notice, this list of conditions and the following
14  *      disclaimer in the documentation and/or other materials
15  *      provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
18  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
21  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
24  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  *
30  * The views and conclusions contained in the software and
31  * documentation are those of the authors and should not be
32  * interpreted as representing official policies, either expressed
33  * or implied, of GRNET S.A.
34  */
35
36 package gr.grnet.aquarium.logic.test
37
38 import org.junit.Test
39 import org.junit.Assert._
40 import gr.grnet.aquarium.util.TestMethods
41 import gr.grnet.aquarium.logic.accounting.dsl._
42 import annotation.tailrec
43 import java.util.Date
44
45 class DSLUtilsTest extends DSLTestBase with DSLUtils with TestMethods {
46
47   @Test
48   def testExpandTimeSpec = {
49     val from =  new Date(1321621969000L) //Fri Nov 18 15:12:49 +0200 2011
50     val to =  new Date(1324214719000L)   //Sun Dec 18 15:25:19 +0200 2011
51
52     var a = DSLTimeSpec(33, 12, -1, -1, 3)
53     var result = expandTimeSpec(a, from, to)
54     assertEquals(4, result.size)
55
56     a = DSLTimeSpec(33, 12, -1, 10, 3)   // Timespec falling outside from-to
57     result = expandTimeSpec(a, from, to)
58     assertEquals(0, result.size)
59
60     // Would only return an entry if the 1rst of Dec 2011 is Thursday
61     a = DSLTimeSpec(33, 12, 1, -1, 3)
62     result = expandTimeSpec(a, from, to)
63     assertEquals(0, result.size)
64
65     // The 9th of Dec 2011 is Friday
66     a = DSLTimeSpec(33, 12, 9, -1, 5)
67     result = expandTimeSpec(a, from, to)
68     assertEquals(1, result.size)
69
70     // Every day
71     a = DSLTimeSpec(33, 12, -1, -1, -1)
72     result = expandTimeSpec(a, from, to)
73     assertEquals(31, result.size)
74   }
75
76   @Test
77   def testExpandTimeSpecs = {
78     val from =  new Date(1321621969000L) //Fri Nov 18 15:12:49 +0200 2011
79     val to =  new Date(1324214719000L)   //Sun Dec 18 15:25:19 +0200 2011
80
81     val a = DSLTimeSpec(33, 12, -1, -1, 3)
82     var result = expandTimeSpecs(List(a), from, to)
83     assertNotEmpty(result)
84     assertEquals(4, result.size)
85
86     val b = DSLTimeSpec(00, 18, -1, -1, -1)
87     result = expandTimeSpecs(List(a,b), from, to)
88     assertNotEmpty(result)
89     assertEquals(34, result.size)
90   }
91
92   @Test
93   def testMergeOverlaps = {
94     var l = List(Timeslot(new Date(12345000), new Date(13345000)),
95       Timeslot(new Date(12845000), new Date(13845000)))
96
97     var result = mergeOverlaps(l)
98     assertEquals(1, result.size)
99     assertEquals(Timeslot(new Date(12345000), new Date(13845000)), result.head)
100
101     l = l ++ List(Timeslot(new Date(13645000), new Date(14845000)))
102     result = mergeOverlaps(l)
103     assertEquals(1, result.size)
104     assertEquals(Timeslot(new Date(12345000), new Date(14845000)), result.head)
105
106     l = l ++ List(Timeslot(new Date(15845000), new Date(16845000)))
107     result = mergeOverlaps(l)
108     assertEquals(2, result.size)
109     assertEquals(Timeslot(new Date(12345000), new Date(14845000)), result.head)
110     assertEquals(Timeslot(new Date(15845000), new Date(16845000)), result.tail.head)
111   }
112
113   @Test
114   def testEffectiveTimeslots = {
115     val from =  new Date(1321621969000L) //Fri Nov 18 15:12:49 +0200 2011
116     val to =  new Date(1324214719000L)   //Sun Dec 18 15:25:19 +0200 2011
117
118     var repeat = DSLTimeFrameRepeat(parseCronString("00 12 * * *"),
119       parseCronString("00 14 * * *"))
120
121     var result = effectiveTimeslots(repeat, from, Some(to))
122
123     assertNotEmpty(result)
124     testSuccessiveTimeslots(result)
125     assertEquals(31, result.size)
126
127     //Expansion outside timeframe
128     repeat = DSLTimeFrameRepeat(parseCronString("00 12 * May *"),
129       parseCronString("00 14 * Sep *"))
130     result = effectiveTimeslots(repeat, from, Some(to))
131     assertEquals(0, result.size)
132
133     repeat = DSLTimeFrameRepeat(parseCronString("00 12 * * 5"),
134       parseCronString("00 14 * * 1"))
135     result = effectiveTimeslots(repeat, from, Some(to))
136     testSuccessiveTimeslots(result)
137     assertEquals(4, result.size)
138
139     repeat = DSLTimeFrameRepeat(parseCronString("00 12 * * Mon,Wed,Fri"),
140       parseCronString("00 14 * * Tue,Thu,Sat"))
141     result = effectiveTimeslots(repeat, from, Some(to))
142     testSuccessiveTimeslots(result)
143     assertEquals(13, result.size)
144
145     repeat = DSLTimeFrameRepeat(parseCronString("00 00 * May *"),
146       parseCronString("59 23 * Sep *"))
147     result = effectiveTimeslots(repeat, new Date(1304121600000L),
148       Some(new Date(1319932800000L)))
149     assertNotEmpty(result)
150   }
151
152   @Test
153   def testAllEffectiveTimeslots = {
154     var from = new Date(1321621969000L) //Fri Nov 18 15:12:49 +0200 2011
155     val to =  new Date(1324214719000L)   //Sun Dec 18 15:25:19 +0200 2011
156
157     val repeat1 = DSLTimeFrameRepeat(parseCronString("00 12 * * *"),
158       parseCronString("00 14 * * *"))
159     val repeat2 = DSLTimeFrameRepeat(parseCronString("00 18 * * 5"),
160       parseCronString("00 20 * * 5"))
161     val tf = DSLTimeFrame(from, None, List(repeat1, repeat2))
162
163     var result = allEffectiveTimeslots(tf, from, to)
164     assertEquals(36, result.size)
165     testSuccessiveTimeslots(result)
166
167     result = allEffectiveTimeslots(DSLTimeFrame(new Date(0), None, List()),
168       new Date(14), new Date(40))
169     assertEquals(1, result.size)
170   }
171
172   @Test
173   def testNonEffectiveTimeslots = {
174     val from =  new Date(1321621969000L) //Fri Nov 18 15:12:49 +0200 2011
175     val to =  new Date(1324214719000L)   //Sun Dec 18 15:25:19 +0200 2011
176
177     var repeat = DSLTimeFrameRepeat(parseCronString("00 12 * * *"),
178       parseCronString("00 14 * * *"))
179
180     var result = ineffectiveTimeslots(repeat, from, Some(to))
181     assertEquals(30, result.size)
182     testSuccessiveTimeslots(result)
183     //printTimeslots(result)
184   }
185
186   @Test
187   def testTimeContinuum : Unit = {
188     val from =  new Date(1321621969000L) //Fri Nov 18 15:12:49 +0200 2011
189     val to =  new Date(1324214719000L)   //Sun Dec 18 15:25:19 +0200 2011
190
191     var repeat = DSLTimeFrameRepeat(parseCronString("00 12 * * *"),
192       parseCronString("00 14 * * *"))
193
194     val continuum = effectiveTimeslots(repeat, from, Some(to)) ++
195       ineffectiveTimeslots(repeat, from, Some(to)) sortWith sorter
196
197     testSuccessiveTimeslots(continuum)
198
199     continuum.reduce {
200       (a,b) =>
201         if(a.to.getTime - b.from.getTime > 1)
202           fail("Effectivity timeslots leave gaps: %s %s".format(a, b))
203         a
204     }
205     return
206   }
207
208   @Test
209   def testFindEffective = {
210     before
211     val agr = creditpolicy.findAgreement("scaledbandwidth").get
212
213     val ts1 = 1322649482000L //Wed, 30 Nov 2011 12:38:02 EET
214     val ts2 = 1322656682000L //Wed, 30 Nov 2011 14:38:02 EET
215     val ts3 = 1322660282000L //Wed, 30 Nov 2011 15:38:02 EET
216     val ts4 = 1322667482000L //Wed, 30 Nov 2011 17:38:02 EET
217     val ts5 = 1322689082000L //Wed, 30 Nov 2011 23:38:02 EET
218     val ts6 = 1322555880000L //Tue, 29 Nov 2011 10:38:00 EET
219
220     var pricelists = resolveEffectivePricelistsForTimeslot(Timeslot(new Date(ts1), new Date(ts2)), agr)
221     assertEquals(2, pricelists.keySet.size)
222     assertNotNone(pricelists.get(new Timeslot(new Date(1322654402000L), new Date(1322656682000L))))
223     assertEquals("foobar", pricelists.head._2.name)
224
225     pricelists = resolveEffectivePricelistsForTimeslot(Timeslot(new Date(ts2), new Date(ts3)), agr)
226     assertEquals(1, pricelists.keySet.size)
227     assertEquals("default", pricelists.head._2.name)
228
229     pricelists = resolveEffectivePricelistsForTimeslot(Timeslot(new Date(ts1), new Date(ts4)), agr)
230     assertEquals(2, pricelists.keySet.size)
231     assertEquals("foobar", pricelists.head._2.name)
232     assertEquals("default", pricelists.tail.head._2.name)
233
234     pricelists = resolveEffectivePricelistsForTimeslot(Timeslot(new Date(ts1), new Date(ts5)), agr)
235     assertEquals(4, pricelists.keySet.size)
236
237     pricelists = resolveEffectivePricelistsForTimeslot(Timeslot(new Date(ts6), new Date(ts5)), agr)
238     assertEquals(9, pricelists.keySet.size)
239   }
240
241   @tailrec
242   private def testSuccessiveTimeslots(result: List[Timeslot]): Unit = {
243     if (result.isEmpty) return
244     if (result.tail.isEmpty) return
245     if (result.head.to.after(result.tail.head.from))
246       fail("Effectivity timeslots not successive: %s %s".format(result.head, result.tail.head))
247     testSuccessiveTimeslots(result.tail)
248   }
249
250   private def printTimeslots(result: List[Timeslot]) = {
251     result.foreach(p => print("from:%s to:%s\n".format(p.from, p.to)))
252   }
253 }