tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

timetest.c (22674B)


      1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this
      4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 /*
      7 * file: timetest.c
      8 * description: test time and date routines
      9 */
     10 /***********************************************************************
     11 ** Includes
     12 ***********************************************************************/
     13 /* Used to get the command line option */
     14 #include "plgetopt.h"
     15 
     16 #include "prinit.h"
     17 #include "prtime.h"
     18 #include "prprf.h"
     19 
     20 #include <stdio.h>
     21 #include <stdlib.h>
     22 #include <string.h>
     23 
     24 int failed_already = 0;
     25 PRBool debug_mode = PR_FALSE;
     26 
     27 static char* dayOfWeek[] = {"Sun", "Mon", "Tue", "Wed",
     28                            "Thu", "Fri", "Sat", "???"};
     29 static char* month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
     30                        "Aug", "Sep", "Oct", "Nov", "Dec", "???"};
     31 
     32 static void PrintExplodedTime(const PRExplodedTime* et) {
     33  PRInt32 totalOffset;
     34  PRInt32 hourOffset, minOffset;
     35  const char* sign;
     36 
     37  /* Print day of the week, month, day, hour, minute, and second */
     38  if (debug_mode)
     39    printf("%s %s %ld %02ld:%02ld:%02ld ", dayOfWeek[et->tm_wday],
     40           month[et->tm_month], et->tm_mday, et->tm_hour, et->tm_min,
     41           et->tm_sec);
     42 
     43  /* Print time zone */
     44  totalOffset = et->tm_params.tp_gmt_offset + et->tm_params.tp_dst_offset;
     45  if (totalOffset == 0) {
     46    if (debug_mode) {
     47      printf("UTC ");
     48    }
     49  } else {
     50    sign = "+";
     51    if (totalOffset < 0) {
     52      totalOffset = -totalOffset;
     53      sign = "-";
     54    }
     55    hourOffset = totalOffset / 3600;
     56    minOffset = (totalOffset % 3600) / 60;
     57    if (debug_mode) {
     58      printf("%s%02ld%02ld ", sign, hourOffset, minOffset);
     59    }
     60  }
     61 
     62  /* Print year */
     63  if (debug_mode) {
     64    printf("%hd", et->tm_year);
     65  }
     66 }
     67 
     68 static int ExplodedTimeIsEqual(const PRExplodedTime* et1,
     69                               const PRExplodedTime* et2) {
     70  if (et1->tm_usec == et2->tm_usec && et1->tm_sec == et2->tm_sec &&
     71      et1->tm_min == et2->tm_min && et1->tm_hour == et2->tm_hour &&
     72      et1->tm_mday == et2->tm_mday && et1->tm_month == et2->tm_month &&
     73      et1->tm_year == et2->tm_year && et1->tm_wday == et2->tm_wday &&
     74      et1->tm_yday == et2->tm_yday &&
     75      et1->tm_params.tp_gmt_offset == et2->tm_params.tp_gmt_offset &&
     76      et1->tm_params.tp_dst_offset == et2->tm_params.tp_dst_offset) {
     77    return 1;
     78  } else {
     79    return 0;
     80  }
     81 }
     82 
     83 static void testParseTimeString(PRTime t) {
     84  PRExplodedTime et;
     85  PRTime t2;
     86  char timeString[128];
     87  char buf[128];
     88  PRInt32 totalOffset;
     89  PRInt32 hourOffset, minOffset;
     90  const char* sign;
     91  PRInt64 usec_per_sec;
     92 
     93  /* Truncate the microsecond part of PRTime */
     94  LL_I2L(usec_per_sec, PR_USEC_PER_SEC);
     95  LL_DIV(t, t, usec_per_sec);
     96  LL_MUL(t, t, usec_per_sec);
     97 
     98  PR_ExplodeTime(t, PR_LocalTimeParameters, &et);
     99 
    100  /* Print day of the week, month, day, hour, minute, and second */
    101  PR_snprintf(timeString, 128, "%s %s %ld %02ld:%02ld:%02ld ",
    102              dayOfWeek[et.tm_wday], month[et.tm_month], et.tm_mday, et.tm_hour,
    103              et.tm_min, et.tm_sec);
    104  /* Print time zone */
    105  totalOffset = et.tm_params.tp_gmt_offset + et.tm_params.tp_dst_offset;
    106  if (totalOffset == 0) {
    107    strcat(timeString, "GMT "); /* I wanted to use "UTC" here, but
    108                                 * PR_ParseTimeString doesn't
    109                                 * understand "UTC".  */
    110  } else {
    111    sign = "+";
    112    if (totalOffset < 0) {
    113      totalOffset = -totalOffset;
    114      sign = "-";
    115    }
    116    hourOffset = totalOffset / 3600;
    117    minOffset = (totalOffset % 3600) / 60;
    118    PR_snprintf(buf, 128, "%s%02ld%02ld ", sign, hourOffset, minOffset);
    119    strcat(timeString, buf);
    120  }
    121  /* Print year */
    122  PR_snprintf(buf, 128, "%hd", et.tm_year);
    123  strcat(timeString, buf);
    124 
    125  if (PR_ParseTimeString(timeString, PR_FALSE, &t2) == PR_FAILURE) {
    126    fprintf(stderr, "PR_ParseTimeString() failed\n");
    127    exit(1);
    128  }
    129  if (LL_NE(t, t2)) {
    130    fprintf(stderr, "PR_ParseTimeString() incorrect\n");
    131    PR_snprintf(buf, 128, "t is %lld, t2 is %lld, time string is %s\n", t, t2,
    132                timeString);
    133    fprintf(stderr, "%s\n", buf);
    134    exit(1);
    135  }
    136 }
    137 
    138 int main(int argc, char** argv) {
    139  /* The command line argument: -d is used to determine if the test is being run
    140  in debug mode. The regress tool requires only one line output:PASS or FAIL.
    141  All of the printfs associated with this test has been handled with a if
    142  (debug_mode) test. Usage: test_name -d
    143  */
    144  PLOptStatus os;
    145  PLOptState* opt;
    146 
    147  opt = PL_CreateOptState(argc, argv, "d");
    148  while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) {
    149    if (PL_OPT_BAD == os) {
    150      continue;
    151    }
    152    switch (opt->option) {
    153      case 'd': /* debug mode */
    154        debug_mode = PR_TRUE;
    155        break;
    156      default:
    157        break;
    158    }
    159  }
    160  PL_DestroyOptState(opt);
    161 
    162  /* main test */
    163 
    164  PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
    165 
    166  /* Testing zero PRTime (the epoch) */
    167  {
    168    PRTime t;
    169    PRExplodedTime et;
    170 
    171    LL_I2L(t, 0);
    172    if (debug_mode) {
    173      printf("The NSPR epoch is:\n");
    174    }
    175    PR_ExplodeTime(t, PR_LocalTimeParameters, &et);
    176    PrintExplodedTime(&et);
    177    if (debug_mode) {
    178      printf("\n");
    179    }
    180    PR_ExplodeTime(t, PR_GMTParameters, &et);
    181    PrintExplodedTime(&et);
    182    if (debug_mode) {
    183      printf("\n\n");
    184    }
    185    testParseTimeString(t);
    186  }
    187 
    188  /*
    189   *************************************************************
    190   **
    191   **  Testing PR_Now(), PR_ExplodeTime, and PR_ImplodeTime
    192   **  on the current time
    193   **
    194   *************************************************************
    195   */
    196 
    197  {
    198    PRTime t1, t2;
    199    PRExplodedTime et;
    200 
    201    if (debug_mode) {
    202      printf("*********************************************\n");
    203      printf("**                                         **\n");
    204      printf("** Testing PR_Now(), PR_ExplodeTime, and   **\n");
    205      printf("** PR_ImplodeTime on the current time      **\n");
    206      printf("**                                         **\n");
    207      printf("*********************************************\n\n");
    208    }
    209    t1 = PR_Now();
    210 
    211    /* First try converting to UTC */
    212 
    213    PR_ExplodeTime(t1, PR_GMTParameters, &et);
    214    if (et.tm_params.tp_gmt_offset || et.tm_params.tp_dst_offset) {
    215      if (debug_mode) {
    216        printf("ERROR: UTC has nonzero gmt or dst offset.\n");
    217      } else {
    218        failed_already = 1;
    219      }
    220      return 1;
    221    }
    222    if (debug_mode) {
    223      printf("Current UTC is ");
    224    }
    225    PrintExplodedTime(&et);
    226    if (debug_mode) {
    227      printf("\n");
    228    }
    229 
    230    t2 = PR_ImplodeTime(&et);
    231    if (LL_NE(t1, t2)) {
    232      if (debug_mode) {
    233        printf("ERROR: Explode and implode are NOT inverse.\n");
    234      } else {
    235        printf("FAIL\n");
    236      }
    237      return 1;
    238    }
    239 
    240    /* Next, try converting to local (US Pacific) time */
    241 
    242    PR_ExplodeTime(t1, PR_LocalTimeParameters, &et);
    243    if (debug_mode) {
    244      printf("Current local time is ");
    245    }
    246    PrintExplodedTime(&et);
    247    if (debug_mode) {
    248      printf("\n");
    249    }
    250    if (debug_mode)
    251      printf("GMT offset is %ld, DST offset is %ld\n",
    252             et.tm_params.tp_gmt_offset, et.tm_params.tp_dst_offset);
    253    t2 = PR_ImplodeTime(&et);
    254    if (LL_NE(t1, t2)) {
    255      if (debug_mode) {
    256        printf("ERROR: Explode and implode are NOT inverse.\n");
    257      }
    258      return 1;
    259    }
    260 
    261    if (debug_mode) {
    262      printf("Please examine the results\n");
    263    }
    264    testParseTimeString(t1);
    265  }
    266 
    267  /*
    268   *******************************************
    269   **
    270   ** Testing PR_NormalizeTime()
    271   **
    272   *******************************************
    273   */
    274 
    275  /* July 4, 2001 is Wednesday */
    276  {
    277    PRExplodedTime et;
    278 
    279    if (debug_mode) {
    280      printf("\n");
    281      printf("**********************************\n");
    282      printf("**                              **\n");
    283      printf("** Testing PR_NormalizeTime()   **\n");
    284      printf("**                              **\n");
    285      printf("**********************************\n\n");
    286    }
    287    et.tm_year = 2001;
    288    et.tm_month = 7 - 1;
    289    et.tm_mday = 4;
    290    et.tm_hour = 0;
    291    et.tm_min = 0;
    292    et.tm_sec = 0;
    293    et.tm_usec = 0;
    294    et.tm_params = PR_GMTParameters(&et);
    295 
    296    PR_NormalizeTime(&et, PR_GMTParameters);
    297 
    298    if (debug_mode) {
    299      printf("July 4, 2001 is %s.\n", dayOfWeek[et.tm_wday]);
    300    }
    301    if (et.tm_wday == 3) {
    302      if (debug_mode) {
    303        printf("PASS\n");
    304      }
    305    } else {
    306      if (debug_mode) {
    307        printf("ERROR: It should be Wednesday\n");
    308      } else {
    309        failed_already = 1;
    310      }
    311      return 1;
    312    }
    313    testParseTimeString(PR_ImplodeTime(&et));
    314 
    315    /* June 12, 1997 23:00 PST == June 13, 1997 00:00 PDT */
    316    et.tm_year = 1997;
    317    et.tm_month = 6 - 1;
    318    et.tm_mday = 12;
    319    et.tm_hour = 23;
    320    et.tm_min = 0;
    321    et.tm_sec = 0;
    322    et.tm_usec = 0;
    323    et.tm_params.tp_gmt_offset = -8 * 3600;
    324    et.tm_params.tp_dst_offset = 0;
    325 
    326    PR_NormalizeTime(&et, PR_USPacificTimeParameters);
    327 
    328    if (debug_mode) {
    329      printf("Thu Jun 12, 1997 23:00:00 PST is ");
    330    }
    331    PrintExplodedTime(&et);
    332    if (debug_mode) {
    333      printf(".\n");
    334    }
    335    if (et.tm_wday == 5) {
    336      if (debug_mode) {
    337        printf("PASS\n");
    338      }
    339    } else {
    340      if (debug_mode) {
    341        printf("ERROR: It should be Friday\n");
    342      } else {
    343        failed_already = 1;
    344      }
    345      return 1;
    346    }
    347    testParseTimeString(PR_ImplodeTime(&et));
    348 
    349    /* Feb 14, 1997 00:00:00 PDT == Feb 13, 1997 23:00:00 PST */
    350    et.tm_year = 1997;
    351    et.tm_month = 2 - 1;
    352    et.tm_mday = 14;
    353    et.tm_hour = 0;
    354    et.tm_min = 0;
    355    et.tm_sec = 0;
    356    et.tm_usec = 0;
    357    et.tm_params.tp_gmt_offset = -8 * 3600;
    358    et.tm_params.tp_dst_offset = 3600;
    359 
    360    PR_NormalizeTime(&et, PR_USPacificTimeParameters);
    361 
    362    if (debug_mode) {
    363      printf("Fri Feb 14, 1997 00:00:00 PDT is ");
    364    }
    365    PrintExplodedTime(&et);
    366    if (debug_mode) {
    367      printf(".\n");
    368    }
    369    if (et.tm_wday == 4) {
    370      if (debug_mode) {
    371        printf("PASS\n");
    372      }
    373    } else {
    374      if (debug_mode) {
    375        printf("ERROR: It should be Thursday\n");
    376      } else {
    377        failed_already = 1;
    378      }
    379      return 1;
    380    }
    381    testParseTimeString(PR_ImplodeTime(&et));
    382 
    383    /* What time is Nov. 7, 1996, 18:29:23 PDT? */
    384    et.tm_year = 1996;
    385    et.tm_month = 11 - 1;
    386    et.tm_mday = 7;
    387    et.tm_hour = 18;
    388    et.tm_min = 29;
    389    et.tm_sec = 23;
    390    et.tm_usec = 0;
    391    et.tm_params.tp_gmt_offset = -8 * 3600; /* PDT */
    392    et.tm_params.tp_dst_offset = 3600;
    393 
    394    PR_NormalizeTime(&et, PR_LocalTimeParameters);
    395    if (debug_mode) {
    396      printf("Nov 7 18:29:23 PDT 1996 is ");
    397    }
    398    PrintExplodedTime(&et);
    399    if (debug_mode) {
    400      printf(".\n");
    401    }
    402    testParseTimeString(PR_ImplodeTime(&et));
    403 
    404    /* What time is Oct. 7, 1995, 18:29:23 PST? */
    405    et.tm_year = 1995;
    406    et.tm_month = 10 - 1;
    407    et.tm_mday = 7;
    408    et.tm_hour = 18;
    409    et.tm_min = 29;
    410    et.tm_sec = 23;
    411    et.tm_params.tp_gmt_offset = -8 * 3600; /* PST */
    412    et.tm_params.tp_dst_offset = 0;
    413 
    414    PR_NormalizeTime(&et, PR_LocalTimeParameters);
    415    if (debug_mode) {
    416      printf("Oct 7 18:29:23 PST 1995 is ");
    417    }
    418    PrintExplodedTime(&et);
    419    if (debug_mode) {
    420      printf(".\n");
    421    }
    422    testParseTimeString(PR_ImplodeTime(&et));
    423 
    424    if (debug_mode) {
    425      printf("Please examine the results\n");
    426    }
    427  }
    428 
    429  /*
    430   **************************************************************
    431   **
    432   ** Testing range of years
    433   **
    434   **************************************************************
    435   */
    436 
    437  {
    438    PRExplodedTime et1, et2;
    439    PRTime ttt;
    440    PRTime secs;
    441 
    442    if (debug_mode) {
    443      printf("\n");
    444      printf("***************************************\n");
    445      printf("**                                   **\n");
    446      printf("**  Testing range of years           **\n");
    447      printf("**                                   **\n");
    448      printf("***************************************\n\n");
    449    }
    450    /* April 4, 1917 GMT */
    451    et1.tm_usec = 0;
    452    et1.tm_sec = 0;
    453    et1.tm_min = 0;
    454    et1.tm_hour = 0;
    455    et1.tm_mday = 4;
    456    et1.tm_month = 4 - 1;
    457    et1.tm_year = 1917;
    458    et1.tm_params = PR_GMTParameters(&et1);
    459    PR_NormalizeTime(&et1, PR_LocalTimeParameters);
    460    secs = PR_ImplodeTime(&et1);
    461    if (LL_GE_ZERO(secs)) {
    462      if (debug_mode) {
    463        printf("ERROR: April 4, 1917 GMT returns a nonnegative second count\n");
    464      }
    465      failed_already = 1;
    466      return 1;
    467    }
    468    PR_ExplodeTime(secs, PR_LocalTimeParameters, &et2);
    469    if (!ExplodedTimeIsEqual(&et1, &et2)) {
    470      if (debug_mode) {
    471        printf(
    472            "ERROR: PR_ImplodeTime and PR_ExplodeTime are not inverse for "
    473            "April 4, 1917 GMT\n");
    474      }
    475      failed_already = 1;
    476      return 1;
    477    }
    478    ttt = PR_ImplodeTime(&et1);
    479    testParseTimeString(ttt);
    480 
    481    if (debug_mode) {
    482      printf("Test passed for April 4, 1917\n");
    483    }
    484 
    485    /* July 4, 2050 */
    486    et1.tm_usec = 0;
    487    et1.tm_sec = 0;
    488    et1.tm_min = 0;
    489    et1.tm_hour = 0;
    490    et1.tm_mday = 4;
    491    et1.tm_month = 7 - 1;
    492    et1.tm_year = 2050;
    493    et1.tm_params = PR_GMTParameters(&et1);
    494    PR_NormalizeTime(&et1, PR_LocalTimeParameters);
    495    secs = PR_ImplodeTime(&et1);
    496    if (!LL_GE_ZERO(secs)) {
    497      if (debug_mode) {
    498        printf("ERROR: July 4, 2050 GMT returns a negative second count\n");
    499      }
    500      failed_already = 1;
    501      return 1;
    502    }
    503    PR_ExplodeTime(secs, PR_LocalTimeParameters, &et2);
    504    if (!ExplodedTimeIsEqual(&et1, &et2)) {
    505      if (debug_mode) {
    506        printf(
    507            "ERROR: PR_ImplodeTime and PR_ExplodeTime are not inverse for July "
    508            "4, 2050 GMT\n");
    509      }
    510      failed_already = 1;
    511      return 1;
    512    }
    513    testParseTimeString(PR_ImplodeTime(&et1));
    514 
    515    if (debug_mode) {
    516      printf("Test passed for July 4, 2050\n");
    517    }
    518  }
    519 
    520  /*
    521   **************************************************************
    522   **
    523   **  Stress test
    524   *
    525   **      Go through four years, starting from
    526   **      00:00:00 PST Jan. 1, 2005, incrementing
    527   **      every 10 minutes.
    528   **
    529   **************************************************************
    530   */
    531 
    532  {
    533    PRExplodedTime et, et1, et2;
    534    PRInt64 usecPer10Min;
    535    int day, hour, min;
    536    PRTime usecs;
    537    int dstInEffect = 0;
    538 
    539    if (debug_mode) {
    540      printf("\n");
    541      printf("*******************************************************\n");
    542      printf("**                                                   **\n");
    543      printf("**        Stress test  Pacific Time                  **\n");
    544      printf("**  Starting from midnight Jan. 1, 2005 PST,         **\n");
    545      printf("**  going through four years in 10-minute increment  **\n");
    546      printf("**                                                   **\n");
    547      printf("*******************************************************\n\n");
    548    }
    549    LL_I2L(usecPer10Min, 600000000L);
    550 
    551    /* 00:00:00 PST Jan. 1, 2005 */
    552    et.tm_usec = 0;
    553    et.tm_sec = 0;
    554    et.tm_min = 0;
    555    et.tm_hour = 0;
    556    et.tm_mday = 1;
    557    et.tm_month = 0;
    558    et.tm_year = 2005;
    559    et.tm_params.tp_gmt_offset = -8 * 3600;
    560    et.tm_params.tp_dst_offset = 0;
    561    usecs = PR_ImplodeTime(&et);
    562 
    563    for (day = 0; day < 4 * 365 + 1; day++) {
    564      for (hour = 0; hour < 24; hour++) {
    565        for (min = 0; min < 60; min += 10) {
    566          LL_ADD(usecs, usecs, usecPer10Min);
    567          PR_ExplodeTime(usecs, PR_USPacificTimeParameters, &et1);
    568 
    569          et2 = et;
    570          et2.tm_usec += 600000000L;
    571          PR_NormalizeTime(&et2, PR_USPacificTimeParameters);
    572 
    573          if (!ExplodedTimeIsEqual(&et1, &et2)) {
    574            printf("ERROR: componentwise comparison failed\n");
    575            PrintExplodedTime(&et1);
    576            printf("\n");
    577            PrintExplodedTime(&et2);
    578            printf("\n");
    579            failed_already = 1;
    580            return 1;
    581          }
    582 
    583          if (LL_NE(usecs, PR_ImplodeTime(&et1))) {
    584            printf(
    585                "ERROR: PR_ExplodeTime and PR_ImplodeTime are not inverse\n");
    586            PrintExplodedTime(&et1);
    587            printf("\n");
    588            failed_already = 1;
    589            return 1;
    590          }
    591          testParseTimeString(usecs);
    592 
    593          if (!dstInEffect && et1.tm_params.tp_dst_offset) {
    594            dstInEffect = 1;
    595            if (debug_mode) {
    596              printf("DST changeover from ");
    597              PrintExplodedTime(&et);
    598              printf(" to ");
    599              PrintExplodedTime(&et1);
    600              printf(".\n");
    601            }
    602          } else if (dstInEffect && !et1.tm_params.tp_dst_offset) {
    603            dstInEffect = 0;
    604            if (debug_mode) {
    605              printf("DST changeover from ");
    606              PrintExplodedTime(&et);
    607              printf(" to ");
    608              PrintExplodedTime(&et1);
    609              printf(".\n");
    610            }
    611          }
    612 
    613          et = et1;
    614        }
    615      }
    616    }
    617    if (debug_mode) {
    618      printf("Test passed\n");
    619    }
    620  }
    621 
    622  /* Same stress test, but with PR_LocalTimeParameters */
    623 
    624  {
    625    PRExplodedTime et, et1, et2;
    626    PRInt64 usecPer10Min;
    627    int day, hour, min;
    628    PRTime usecs;
    629    int dstInEffect = 0;
    630 
    631    if (debug_mode) {
    632      printf("\n");
    633      printf("*******************************************************\n");
    634      printf("**                                                   **\n");
    635      printf("**         Stress test    Local Time                 **\n");
    636      printf("**  Starting from midnight Jan. 1, 2005 PST,         **\n");
    637      printf("**  going through four years in 10-minute increment  **\n");
    638      printf("**                                                   **\n");
    639      printf("*******************************************************\n\n");
    640    }
    641 
    642    LL_I2L(usecPer10Min, 600000000L);
    643 
    644    /* 00:00:00 PST Jan. 1, 2005 */
    645    et.tm_usec = 0;
    646    et.tm_sec = 0;
    647    et.tm_min = 0;
    648    et.tm_hour = 0;
    649    et.tm_mday = 1;
    650    et.tm_month = 0;
    651    et.tm_year = 2005;
    652    et.tm_params.tp_gmt_offset = -8 * 3600;
    653    et.tm_params.tp_dst_offset = 0;
    654    usecs = PR_ImplodeTime(&et);
    655 
    656    for (day = 0; day < 4 * 365 + 1; day++) {
    657      for (hour = 0; hour < 24; hour++) {
    658        for (min = 0; min < 60; min += 10) {
    659          LL_ADD(usecs, usecs, usecPer10Min);
    660          PR_ExplodeTime(usecs, PR_LocalTimeParameters, &et1);
    661 
    662          et2 = et;
    663          et2.tm_usec += 600000000L;
    664          PR_NormalizeTime(&et2, PR_LocalTimeParameters);
    665 
    666          if (!ExplodedTimeIsEqual(&et1, &et2)) {
    667            printf("ERROR: componentwise comparison failed\n");
    668            PrintExplodedTime(&et1);
    669            printf("\n");
    670            PrintExplodedTime(&et2);
    671            printf("\n");
    672            return 1;
    673          }
    674 
    675          if (LL_NE(usecs, PR_ImplodeTime(&et1))) {
    676            printf(
    677                "ERROR: PR_ExplodeTime and PR_ImplodeTime are not inverse\n");
    678            PrintExplodedTime(&et1);
    679            printf("\n");
    680            failed_already = 1;
    681            return 1;
    682          }
    683          testParseTimeString(usecs);
    684 
    685          if (!dstInEffect && et1.tm_params.tp_dst_offset) {
    686            dstInEffect = 1;
    687            if (debug_mode) {
    688              printf("DST changeover from ");
    689              PrintExplodedTime(&et);
    690              printf(" to ");
    691              PrintExplodedTime(&et1);
    692              printf(".\n");
    693            }
    694          } else if (dstInEffect && !et1.tm_params.tp_dst_offset) {
    695            dstInEffect = 0;
    696            if (debug_mode) {
    697              printf("DST changeover from ");
    698              PrintExplodedTime(&et);
    699              printf(" to ");
    700              PrintExplodedTime(&et1);
    701              printf(".\n");
    702            }
    703          }
    704 
    705          et = et1;
    706        }
    707      }
    708    }
    709    if (debug_mode) {
    710      printf("Test passed\n");
    711    }
    712  }
    713 
    714  /* Same stress test, but with PR_LocalTimeParameters and going backward */
    715 
    716  {
    717    PRExplodedTime et, et1, et2;
    718    PRInt64 usecPer10Min;
    719    int day, hour, min;
    720    PRTime usecs;
    721    int dstInEffect = 0;
    722 
    723    if (debug_mode) {
    724      printf("\n");
    725      printf("*******************************************************\n");
    726      printf("**                                                   **\n");
    727      printf("**           Stress test    Local Time               **\n");
    728      printf("**  Starting from midnight Jan. 1, 2009 PST,         **\n");
    729      printf("**  going back four years in 10-minute increment     **\n");
    730      printf("**                                                   **\n");
    731      printf("*******************************************************\n\n");
    732    }
    733 
    734    LL_I2L(usecPer10Min, 600000000L);
    735 
    736    /* 00:00:00 PST Jan. 1, 2009 */
    737    et.tm_usec = 0;
    738    et.tm_sec = 0;
    739    et.tm_min = 0;
    740    et.tm_hour = 0;
    741    et.tm_mday = 1;
    742    et.tm_month = 0;
    743    et.tm_year = 2009;
    744    et.tm_params.tp_gmt_offset = -8 * 3600;
    745    et.tm_params.tp_dst_offset = 0;
    746    usecs = PR_ImplodeTime(&et);
    747 
    748    for (day = 0; day < 4 * 365 + 1; day++) {
    749      for (hour = 0; hour < 24; hour++) {
    750        for (min = 0; min < 60; min += 10) {
    751          LL_SUB(usecs, usecs, usecPer10Min);
    752          PR_ExplodeTime(usecs, PR_LocalTimeParameters, &et1);
    753 
    754          et2 = et;
    755          et2.tm_usec -= 600000000L;
    756          PR_NormalizeTime(&et2, PR_LocalTimeParameters);
    757 
    758          if (!ExplodedTimeIsEqual(&et1, &et2)) {
    759            printf("ERROR: componentwise comparison failed\n");
    760            PrintExplodedTime(&et1);
    761            printf("\n");
    762            PrintExplodedTime(&et2);
    763            printf("\n");
    764            return 1;
    765          }
    766 
    767          if (LL_NE(usecs, PR_ImplodeTime(&et1))) {
    768            printf(
    769                "ERROR: PR_ExplodeTime and PR_ImplodeTime are not inverse\n");
    770            PrintExplodedTime(&et1);
    771            printf("\n");
    772            failed_already = 1;
    773            return 1;
    774          }
    775          testParseTimeString(usecs);
    776 
    777          if (!dstInEffect && et1.tm_params.tp_dst_offset) {
    778            dstInEffect = 1;
    779            if (debug_mode) {
    780              printf("DST changeover from ");
    781              PrintExplodedTime(&et);
    782              printf(" to ");
    783              PrintExplodedTime(&et1);
    784              printf(".\n");
    785            }
    786          } else if (dstInEffect && !et1.tm_params.tp_dst_offset) {
    787            dstInEffect = 0;
    788            if (debug_mode) {
    789              printf("DST changeover from ");
    790              PrintExplodedTime(&et);
    791              printf(" to ");
    792              PrintExplodedTime(&et1);
    793              printf(".\n");
    794            }
    795          }
    796 
    797          et = et1;
    798        }
    799      }
    800    }
    801  }
    802 
    803  if (failed_already) {
    804    return 1;
    805  } else {
    806    return 0;
    807  }
    808 }