1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.calendarcommon2;
18 
19 import com.android.calendarcommon2.EventRecurrence.InvalidFormatException;
20 
21 import android.test.suitebuilder.annotation.SmallTest;
22 import android.test.suitebuilder.annotation.Suppress;
23 
24 import junit.framework.TestCase;
25 
26 import java.util.Arrays;
27 
28 /**
29  * Test android.pim.EventRecurrence.
30  *
31  * adb shell am instrument -w -e class com.android.calendarcommon2.EventRecurrenceTest \
32  *   com.android.calendarcommon2.tests/android.test.InstrumentationTestRunner
33  */
34 public class EventRecurrenceTest extends TestCase {
35 
36     @SmallTest
test0()37     public void test0() throws Exception {
38         verifyRecurType("FREQ=SECONDLY",
39                 /* int freq */         EventRecurrence.SECONDLY,
40                 /* String until */     null,
41                 /* int count */        0,
42                 /* int interval */     0,
43                 /* int[] bysecond */   null,
44                 /* int[] byminute */   null,
45                 /* int[] byhour */     null,
46                 /* int[] byday */      null,
47                 /* int[] bydayNum */   null,
48                 /* int[] bymonthday */ null,
49                 /* int[] byyearday */  null,
50                 /* int[] byweekno */   null,
51                 /* int[] bymonth */    null,
52                 /* int[] bysetpos */   null,
53                 /* int wkst */         EventRecurrence.MO
54         );
55     }
56 
57     @SmallTest
test1()58     public void test1() throws Exception {
59         verifyRecurType("FREQ=MINUTELY",
60                 /* int freq */         EventRecurrence.MINUTELY,
61                 /* String until */     null,
62                 /* int count */        0,
63                 /* int interval */     0,
64                 /* int[] bysecond */   null,
65                 /* int[] byminute */   null,
66                 /* int[] byhour */     null,
67                 /* int[] byday */      null,
68                 /* int[] bydayNum */   null,
69                 /* int[] bymonthday */ null,
70                 /* int[] byyearday */  null,
71                 /* int[] byweekno */   null,
72                 /* int[] bymonth */    null,
73                 /* int[] bysetpos */   null,
74                 /* int wkst */         EventRecurrence.MO
75         );
76     }
77 
78     @SmallTest
test2()79     public void test2() throws Exception {
80         verifyRecurType("FREQ=HOURLY",
81                 /* int freq */         EventRecurrence.HOURLY,
82                 /* String until */     null,
83                 /* int count */        0,
84                 /* int interval */     0,
85                 /* int[] bysecond */   null,
86                 /* int[] byminute */   null,
87                 /* int[] byhour */     null,
88                 /* int[] byday */      null,
89                 /* int[] bydayNum */   null,
90                 /* int[] bymonthday */ null,
91                 /* int[] byyearday */  null,
92                 /* int[] byweekno */   null,
93                 /* int[] bymonth */    null,
94                 /* int[] bysetpos */   null,
95                 /* int wkst */         EventRecurrence.MO
96         );
97     }
98 
99     @SmallTest
test3()100     public void test3() throws Exception {
101         verifyRecurType("FREQ=DAILY",
102                 /* int freq */         EventRecurrence.DAILY,
103                 /* String until */     null,
104                 /* int count */        0,
105                 /* int interval */     0,
106                 /* int[] bysecond */   null,
107                 /* int[] byminute */   null,
108                 /* int[] byhour */     null,
109                 /* int[] byday */      null,
110                 /* int[] bydayNum */   null,
111                 /* int[] bymonthday */ null,
112                 /* int[] byyearday */  null,
113                 /* int[] byweekno */   null,
114                 /* int[] bymonth */    null,
115                 /* int[] bysetpos */   null,
116                 /* int wkst */         EventRecurrence.MO
117         );
118     }
119 
120     @SmallTest
test4()121     public void test4() throws Exception {
122         verifyRecurType("FREQ=WEEKLY",
123                 /* int freq */         EventRecurrence.WEEKLY,
124                 /* String until */     null,
125                 /* int count */        0,
126                 /* int interval */     0,
127                 /* int[] bysecond */   null,
128                 /* int[] byminute */   null,
129                 /* int[] byhour */     null,
130                 /* int[] byday */      null,
131                 /* int[] bydayNum */   null,
132                 /* int[] bymonthday */ null,
133                 /* int[] byyearday */  null,
134                 /* int[] byweekno */   null,
135                 /* int[] bymonth */    null,
136                 /* int[] bysetpos */   null,
137                 /* int wkst */         EventRecurrence.MO
138         );
139     }
140 
141     @SmallTest
test5()142     public void test5() throws Exception {
143         verifyRecurType("FREQ=MONTHLY",
144                 /* int freq */         EventRecurrence.MONTHLY,
145                 /* String until */     null,
146                 /* int count */        0,
147                 /* int interval */     0,
148                 /* int[] bysecond */   null,
149                 /* int[] byminute */   null,
150                 /* int[] byhour */     null,
151                 /* int[] byday */      null,
152                 /* int[] bydayNum */   null,
153                 /* int[] bymonthday */ null,
154                 /* int[] byyearday */  null,
155                 /* int[] byweekno */   null,
156                 /* int[] bymonth */    null,
157                 /* int[] bysetpos */   null,
158                 /* int wkst */         EventRecurrence.MO
159         );
160     }
161 
162     @SmallTest
test6()163     public void test6() throws Exception {
164         verifyRecurType("FREQ=YEARLY",
165                 /* int freq */         EventRecurrence.YEARLY,
166                 /* String until */     null,
167                 /* int count */        0,
168                 /* int interval */     0,
169                 /* int[] bysecond */   null,
170                 /* int[] byminute */   null,
171                 /* int[] byhour */     null,
172                 /* int[] byday */      null,
173                 /* int[] bydayNum */   null,
174                 /* int[] bymonthday */ null,
175                 /* int[] byyearday */  null,
176                 /* int[] byweekno */   null,
177                 /* int[] bymonth */    null,
178                 /* int[] bysetpos */   null,
179                 /* int wkst */         EventRecurrence.MO
180         );
181     }
182 
183     @SmallTest
test7()184     public void test7() throws Exception {
185         // with an until
186         verifyRecurType("FREQ=DAILY;UNTIL=112233T223344Z",
187                 /* int freq */         EventRecurrence.DAILY,
188                 /* String until */     "112233T223344Z",
189                 /* int count */        0,
190                 /* int interval */     0,
191                 /* int[] bysecond */   null,
192                 /* int[] byminute */   null,
193                 /* int[] byhour */     null,
194                 /* int[] byday */      null,
195                 /* int[] bydayNum */   null,
196                 /* int[] bymonthday */ null,
197                 /* int[] byyearday */  null,
198                 /* int[] byweekno */   null,
199                 /* int[] bymonth */    null,
200                 /* int[] bysetpos */   null,
201                 /* int wkst */         EventRecurrence.MO
202         );
203     }
204 
205     @SmallTest
test8()206     public void test8() throws Exception {
207         // with a count
208         verifyRecurType("FREQ=DAILY;COUNT=334",
209                 /* int freq */         EventRecurrence.DAILY,
210                 /* String until */     null,
211                 /* int count */        334,
212                 /* int interval */     0,
213                 /* int[] bysecond */   null,
214                 /* int[] byminute */   null,
215                 /* int[] byhour */     null,
216                 /* int[] byday */      null,
217                 /* int[] bydayNum */   null,
218                 /* int[] bymonthday */ null,
219                 /* int[] byyearday */  null,
220                 /* int[] byweekno */   null,
221                 /* int[] bymonth */    null,
222                 /* int[] bysetpos */   null,
223                 /* int wkst */         EventRecurrence.MO
224         );
225     }
226 
227     @SmallTest
test9()228     public void test9() throws Exception {
229         // with a count
230         verifyRecurType("FREQ=DAILY;INTERVAL=5000",
231                 /* int freq */         EventRecurrence.DAILY,
232                 /* String until */     null,
233                 /* int count */        0,
234                 /* int interval */     5000,
235                 /* int[] bysecond */   null,
236                 /* int[] byminute */   null,
237                 /* int[] byhour */     null,
238                 /* int[] byday */      null,
239                 /* int[] bydayNum */   null,
240                 /* int[] bymonthday */ null,
241                 /* int[] byyearday */  null,
242                 /* int[] byweekno */   null,
243                 /* int[] bymonth */    null,
244                 /* int[] bysetpos */   null,
245                 /* int wkst */         EventRecurrence.MO
246         );
247     }
248 
249     @SmallTest
test10()250     public void test10() throws Exception {
251         // verifyRecurType all of the BY* ones with one element
252         verifyRecurType("FREQ=DAILY"
253                 + ";BYSECOND=0"
254                 + ";BYMINUTE=1"
255                 + ";BYHOUR=2"
256                 + ";BYMONTHDAY=30"
257                 + ";BYYEARDAY=300"
258                 + ";BYWEEKNO=53"
259                 + ";BYMONTH=12"
260                 + ";BYSETPOS=-15"
261                 + ";WKST=SU",
262                 /* int freq */         EventRecurrence.DAILY,
263                 /* String until */     null,
264                 /* int count */        0,
265                 /* int interval */     0,
266                 /* int[] bysecond */   new int[]{0},
267                 /* int[] byminute */   new int[]{1},
268                 /* int[] byhour */     new int[]{2},
269                 /* int[] byday */      null,
270                 /* int[] bydayNum */   null,
271                 /* int[] bymonthday */ new int[]{30},
272                 /* int[] byyearday */  new int[]{300},
273                 /* int[] byweekno */   new int[]{53},
274                 /* int[] bymonth */    new int[]{12},
275                 /* int[] bysetpos */   new int[]{-15},
276                 /* int wkst */         EventRecurrence.SU
277         );
278     }
279 
280     @SmallTest
test11()281     public void test11() throws Exception {
282         // verifyRecurType all of the BY* ones with one element
283         verifyRecurType("FREQ=DAILY"
284                 + ";BYSECOND=0,30,59"
285                 + ";BYMINUTE=0,41,59"
286                 + ";BYHOUR=0,4,23"
287                 + ";BYMONTHDAY=-31,-1,1,31"
288                 + ";BYYEARDAY=-366,-1,1,366"
289                 + ";BYWEEKNO=-53,-1,1,53"
290                 + ";BYMONTH=1,12"
291                 + ";BYSETPOS=1,2,3,4,500,10000"
292                 + ";WKST=SU",
293                 /* int freq */         EventRecurrence.DAILY,
294                 /* String until */     null,
295                 /* int count */        0,
296                 /* int interval */     0,
297                 /* int[] bysecond */   new int[]{0, 30, 59},
298                 /* int[] byminute */   new int[]{0, 41, 59},
299                 /* int[] byhour */     new int[]{0, 4, 23},
300                 /* int[] byday */      null,
301                 /* int[] bydayNum */   null,
302                 /* int[] bymonthday */ new int[]{-31, -1, 1, 31},
303                 /* int[] byyearday */  new int[]{-366, -1, 1, 366},
304                 /* int[] byweekno */   new int[]{-53, -1, 1, 53},
305                 /* int[] bymonth */    new int[]{1, 12},
306                 /* int[] bysetpos */   new int[]{1, 2, 3, 4, 500, 10000},
307                 /* int wkst */         EventRecurrence.SU
308         );
309     }
310 
311     private static class Check {
Check(String k, int... v)312         Check(String k, int... v) {
313             key = k;
314             values = v;
315         }
316 
317         String key;
318         int[] values;
319     }
320 
321     // this is a negative verifyRecurType case to verifyRecurType the range of the numbers accepted
322     @SmallTest
test12()323     public void test12() throws Exception {
324         Check[] checks = new Check[]{
325                 new Check("BYSECOND", -100, -1, 60, 100),
326                 new Check("BYMINUTE", -100, -1, 60, 100),
327                 new Check("BYHOUR", -100, -1, 24, 100),
328                 new Check("BYMONTHDAY", -100, -32, 0, 32, 100),
329                 new Check("BYYEARDAY", -400, -367, 0, 367, 400),
330                 new Check("BYWEEKNO", -100, -54, 0, 54, 100),
331                 new Check("BYMONTH", -100, -5, 0, 13, 100)
332         };
333 
334         for (Check ck : checks) {
335             for (int n : ck.values) {
336                 String recur = "FREQ=DAILY;" + ck.key + "=" + n;
337                 try {
338                     EventRecurrence er = new EventRecurrence();
339                     er.parse(recur);
340                     fail("Negative verifyRecurType failed. "
341                             + " parse failed to throw an exception for '"
342                             + recur + "'");
343                 } catch (EventRecurrence.InvalidFormatException e) {
344                     // expected
345                 }
346             }
347         }
348     }
349 
350     // verifyRecurType BYDAY
351     @SmallTest
test13()352     public void test13() throws Exception {
353         verifyRecurType("FREQ=DAILY;BYDAY=1SU,-2MO,+33TU,WE,TH,FR,SA",
354                 /* int freq */         EventRecurrence.DAILY,
355                 /* String until */     null,
356                 /* int count */        0,
357                 /* int interval */     0,
358                 /* int[] bysecond */   null,
359                 /* int[] byminute */   null,
360                 /* int[] byhour */     null,
361                 /* int[] byday */      new int[] {
362                         EventRecurrence.SU,
363                         EventRecurrence.MO,
364                         EventRecurrence.TU,
365                         EventRecurrence.WE,
366                         EventRecurrence.TH,
367                         EventRecurrence.FR,
368                         EventRecurrence.SA
369                 },
370                 /* int[] bydayNum */   new int[]{1, -2, 33, 0, 0, 0, 0},
371                 /* int[] bymonthday */ null,
372                 /* int[] byyearday */  null,
373                 /* int[] byweekno */   null,
374                 /* int[] bymonth */    null,
375                 /* int[] bysetpos */   null,
376                 /* int wkst */         EventRecurrence.MO
377         );
378     }
379 
380     @Suppress
381     // Repro bug #2331761 - this should fail because of the last comma into BYDAY
test14()382     public void test14() throws Exception {
383         verifyRecurType("FREQ=WEEKLY;WKST=MO;UNTIL=20100129T130000Z;INTERVAL=1;BYDAY=MO,TU,WE,",
384                 /* int freq */         EventRecurrence.WEEKLY,
385                 /* String until */     "20100129T130000Z",
386                 /* int count */        0,
387                 /* int interval */     1,
388                 /* int[] bysecond */   null,
389                 /* int[] byminute */   null,
390                 /* int[] byhour */     null,
391                 /* int[] byday */      new int[] {
392                         EventRecurrence.MO,
393                         EventRecurrence.TU,
394                         EventRecurrence.WE,
395                 },
396                 /* int[] bydayNum */   new int[]{0, 0, 0},
397                 /* int[] bymonthday */ null,
398                 /* int[] byyearday */  null,
399                 /* int[] byweekno */   null,
400                 /* int[] bymonth */    null,
401                 /* int[] bysetpos */   null,
402                 /* int wkst */         EventRecurrence.MO
403         );
404     }
405 
406     // This test should pass
test15()407     public void test15() throws Exception {
408         verifyRecurType("FREQ=WEEKLY;WKST=MO;UNTIL=20100129T130000Z;INTERVAL=1;"
409                 + "BYDAY=MO,TU,WE,TH,FR,SA,SU",
410                 /* int freq */         EventRecurrence.WEEKLY,
411                 /* String until */     "20100129T130000Z",
412                 /* int count */        0,
413                 /* int interval */     1,
414                 /* int[] bysecond */   null,
415                 /* int[] byminute */   null,
416                 /* int[] byhour */     null,
417                 /* int[] byday */      new int[] {
418                         EventRecurrence.MO,
419                         EventRecurrence.TU,
420                         EventRecurrence.WE,
421                         EventRecurrence.TH,
422                         EventRecurrence.FR,
423                         EventRecurrence.SA,
424                         EventRecurrence.SU
425                 },
426                 /* int[] bydayNum */   new int[]{0, 0, 0, 0, 0, 0, 0},
427                 /* int[] bymonthday */ null,
428                 /* int[] byyearday */  null,
429                 /* int[] byweekno */   null,
430                 /* int[] bymonth */    null,
431                 /* int[] bysetpos */   null,
432                 /* int wkst */         EventRecurrence.MO
433         );
434     }
435 
436     // Sample coming from RFC2445
test16()437     public void test16() throws Exception {
438         verifyRecurType("FREQ=MONTHLY;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=-1",
439                 /* int freq */         EventRecurrence.MONTHLY,
440                 /* String until */     null,
441                 /* int count */        0,
442                 /* int interval */     0,
443                 /* int[] bysecond */   null,
444                 /* int[] byminute */   null,
445                 /* int[] byhour */     null,
446                 /* int[] byday */      new int[] {
447                         EventRecurrence.MO,
448                         EventRecurrence.TU,
449                         EventRecurrence.WE,
450                         EventRecurrence.TH,
451                         EventRecurrence.FR
452                 },
453                 /* int[] bydayNum */   new int[] {0, 0, 0, 0, 0},
454                 /* int[] bymonthday */ null,
455                 /* int[] byyearday */  null,
456                 /* int[] byweekno */   null,
457                 /* int[] bymonth */    null,
458                 /* int[] bysetpos */   new int[] { -1 },
459                 /* int wkst */         EventRecurrence.MO
460         );
461     }
462 
463     // Sample coming from RFC2445
test17()464     public void test17() throws Exception {
465         verifyRecurType("FREQ=DAILY;COUNT=10;INTERVAL=2",
466                 /* int freq */         EventRecurrence.DAILY,
467                 /* String until */     null,
468                 /* int count */        10,
469                 /* int interval */     2,
470                 /* int[] bysecond */   null,
471                 /* int[] byminute */   null,
472                 /* int[] byhour */     null,
473                 /* int[] byday */      null,
474                 /* int[] bydayNum */   null,
475                 /* int[] bymonthday */ null,
476                 /* int[] byyearday */  null,
477                 /* int[] byweekno */   null,
478                 /* int[] bymonth */    null,
479                 /* int[] bysetpos */   null,
480                 /* int wkst */         EventRecurrence.MO
481         );
482     }
483 
484     // Sample coming from RFC2445
test18()485     public void test18() throws Exception {
486         verifyRecurType("FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10",
487                 /* int freq */         EventRecurrence.YEARLY,
488                 /* String until */     null,
489                 /* int count */        0,
490                 /* int interval */     0,
491                 /* int[] bysecond */   null,
492                 /* int[] byminute */   null,
493                 /* int[] byhour */     null,
494                 /* int[] byday */      new int[] {
495                         EventRecurrence.SU
496                 },
497                 /* int[] bydayNum */   new int[] { -1 },
498                 /* int[] bymonthday */ null,
499                 /* int[] byyearday */  null,
500                 /* int[] byweekno */   null,
501                 /* int[] bymonth */    new int[] { 10 },
502                 /* int[] bysetpos */   null,
503                 /* int wkst */         EventRecurrence.MO
504         );
505     }
506 
507     // Sample coming from bug #1640517
test19()508     public void test19() throws Exception {
509         verifyRecurType("FREQ=YEARLY;BYMONTH=3;BYDAY=TH",
510                 /* int freq */         EventRecurrence.YEARLY,
511                 /* String until */     null,
512                 /* int count */        0,
513                 /* int interval */     0,
514                 /* int[] bysecond */   null,
515                 /* int[] byminute */   null,
516                 /* int[] byhour */     null,
517                 /* int[] byday */      new int[] {
518                         EventRecurrence.TH
519                 },
520                 /* int[] bydayNum */   new int[] { 0 },
521                 /* int[] bymonthday */ null,
522                 /* int[] byyearday */  null,
523                 /* int[] byweekno */   null,
524                 /* int[] bymonth */    new int[] { 3 },
525                 /* int[] bysetpos */   null,
526                 /* int wkst */         EventRecurrence.MO
527         );
528     }
529 
530     // INTERVAL = 0 -> Interval = 1 bug #5676414
test20()531     public void test20() throws Exception {
532         verifyRecurType("FREQ=YEARLY;BYMONTHDAY=18;BYMONTH=10;INTERVAL=0;",
533                 /* int freq */         EventRecurrence.YEARLY,
534                 /* String until */     null,
535                 /* int count */        0,
536                 /* int interval */     1,
537                 /* int[] bysecond */   null,
538                 /* int[] byminute */   null,
539                 /* int[] byhour */     null,
540                 /* int[] byday */      null,
541                 /* int[] bydayNum */   null,
542                 /* int[] bymonthday */ new int[]{18},
543                 /* int[] byyearday */  null,
544                 /* int[] byweekno */   null,
545                 /* int[] bymonth */    new int[]{10},
546                 /* int[] bysetpos */   null,
547                 /* int wkst */         EventRecurrence.MO
548         );
549     }
550 
551     // Working case: INTERVAL=1 -> Interval = 1 bug #5676414
test21()552     public void test21() throws Exception {
553         verifyRecurType("FREQ=WEEKLY;WKST=SU;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR",
554                 /* int freq */         EventRecurrence.WEEKLY,
555                 /* String until */     null,
556                 /* int count */        0,
557                 /* int interval */     1,
558                 /* int[] bysecond */   null,
559                 /* int[] byminute */   null,
560                 /* int[] byhour */     null,
561                 /* int[] byday */      new int[] {
562                         EventRecurrence.MO,
563                         EventRecurrence.TU,
564                         EventRecurrence.WE,
565                         EventRecurrence.TH,
566                         EventRecurrence.FR,
567                 },
568                 /* int[] bydayNum */   new int[]{0, 0, 0, 0, 0},
569                 /* int[] bymonthday */ null,
570                 /* int[] byyearday */  null,
571                 /* int[] byweekno */   null,
572                 /* int[] bymonth */    null,
573                 /* int[] bysetpos */   null,
574                 /* int wkst */         EventRecurrence.SU
575         );
576     }
577 
578     // Working case: INTERVAL=2 -> Interval = 2 bug #5676414
test22()579     public void test22() throws Exception {
580         verifyRecurType("FREQ=WEEKLY;WKST=SU;INTERVAL=2;BYDAY=MO,TU,WE,TH,FR",
581                 /* int freq */         EventRecurrence.WEEKLY,
582                 /* String until */     null,
583                 /* int count */        0,
584                 /* int interval */     2,
585                 /* int[] bysecond */   null,
586                 /* int[] byminute */   null,
587                 /* int[] byhour */     null,
588                 /* int[] byday */      new int[] {
589                         EventRecurrence.MO,
590                         EventRecurrence.TU,
591                         EventRecurrence.WE,
592                         EventRecurrence.TH,
593                         EventRecurrence.FR,
594                 },
595                 /* int[] bydayNum */   new int[]{0, 0, 0, 0, 0},
596                 /* int[] bymonthday */ null,
597                 /* int[] byyearday */  null,
598                 /* int[] byweekno */   null,
599                 /* int[] bymonth */    null,
600                 /* int[] bysetpos */   null,
601                 /* int wkst */         EventRecurrence.SU
602         );
603     }
604 
605     // COUNT < 0 -> Count = 1 bug #5676414
test23()606     public void test23() throws Exception {
607         verifyRecurType("FREQ=WEEKLY;COUNT=-20;BYDAY=MO,TU,WE,TH,FR;",
608                 /* int freq */         EventRecurrence.WEEKLY,
609                 /* String until */     null,
610                 /* int count */        1,
611                 /* int interval */     0,
612                 /* int[] bysecond */   null,
613                 /* int[] byminute */   null,
614                 /* int[] byhour */     null,
615                 /* int[] byday */      new int[] {
616                         EventRecurrence.MO,
617                         EventRecurrence.TU,
618                         EventRecurrence.WE,
619                         EventRecurrence.TH,
620                         EventRecurrence.FR,
621                 },
622                 /* int[] bydayNum */   new int[]{0, 0, 0, 0, 0},
623                 /* int[] bymonthday */ null,
624                 /* int[] byyearday */  null,
625                 /* int[] byweekno */   null,
626                 /* int[] bymonth */    null,
627                 /* int[] bysetpos */   null,
628                 /* int wkst */         EventRecurrence.MO
629         );
630     }
631 
632     // Working case: COUNT=2 -> Count=2 bug #5676414
test24()633     public void test24() throws Exception {
634         verifyRecurType("FREQ=WEEKLY;COUNT=2;BYDAY=MO,TU,WE,TH,FR;",
635                 /* int freq */         EventRecurrence.WEEKLY,
636                 /* String until */     null,
637                 /* int count */        2,
638                 /* int interval */     0,
639                 /* int[] bysecond */   null,
640                 /* int[] byminute */   null,
641                 /* int[] byhour */     null,
642                 /* int[] byday */      new int[] {
643                         EventRecurrence.MO,
644                         EventRecurrence.TU,
645                         EventRecurrence.WE,
646                         EventRecurrence.TH,
647                         EventRecurrence.FR,
648                 },
649                 /* int[] bydayNum */   new int[]{0, 0, 0, 0, 0},
650                 /* int[] bymonthday */ null,
651                 /* int[] byyearday */  null,
652                 /* int[] byweekno */   null,
653                 /* int[] bymonth */    null,
654                 /* int[] bysetpos */   null,
655                 /* int wkst */         EventRecurrence.MO
656         );
657     }
658 
659     // for your copying pleasure
fakeTestXX()660     public void fakeTestXX() throws Exception {
661         verifyRecurType("FREQ=DAILY;",
662                 /* int freq */         EventRecurrence.DAILY,
663                 /* String until */     null,
664                 /* int count */        0,
665                 /* int interval */     0,
666                 /* int[] bysecond */   null,
667                 /* int[] byminute */   null,
668                 /* int[] byhour */     null,
669                 /* int[] byday */      null,
670                 /* int[] bydayNum */   null,
671                 /* int[] bymonthday */ null,
672                 /* int[] byyearday */  null,
673                 /* int[] byweekno */   null,
674                 /* int[] bymonth */    null,
675                 /* int[] bysetpos */   null,
676                 /* int wkst */         EventRecurrence.MO
677         );
678     }
679 
cmp(int vlen, int[] v, int[] correct, String name)680     private static void cmp(int vlen, int[] v, int[] correct, String name) {
681         if ((correct == null && v != null)
682                 || (correct != null && v == null)) {
683             throw new RuntimeException("One is null, one isn't for " + name
684                     + ": correct=" + Arrays.toString(correct)
685                     + " actual=" + Arrays.toString(v));
686         }
687         if ((correct == null && vlen != 0)
688                 || (vlen != (correct == null ? 0 : correct.length))) {
689             throw new RuntimeException("Reported length mismatch for " + name
690                     + ": correct=" + ((correct == null) ? "null" : correct.length)
691                     + " actual=" + vlen);
692         }
693         if (correct == null) {
694             return;
695         }
696         if (v.length < correct.length) {
697             throw new RuntimeException("Array length mismatch for " + name
698                     + ": correct=" + Arrays.toString(correct)
699                     + " actual=" + Arrays.toString(v));
700         }
701         for (int i = 0; i < correct.length; i++) {
702             if (v[i] != correct[i]) {
703                 throw new RuntimeException("Array value mismatch for " + name
704                         + ": correct=" + Arrays.toString(correct)
705                         + " actual=" + Arrays.toString(v));
706             }
707         }
708     }
709 
eq(String a, String b)710     private static boolean eq(String a, String b) {
711         if ((a == null && b != null) || (a != null && b == null)) {
712             return false;
713         } else {
714             return a == b || a.equals(b);
715         }
716     }
717 
verifyRecurType(String recur, int freq, String until, int count, int interval, int[] bysecond, int[] byminute, int[] byhour, int[] byday, int[] bydayNum, int[] bymonthday, int[] byyearday, int[] byweekno, int[] bymonth, int[] bysetpos, int wkst)718     private static void verifyRecurType(String recur,
719             int freq, String until, int count, int interval,
720             int[] bysecond, int[] byminute, int[] byhour,
721             int[] byday, int[] bydayNum, int[] bymonthday,
722             int[] byyearday, int[] byweekno, int[] bymonth,
723             int[] bysetpos, int wkst) {
724         EventRecurrence eventRecurrence = new EventRecurrence();
725         eventRecurrence.parse(recur);
726         if (eventRecurrence.freq != freq
727                 || !eq(eventRecurrence.until, until)
728                 || eventRecurrence.count != count
729                 || eventRecurrence.interval != interval
730                 || eventRecurrence.wkst != wkst) {
731             System.out.println("Error... got:");
732             print(eventRecurrence);
733             System.out.println("expected:");
734             System.out.println("{");
735             System.out.println("    freq=" + freq);
736             System.out.println("    until=" + until);
737             System.out.println("    count=" + count);
738             System.out.println("    interval=" + interval);
739             System.out.println("    wkst=" + wkst);
740             System.out.println("    bysecond=" + Arrays.toString(bysecond));
741             System.out.println("    byminute=" + Arrays.toString(byminute));
742             System.out.println("    byhour=" + Arrays.toString(byhour));
743             System.out.println("    byday=" + Arrays.toString(byday));
744             System.out.println("    bydayNum=" + Arrays.toString(bydayNum));
745             System.out.println("    bymonthday=" + Arrays.toString(bymonthday));
746             System.out.println("    byyearday=" + Arrays.toString(byyearday));
747             System.out.println("    byweekno=" + Arrays.toString(byweekno));
748             System.out.println("    bymonth=" + Arrays.toString(bymonth));
749             System.out.println("    bysetpos=" + Arrays.toString(bysetpos));
750             System.out.println("}");
751             throw new RuntimeException("Mismatch in fields");
752         }
753         cmp(eventRecurrence.bysecondCount, eventRecurrence.bysecond, bysecond, "bysecond");
754         cmp(eventRecurrence.byminuteCount, eventRecurrence.byminute, byminute, "byminute");
755         cmp(eventRecurrence.byhourCount, eventRecurrence.byhour, byhour, "byhour");
756         cmp(eventRecurrence.bydayCount, eventRecurrence.byday, byday, "byday");
757         cmp(eventRecurrence.bydayCount, eventRecurrence.bydayNum, bydayNum, "bydayNum");
758         cmp(eventRecurrence.bymonthdayCount, eventRecurrence.bymonthday, bymonthday, "bymonthday");
759         cmp(eventRecurrence.byyeardayCount, eventRecurrence.byyearday, byyearday, "byyearday");
760         cmp(eventRecurrence.byweeknoCount, eventRecurrence.byweekno, byweekno, "byweekno");
761         cmp(eventRecurrence.bymonthCount, eventRecurrence.bymonth, bymonth, "bymonth");
762         cmp(eventRecurrence.bysetposCount, eventRecurrence.bysetpos, bysetpos, "bysetpos");
763     }
764 
print(EventRecurrence er)765     private static void print(EventRecurrence er) {
766         System.out.println("{");
767         System.out.println("    freq=" + er.freq);
768         System.out.println("    until=" + er.until);
769         System.out.println("    count=" + er.count);
770         System.out.println("    interval=" + er.interval);
771         System.out.println("    wkst=" + er.wkst);
772         System.out.println("    bysecond=" + Arrays.toString(er.bysecond));
773         System.out.println("    bysecondCount=" + er.bysecondCount);
774         System.out.println("    byminute=" + Arrays.toString(er.byminute));
775         System.out.println("    byminuteCount=" + er.byminuteCount);
776         System.out.println("    byhour=" + Arrays.toString(er.byhour));
777         System.out.println("    byhourCount=" + er.byhourCount);
778         System.out.println("    byday=" + Arrays.toString(er.byday));
779         System.out.println("    bydayNum=" + Arrays.toString(er.bydayNum));
780         System.out.println("    bydayCount=" + er.bydayCount);
781         System.out.println("    bymonthday=" + Arrays.toString(er.bymonthday));
782         System.out.println("    bymonthdayCount=" + er.bymonthdayCount);
783         System.out.println("    byyearday=" + Arrays.toString(er.byyearday));
784         System.out.println("    byyeardayCount=" + er.byyeardayCount);
785         System.out.println("    byweekno=" + Arrays.toString(er.byweekno));
786         System.out.println("    byweeknoCount=" + er.byweeknoCount);
787         System.out.println("    bymonth=" + Arrays.toString(er.bymonth));
788         System.out.println("    bymonthCount=" + er.bymonthCount);
789         System.out.println("    bysetpos=" + Arrays.toString(er.bysetpos));
790         System.out.println("    bysetposCount=" + er.bysetposCount);
791         System.out.println("}");
792     }
793 
794 
795     /** A list of valid rules.  The parser must accept these. */
796     private static final String[] GOOD_RRULES = {
797         /* extracted wholesale from from RFC 2445 section 4.8.5.4 */
798         "FREQ=DAILY;COUNT=10",
799         "FREQ=DAILY;UNTIL=19971224T000000Z",
800         "FREQ=DAILY;INTERVAL=2",
801         "FREQ=DAILY;INTERVAL=10;COUNT=5",
802         "FREQ=YEARLY;UNTIL=20000131T090000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA",
803         "FREQ=DAILY;UNTIL=20000131T090000Z;BYMONTH=1",
804         "FREQ=WEEKLY;COUNT=10",
805         "FREQ=WEEKLY;UNTIL=19971224T000000Z",
806         "FREQ=WEEKLY;INTERVAL=2;WKST=SU",
807         "FREQ=WEEKLY;UNTIL=19971007T000000Z;WKST=SU;BYDAY=TU,TH",
808         "FREQ=WEEKLY;COUNT=10;WKST=SU;BYDAY=TU,TH",
809         "FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;WKST=SU;BYDAY=MO,WE,FR",
810         "FREQ=WEEKLY;INTERVAL=2;COUNT=8;WKST=SU;BYDAY=TU,TH",
811         "FREQ=MONTHLY;COUNT=10;BYDAY=1FR",
812         "FREQ=MONTHLY;UNTIL=19971224T000000Z;BYDAY=1FR",
813         "FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=1SU,-1SU",
814         "FREQ=MONTHLY;COUNT=6;BYDAY=-2MO",
815         "FREQ=MONTHLY;BYMONTHDAY=-3",
816         "FREQ=MONTHLY;COUNT=10;BYMONTHDAY=2,15",
817         "FREQ=MONTHLY;COUNT=10;BYMONTHDAY=1,-1",
818         "FREQ=MONTHLY;INTERVAL=18;COUNT=10;BYMONTHDAY=10,11,12,13,14,15",
819         "FREQ=MONTHLY;INTERVAL=2;BYDAY=TU",
820         "FREQ=YEARLY;COUNT=10;BYMONTH=6,7",
821         "FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3",
822         "FREQ=YEARLY;INTERVAL=3;COUNT=10;BYYEARDAY=1,100,200",
823         "FREQ=YEARLY;BYDAY=20MO",
824         "FREQ=YEARLY;BYWEEKNO=20;BYDAY=MO",
825         "FREQ=YEARLY;BYMONTH=3;BYDAY=TH",
826         "FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8",
827         "FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13",
828         "FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13",
829         "FREQ=YEARLY;INTERVAL=4;BYMONTH=11;BYDAY=TU;BYMONTHDAY=2,3,4,5,6,7,8",
830         "FREQ=MONTHLY;COUNT=3;BYDAY=TU,WE,TH;BYSETPOS=3",
831         "FREQ=MONTHLY;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=-2",
832         "FREQ=HOURLY;INTERVAL=3;UNTIL=19970902T170000Z",
833         "FREQ=MINUTELY;INTERVAL=15;COUNT=6",
834         "FREQ=MINUTELY;INTERVAL=90;COUNT=4",
835         "FREQ=DAILY;BYHOUR=9,10,11,12,13,14,15,16;BYMINUTE=0,20,40",
836         "FREQ=MINUTELY;INTERVAL=20;BYHOUR=9,10,11,12,13,14,15,16",
837         "FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU;WKST=MO",
838         "FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU;WKST=SU",
839         /* a few more */
840         "FREQ=SECONDLY;BYSECOND=0,15,59",
841         "FREQ=MINUTELY;BYMINUTE=0,15,59",
842         "FREQ=HOURLY;BYHOUR=+0,+15,+23",
843         "INTERVAL=4;FREQ=YEARLY",
844         "FREQ=DAILY;X-WHATEVER=blah",
845         //"freq=daily;wkst=su",                               // mixed case currently not allowed
846         "FREQ=WEEKLY;INTERVAL=2;BYDAY=Mo;;UNTIL=20120327T000000Z", // double simicolon should be allowed
847         "FREQ=MONTHLY;BYDAY=1Mo",
848         "FREQ=MONTHLY;BYDAY=2Mo,2We,4Mo,4We",
849         "FREQ=MONTHLY;WKST=SU;BYMONTHDAY=25;UNTIL=20110524",
850         "FREQ=WEEKLY;BYDAY=MO;WKST=SU;UNTIL=20111218T010000Z"
851     };
852 
853     /** The parser must reject these. */
854     private static final String[] BAD_RRULES = {
855         "FREQ=MONTHLY;FREQ=MONTHLY",                        // can't specify twice
856         "FREQ=MONTHLY;COUNT=1;COUNT=1",                     // can't specify twice
857         "FREQ=SECONDLY;BYSECOND=60",                        // range
858         "FREQ=MINUTELY;BYMINUTE=-1",                        // range
859         "FREQ=HOURLY;BYHOUR=24",                            // range
860         "FREQ=YEARLY;BYMONTHDAY=0",                         // zero not valid
861         "BYMONTHDAY=1",                                     // must specify FREQ
862         //"FREQ=YEARLY;COUNT=1;UNTIL=12345",                  // can't have both COUNT and UNTIL
863         //"FREQ=DAILY;UNTIL=19970829T021400e",                // invalid date
864     };
865 
866     /**
867      * Simple test of good/bad rules.
868      */
869     @SmallTest
testBasicParse()870     public void testBasicParse() {
871         for (String rule : GOOD_RRULES) {
872             EventRecurrence recur = new EventRecurrence();
873             recur.parse(rule);
874         }
875 
876         for (String rule : BAD_RRULES) {
877             EventRecurrence recur = new EventRecurrence();
878             boolean didThrow = false;
879 
880             try {
881                 recur.parse(rule);
882             } catch (InvalidFormatException ife) {
883                 didThrow = true;
884             }
885 
886             assertTrue("Expected throw on " + rule, didThrow);
887         }
888     }
889 }
890