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