Home | History | Annotate | Download | only in intltest
      1 /********************************************************************
      2  * COPYRIGHT:
      3  * Copyright (c) 1997-2010, 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","spec", "date", "str"}
     77             // locale: locale including calendar type
     78             // spec:   either 'PATTERN=y mm h' etc, or 'DATE=SHORT,TIME=LONG'
     79             // date:   either an unsigned long (millis), or a calendar spec ERA=0,YEAR=1, etc.. applied to the calendar type specified by the locale
     80             // str:   the expected unicode string
     81             Cases {
     82                {
     83                     "en_US@calendar=gregorian",
     84                     "DATE=SHORT,TIME=SHORT",
     85                     "ERA=1,YEAR=2007,MONTH=AUGUST,DATE=8,HOUR=18,MINUTE=54,SECOND=12",
     86                     "8/8/2007 6:54pm"
     87                },
     88  * */
     89 
     90 
     91 void DataDrivenFormatTest::testConvertDate(TestData *testData,
     92         const DataMap * /* settings */, UBool fmt) {
     93     UnicodeString kPATTERN("PATTERN="); // TODO: static
     94     UnicodeString kMILLIS("MILLIS="); // TODO: static
     95     UnicodeString kRELATIVE_MILLIS("RELATIVE_MILLIS="); // TODO: static
     96     UnicodeString kRELATIVE_ADD("RELATIVE_ADD:"); // TODO: static
     97 
     98     UErrorCode status = U_ZERO_ERROR;
     99     SimpleDateFormat basicFmt(UnicodeString("EEE MMM dd yyyy / YYYY'-W'ww-ee"),
    100             status);
    101     if (U_FAILURE(status)) {
    102         dataerrln("FAIL: Couldn't create basic SimpleDateFormat: %s",
    103                 u_errorName(status));
    104         return;
    105     }
    106 
    107     const DataMap *currentCase= NULL;
    108     // Start the processing
    109     int n = 0;
    110     while (testData->nextCase(currentCase, status)) {
    111         char calLoc[256] = "";
    112         DateTimeStyleSet styleSet;
    113         UnicodeString pattern;
    114         UBool usePattern = FALSE;
    115         CalendarFieldsSet fromSet;
    116         UDate fromDate = 0;
    117         UBool useDate = FALSE;
    118 
    119         UDate now = Calendar::getNow();
    120 
    121         ++n;
    122 
    123         char theCase[200];
    124         sprintf(theCase, "case %d:", n);
    125         UnicodeString caseString(theCase, "");
    126 
    127         // load params
    128         UnicodeString locale = currentCase->getString("locale", status);
    129         if (U_FAILURE(status)) {
    130             errln("case %d: No 'locale' line.", n);
    131             continue;
    132         }
    133         UnicodeString spec = currentCase->getString("spec", status);
    134         if(U_FAILURE(status)) {
    135             errln("case %d: No 'spec' line.", n);
    136             continue;
    137         }
    138         UnicodeString date = currentCase->getString("date", status);
    139         if(U_FAILURE(status)) {
    140             errln("case %d: No 'date' line.", n);
    141             continue;
    142         }
    143         UnicodeString expectStr= currentCase->getString("str", status);
    144         if(U_FAILURE(status)) {
    145             errln("case %d: No 'str' line.", n);
    146             continue;
    147         }
    148 
    149         DateFormat *format = NULL;
    150 
    151         // Process: 'locale'
    152         locale.extract(0, locale.length(), calLoc, (const char*)0); // default codepage.  Invariant codepage doesn't have '@'!
    153         Locale loc(calLoc);
    154         if(spec.startsWith(kPATTERN)) {
    155             pattern = UnicodeString(spec,kPATTERN.length());
    156             usePattern = TRUE;
    157             format = new SimpleDateFormat(pattern, loc, status);
    158             if(U_FAILURE(status)) {
    159                 errln("case %d: could not create SimpleDateFormat from pattern: %s", n, u_errorName(status));
    160                 continue;
    161             }
    162         } else {
    163             if(styleSet.parseFrom(spec, status)<0 || U_FAILURE(status)) {
    164                 errln("case %d: could not parse spec as style fields: %s", n, u_errorName(status));
    165                 continue;
    166             }
    167             format = DateFormat::createDateTimeInstance((DateFormat::EStyle)styleSet.getDateStyle(), (DateFormat::EStyle)styleSet.getTimeStyle(), loc);
    168             if(format == NULL ) {
    169                 errln("case %d: could not create SimpleDateFormat from styles.", n);
    170                 continue;
    171             }
    172         }
    173 
    174         Calendar *cal = Calendar::createInstance(loc, status);
    175         if(U_FAILURE(status)) {
    176             errln("case %d: could not create calendar from %s", n, calLoc);
    177         }
    178 
    179         // parse 'date'
    180         if(date.startsWith(kMILLIS)) {
    181             UnicodeString millis = UnicodeString(date, kMILLIS.length());
    182             useDate = TRUE;
    183             fromDate = udbg_stod(millis);
    184         } else if(date.startsWith(kRELATIVE_MILLIS)) {
    185             UnicodeString millis = UnicodeString(date, kRELATIVE_MILLIS.length());
    186             useDate = TRUE;
    187             fromDate = udbg_stod(millis) + now;
    188         } else if(date.startsWith(kRELATIVE_ADD)) {
    189             UnicodeString add = UnicodeString(date, kRELATIVE_ADD.length());  // "add" is a string indicating which fields to add
    190             if(fromSet.parseFrom(add, status)<0 || U_FAILURE(status)) {
    191                 errln("case %d: could not parse date as RELATIVE_ADD calendar fields: %s", n, u_errorName(status));
    192                 continue;
    193             }
    194             useDate=TRUE;
    195             cal->clear();
    196             cal->setTime(now, status);
    197             for (int q=0; q<UCAL_FIELD_COUNT; q++) {
    198                 if (fromSet.isSet((UCalendarDateFields)q)) {
    199                     //int32_t oldv = cal->get((UCalendarDateFields)q, status);
    200                     cal->add((UCalendarDateFields)q,
    201                                 fromSet.get((UCalendarDateFields)q), status);
    202                     //int32_t newv = cal->get((UCalendarDateFields)q, status);
    203                 }
    204             }
    205             fromDate = cal->getTime(status);
    206             if(U_FAILURE(status)) {
    207                 errln("case %d: could not apply date as RELATIVE_ADD calendar fields: %s", n, u_errorName(status));
    208                 continue;
    209             }
    210         } else if(fromSet.parseFrom(date, status)<0 || U_FAILURE(status)) {
    211             errln("case %d: could not parse date as calendar fields: %s", n, u_errorName(status));
    212             continue;
    213         }
    214 
    215         // now, do it.
    216         if (fmt) {
    217             FieldPosition pos;
    218 //            logln((UnicodeString)"#"+n+" "+locale+"/"+from+" >>> "+toCalLoc+"/"
    219 //                    +to);
    220             cal->clear();
    221             UnicodeString output;
    222             output.remove();
    223 
    224             if(useDate) {
    225 //                cal->setTime(fromDate, status);
    226 //                if(U_FAILURE(status)) {
    227 //                    errln("case %d: could not set time on calendar: %s", n, u_errorName(status));
    228 //                    continue;
    229 //                }
    230                 format->format(fromDate, output, pos, status);
    231             } else {
    232                 fromSet.setOnCalendar(cal, status);
    233                 if(U_FAILURE(status)) {
    234                     errln("case %d: could not set fields on calendar: %s", n, u_errorName(status));
    235                     continue;
    236                 }
    237                 format->format(*cal, output, pos);
    238             }
    239 
    240             // check erro result from 'format'
    241             if(U_FAILURE(status)) {
    242                 errln("case %d: could not format(): %s", n, u_errorName(status)); // TODO: use 'pos'
    243             }
    244 //            if(pos.getBeginIndex()==0 && pos.getEndIndex()==0) { // TODO: more precise error?
    245 //                errln("WARNING: case %d: format's pos returned (0,0) - error ??", n);
    246 //            }
    247 
    248             if(output == expectStr) {
    249                 logln(caseString+": format: SUCCESS! "+UnicodeString("expect=output=")+output);
    250             } else {
    251                 UnicodeString result;
    252                 UnicodeString result2;
    253                 errln(caseString+": format:  output!=expectStr, got " + *udbg_escape(output, &result) + " expected " + *udbg_escape(expectStr, &result2));
    254             }
    255         } else {
    256             cal->clear();
    257             ParsePosition pos;
    258             format->parse(expectStr,*cal,pos);
    259             if(useDate) {
    260                 UDate gotDate = cal->getTime(status);
    261                 if(U_FAILURE(status)) {
    262                     errln(caseString+": parse: could not get time on calendar: "+UnicodeString(u_errorName(status)));
    263                     continue;
    264                 }
    265                 if(gotDate == fromDate) {
    266                     logln(caseString+": parse: SUCCESS! "+UnicodeString("gotDate=parseDate=")+expectStr);
    267                 } else {
    268                     UnicodeString expectDateStr, gotDateStr;
    269                     basicFmt.format(fromDate,expectDateStr);
    270                     basicFmt.format(gotDate,gotDateStr);
    271                     errln(caseString+": parse: FAIL. parsed '"+expectStr+"' and got "+gotDateStr+", expected " + expectDateStr);
    272                 }
    273             } else {
    274 //                Calendar *cal2 = cal->clone();
    275 //                cal2->clear();
    276 //                fromSet.setOnCalendar(cal2, status);
    277                 if(U_FAILURE(status)) {
    278                     errln("case %d: parse: could not set fields on calendar: %s", n, u_errorName(status));
    279                     continue;
    280                 }
    281 
    282                 CalendarFieldsSet diffSet;
    283 //                diffSet.clear();
    284                 if (!fromSet.matches(cal, diffSet, status)) {
    285                     UnicodeString diffs = diffSet.diffFrom(fromSet, status);
    286                     errln((UnicodeString)"FAIL: "+caseString
    287                             +", Differences: '"+ diffs
    288                             +"', status: "+ u_errorName(status));
    289                 } else if (U_FAILURE(status)) {
    290                     errln("FAIL: "+caseString+" parse SET SOURCE calendar Failed to match: "
    291                             +u_errorName(status));
    292                 } else {
    293                     logln("PASS: "+caseString+" parse.");
    294                 }
    295 
    296 
    297 
    298             }
    299         }
    300         delete cal;
    301         delete format;
    302 
    303     }
    304 //    delete basicFmt;
    305 }
    306 
    307 void DataDrivenFormatTest::processTest(TestData *testData) {
    308     //Format *cal= NULL;
    309     //const UChar *arguments= NULL;
    310     //int32_t argLen = 0;
    311     char testType[256];
    312     const DataMap *settings= NULL;
    313     //const UChar *type= NULL;
    314     UErrorCode status = U_ZERO_ERROR;
    315     UnicodeString testSetting;
    316     int n = 0;
    317     while (testData->nextSettings(settings, status)) {
    318         status = U_ZERO_ERROR;
    319         // try to get a locale
    320         testSetting = settings->getString("Type", status);
    321         if (U_SUCCESS(status)) {
    322             if ((++n)>0) {
    323                 logln("---");
    324             }
    325             logln(testSetting + "---");
    326             testSetting.extract(0, testSetting.length(), testType, "");
    327         } else {
    328             errln("Unable to extract 'Type'. Skipping..");
    329             continue;
    330         }
    331 
    332         if (!strcmp(testType, "date_format")) {
    333             testConvertDate(testData, settings, true);
    334         } else if (!strcmp(testType, "date_parse")) {
    335             testConvertDate(testData, settings, false);
    336         } else {
    337             errln("Unknown type: %s", testType);
    338         }
    339     }
    340 }
    341 
    342 #endif
    343