Home | History | Annotate | Download | only in calendarcommon2
      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
     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
     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
     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
    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
    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
    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
    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
    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
    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
    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
    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
    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 {
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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 
    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 
    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 
    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 
    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
    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