Home | History | Annotate | Download | only in intltest
      1 /********************************************************************
      2  * COPYRIGHT:
      3  * Copyright (c) 1997-2013 International Business Machines Corporation and
      4  * others. All Rights Reserved.
      5  ********************************************************************/
      6 
      7 /***********************************************************************
      8  * Modification history
      9  * Date        Name        Description
     10  * 07/09/2007  srl         Copied from dadrcoll.cpp
     11  ***********************************************************************/
     12 
     13 #include "unicode/utypes.h"
     14 
     15 #if !UCONFIG_NO_FORMATTING
     16 
     17 #include "unicode/tstdtmod.h"
     18 #include "tsdate.h"
     19 #include "dadrfmt.h"
     20 #include "unicode/calendar.h"
     21 #include "intltest.h"
     22 #include <string.h>
     23 #include "unicode/schriter.h"
     24 #include "unicode/regex.h"
     25 #include "unicode/smpdtfmt.h"
     26 #include "dbgutil.h"
     27 #include "fldset.h"
     28 
     29 
     30 #include <stdio.h>
     31 
     32 DataDrivenFormatTest::DataDrivenFormatTest() {
     33     UErrorCode status = U_ZERO_ERROR;
     34     driver = TestDataModule::getTestDataModule("format", *this, status);
     35 }
     36 
     37 DataDrivenFormatTest::~DataDrivenFormatTest() {
     38     delete driver;
     39 }
     40 
     41 void DataDrivenFormatTest::runIndexedTest(int32_t index, UBool exec,
     42         const char* &name, char* /*par */) {
     43     if (driver != NULL) {
     44         if (exec) {
     45             //  logln("Begin ");
     46         }
     47         const DataMap *info= NULL;
     48         UErrorCode status= U_ZERO_ERROR;
     49         TestData *testData = driver->createTestData(index, status);
     50         if (U_SUCCESS(status)) {
     51             name = testData->getName();
     52             if (testData->getInfo(info, status)) {
     53                 log(info->getString("Description", status));
     54             }
     55             if (exec) {
     56                 log(name);
     57                 logln("---");
     58                 logln("");
     59 
     60                 processTest(testData);
     61             }
     62             delete testData;
     63         } else {
     64             name = "";
     65         }
     66     } else {
     67         dataerrln("format/DataDriven*Test data (format.res) not initialized!");
     68         name = "";
     69     }
     70 
     71 }
     72 
     73 
     74 
     75 /*
     76  *             Headers { "locale", "zone", "spec", "date", "str"}
     77             // locale: locale including calendar type
     78             // zone:   time zone name, or "" to not explicitly set zone
     79             // spec:   either 'PATTERN=y mm h' etc, or 'DATE=SHORT,TIME=LONG'
     80             // date:   either an unsigned long (millis), or a calendar spec ERA=0,YEAR=1, etc.. applied to the calendar type specified by the locale
     81             // str:   the expected unicode string
     82             Cases {
     83                {
     84                     "en_US@calendar=gregorian",
     85                     "",
     86                     "DATE=SHORT,TIME=SHORT",
     87                     "ERA=1,YEAR=2007,MONTH=AUGUST,DATE=8,HOUR=18,MINUTE=54,SECOND=12",
     88                     "8/8/2007 6:54pm"
     89                },
     90  * */
     91 
     92 
     93 void DataDrivenFormatTest::testConvertDate(TestData *testData,
     94         const DataMap * /* settings */, UBool fmt) {
     95     UnicodeString kPATTERN("PATTERN="); // TODO: static
     96     UnicodeString kMILLIS("MILLIS="); // TODO: static
     97     UnicodeString kRELATIVE_MILLIS("RELATIVE_MILLIS="); // TODO: static
     98     UnicodeString kRELATIVE_ADD("RELATIVE_ADD:"); // TODO: static
     99 
    100     UErrorCode status = U_ZERO_ERROR;
    101     SimpleDateFormat basicFmt(UnicodeString("EEE MMM dd yyyy / YYYY'-W'ww-ee"),
    102             status);
    103     if (U_FAILURE(status)) {
    104         dataerrln("FAIL: Couldn't create basic SimpleDateFormat: %s",
    105                 u_errorName(status));
    106         return;
    107     }
    108 
    109     const DataMap *currentCase= NULL;
    110     // Start the processing
    111     int n = 0;
    112     while (testData->nextCase(currentCase, status)) {
    113         char calLoc[256] = "";
    114         DateTimeStyleSet styleSet;
    115         UnicodeString pattern;
    116         UBool usePattern = FALSE;
    117         (void)usePattern;   // Suppress unused warning.
    118         CalendarFieldsSet fromSet;
    119         UDate fromDate = 0;
    120         UBool useDate = FALSE;
    121 
    122         UDate now = Calendar::getNow();
    123 
    124         ++n;
    125 
    126         char theCase[200];
    127         sprintf(theCase, "case %d:", n);
    128         UnicodeString caseString(theCase, "");
    129 
    130         // load params
    131         UnicodeString locale = currentCase->getString("locale", status);
    132         if (U_FAILURE(status)) {
    133             errln("case %d: No 'locale' line.", n);
    134             continue;
    135         }
    136         UnicodeString zone = currentCase->getString("zone", status);
    137         if (U_FAILURE(status)) {
    138             errln("case %d: No 'zone' line.", n);
    139             continue;
    140         }
    141         UnicodeString spec = currentCase->getString("spec", status);
    142         if(U_FAILURE(status)) {
    143             errln("case %d: No 'spec' line.", n);
    144             continue;
    145         }
    146         UnicodeString date = currentCase->getString("date", status);
    147         if(U_FAILURE(status)) {
    148             errln("case %d: No 'date' line.", n);
    149             continue;
    150         }
    151         UnicodeString expectStr= currentCase->getString("str", status);
    152         if(U_FAILURE(status)) {
    153             errln("case %d: No 'str' line.", n);
    154             continue;
    155         }
    156 
    157         DateFormat *format = NULL;
    158 
    159         // Process: 'locale'
    160         locale.extract(0, locale.length(), calLoc, (const char*)0); // default codepage.  Invariant codepage doesn't have '@'!
    161         Locale loc(calLoc);
    162         if(spec.startsWith(kPATTERN)) {
    163             pattern = UnicodeString(spec,kPATTERN.length());
    164             usePattern = TRUE;
    165             format = new SimpleDateFormat(pattern, loc, status);
    166             if(U_FAILURE(status)) {
    167                 errln("case %d: could not create SimpleDateFormat from pattern: %s", n, u_errorName(status));
    168                 continue;
    169             }
    170         } else {
    171             if(styleSet.parseFrom(spec, status)<0 || U_FAILURE(status)) {
    172                 errln("case %d: could not parse spec as style fields: %s", n, u_errorName(status));
    173                 continue;
    174             }
    175             format = DateFormat::createDateTimeInstance((DateFormat::EStyle)styleSet.getDateStyle(), (DateFormat::EStyle)styleSet.getTimeStyle(), loc);
    176             if(format == NULL ) {
    177                 errln("case %d: could not create SimpleDateFormat from styles.", n);
    178                 continue;
    179             }
    180         }
    181 
    182         Calendar *cal = Calendar::createInstance(loc, status);
    183         if(U_FAILURE(status)) {
    184             errln("case %d: could not create calendar from %s", n, calLoc);
    185         }
    186 
    187         if (zone.length() > 0) {
    188             TimeZone * tz = TimeZone::createTimeZone(zone);
    189             cal->setTimeZone(*tz);
    190             format->setTimeZone(*tz);
    191             delete tz;
    192         }
    193 
    194         // parse 'date'
    195         if(date.startsWith(kMILLIS)) {
    196             UnicodeString millis = UnicodeString(date, kMILLIS.length());
    197             useDate = TRUE;
    198             fromDate = udbg_stod(millis);
    199         } else if(date.startsWith(kRELATIVE_MILLIS)) {
    200             UnicodeString millis = UnicodeString(date, kRELATIVE_MILLIS.length());
    201             useDate = TRUE;
    202             fromDate = udbg_stod(millis) + now;
    203         } else if(date.startsWith(kRELATIVE_ADD)) {
    204             UnicodeString add = UnicodeString(date, kRELATIVE_ADD.length());  // "add" is a string indicating which fields to add
    205             if(fromSet.parseFrom(add, status)<0 || U_FAILURE(status)) {
    206                 errln("case %d: could not parse date as RELATIVE_ADD calendar fields: %s", n, u_errorName(status));
    207                 continue;
    208             }
    209             useDate=TRUE;
    210             cal->clear();
    211             cal->setTime(now, status);
    212             for (int q=0; q<UCAL_FIELD_COUNT; q++) {
    213                 if (fromSet.isSet((UCalendarDateFields)q)) {
    214                     //int32_t oldv = cal->get((UCalendarDateFields)q, status);
    215                     if (q == UCAL_DATE) {
    216                         cal->add((UCalendarDateFields)q,
    217                                     fromSet.get((UCalendarDateFields)q), status);
    218                     } else {
    219                         cal->set((UCalendarDateFields)q,
    220                                     fromSet.get((UCalendarDateFields)q));
    221                     }
    222                     //int32_t newv = cal->get((UCalendarDateFields)q, status);
    223                 }
    224             }
    225             fromDate = cal->getTime(status);
    226             if(U_FAILURE(status)) {
    227                 errln("case %d: could not apply date as RELATIVE_ADD calendar fields: %s", n, u_errorName(status));
    228                 continue;
    229             }
    230         } else if(fromSet.parseFrom(date, status)<0 || U_FAILURE(status)) {
    231             errln("case %d: could not parse date as calendar fields: %s", n, u_errorName(status));
    232             continue;
    233         }
    234 
    235         // now, do it.
    236         if (fmt) {
    237             FieldPosition pos;
    238 //            logln((UnicodeString)"#"+n+" "+locale+"/"+from+" >>> "+toCalLoc+"/"
    239 //                    +to);
    240             cal->clear();
    241             UnicodeString output;
    242             output.remove();
    243 
    244             if(useDate) {
    245 //                cal->setTime(fromDate, status);
    246 //                if(U_FAILURE(status)) {
    247 //                    errln("case %d: could not set time on calendar: %s", n, u_errorName(status));
    248 //                    continue;
    249 //                }
    250                 format->format(fromDate, output, pos, status);
    251             } else {
    252                 fromSet.setOnCalendar(cal, status);
    253                 if(U_FAILURE(status)) {
    254                     errln("case %d: could not set fields on calendar: %s", n, u_errorName(status));
    255                     continue;
    256                 }
    257                 format->format(*cal, output, pos);
    258             }
    259 
    260             // check erro result from 'format'
    261             if(U_FAILURE(status)) {
    262                 errln("case %d: could not format(): %s", n, u_errorName(status)); // TODO: use 'pos'
    263             }
    264 //            if(pos.getBeginIndex()==0 && pos.getEndIndex()==0) { // TODO: more precise error?
    265 //                errln("WARNING: case %d: format's pos returned (0,0) - error ??", n);
    266 //            }
    267 
    268             if(output == expectStr) {
    269                 logln(caseString+": format: SUCCESS! "+UnicodeString("expect=output=")+output);
    270             } else {
    271                 UnicodeString result;
    272                 UnicodeString result2;
    273                 errln(caseString+": format:  output!=expectStr, got " + *udbg_escape(output, &result) + " expected " + *udbg_escape(expectStr, &result2));
    274             }
    275         } else {
    276             cal->clear();
    277             ParsePosition pos;
    278             format->parse(expectStr,*cal,pos);
    279             if(useDate) {
    280                 UDate gotDate = cal->getTime(status);
    281                 if(U_FAILURE(status)) {
    282                     errln(caseString+": parse: could not get time on calendar: "+UnicodeString(u_errorName(status)));
    283                     continue;
    284                 }
    285                 if(gotDate == fromDate) {
    286                     logln(caseString+": parse: SUCCESS! "+UnicodeString("gotDate=parseDate=")+expectStr);
    287                 } else {
    288                     UnicodeString expectDateStr, gotDateStr;
    289                     basicFmt.format(fromDate,expectDateStr);
    290                     basicFmt.format(gotDate,gotDateStr);
    291                     errln(caseString+": parse: FAIL. parsed '"+expectStr+"' and got "+gotDateStr+", expected " + expectDateStr);
    292                 }
    293             } else {
    294 //                Calendar *cal2 = cal->clone();
    295 //                cal2->clear();
    296 //                fromSet.setOnCalendar(cal2, status);
    297                 if(U_FAILURE(status)) {
    298                     errln("case %d: parse: could not set fields on calendar: %s", n, u_errorName(status));
    299                     continue;
    300                 }
    301 
    302                 CalendarFieldsSet diffSet;
    303 //                diffSet.clear();
    304                 if (!fromSet.matches(cal, diffSet, status)) {
    305                     UnicodeString diffs = diffSet.diffFrom(fromSet, status);
    306                     errln((UnicodeString)"FAIL: "+caseString
    307                             +", Differences: '"+ diffs
    308                             +"', status: "+ u_errorName(status));
    309                 } else if (U_FAILURE(status)) {
    310                     errln("FAIL: "+caseString+" parse SET SOURCE calendar Failed to match: "
    311                             +u_errorName(status));
    312                 } else {
    313                     logln("PASS: "+caseString+" parse.");
    314                 }
    315 
    316 
    317 
    318             }
    319         }
    320         delete cal;
    321         delete format;
    322 
    323     }
    324 //    delete basicFmt;
    325 }
    326 
    327 void DataDrivenFormatTest::processTest(TestData *testData) {
    328     //Format *cal= NULL;
    329     //const UChar *arguments= NULL;
    330     //int32_t argLen = 0;
    331     char testType[256];
    332     const DataMap *settings= NULL;
    333     //const UChar *type= NULL;
    334     UErrorCode status = U_ZERO_ERROR;
    335     UnicodeString testSetting;
    336     int n = 0;
    337     while (testData->nextSettings(settings, status)) {
    338         status = U_ZERO_ERROR;
    339         // try to get a locale
    340         testSetting = settings->getString("Type", status);
    341         if (U_SUCCESS(status)) {
    342             if ((++n)>0) {
    343                 logln("---");
    344             }
    345             logln(testSetting + "---");
    346             testSetting.extract(0, testSetting.length(), testType, "");
    347         } else {
    348             errln("Unable to extract 'Type'. Skipping..");
    349             continue;
    350         }
    351 
    352         if (!strcmp(testType, "date_format")) {
    353             testConvertDate(testData, settings, true);
    354         } else if (!strcmp(testType, "date_parse")) {
    355             testConvertDate(testData, settings, false);
    356         } else {
    357             errln("Unknown type: %s", testType);
    358         }
    359     }
    360 }
    361 
    362 #endif
    363