• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /********************************************************************
2  * COPYRIGHT:
3  * Copyright (c) 1997-2010,2012, 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 
DataDrivenFormatTest()32 DataDrivenFormatTest::DataDrivenFormatTest() {
33     UErrorCode status = U_ZERO_ERROR;
34     driver = TestDataModule::getTestDataModule("format", *this, status);
35 }
36 
~DataDrivenFormatTest()37 DataDrivenFormatTest::~DataDrivenFormatTest() {
38     delete driver;
39 }
40 
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)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 
testConvertDate(TestData * testData,const DataMap *,UBool fmt)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         CalendarFieldsSet fromSet;
118         UDate fromDate = 0;
119         UBool useDate = FALSE;
120 
121         UDate now = Calendar::getNow();
122 
123         ++n;
124 
125         char theCase[200];
126         sprintf(theCase, "case %d:", n);
127         UnicodeString caseString(theCase, "");
128 
129         // load params
130         UnicodeString locale = currentCase->getString("locale", status);
131         if (U_FAILURE(status)) {
132             errln("case %d: No 'locale' line.", n);
133             continue;
134         }
135         UnicodeString zone = currentCase->getString("zone", status);
136         if (U_FAILURE(status)) {
137             errln("case %d: No 'zone' line.", n);
138             continue;
139         }
140         UnicodeString spec = currentCase->getString("spec", status);
141         if(U_FAILURE(status)) {
142             errln("case %d: No 'spec' line.", n);
143             continue;
144         }
145         UnicodeString date = currentCase->getString("date", status);
146         if(U_FAILURE(status)) {
147             errln("case %d: No 'date' line.", n);
148             continue;
149         }
150         UnicodeString expectStr= currentCase->getString("str", status);
151         if(U_FAILURE(status)) {
152             errln("case %d: No 'str' line.", n);
153             continue;
154         }
155 
156         DateFormat *format = NULL;
157 
158         // Process: 'locale'
159         locale.extract(0, locale.length(), calLoc, (const char*)0); // default codepage.  Invariant codepage doesn't have '@'!
160         Locale loc(calLoc);
161         if(spec.startsWith(kPATTERN)) {
162             pattern = UnicodeString(spec,kPATTERN.length());
163             usePattern = TRUE;
164             format = new SimpleDateFormat(pattern, loc, status);
165             if(U_FAILURE(status)) {
166                 errln("case %d: could not create SimpleDateFormat from pattern: %s", n, u_errorName(status));
167                 continue;
168             }
169         } else {
170             if(styleSet.parseFrom(spec, status)<0 || U_FAILURE(status)) {
171                 errln("case %d: could not parse spec as style fields: %s", n, u_errorName(status));
172                 continue;
173             }
174             format = DateFormat::createDateTimeInstance((DateFormat::EStyle)styleSet.getDateStyle(), (DateFormat::EStyle)styleSet.getTimeStyle(), loc);
175             if(format == NULL ) {
176                 errln("case %d: could not create SimpleDateFormat from styles.", n);
177                 continue;
178             }
179         }
180 
181         Calendar *cal = Calendar::createInstance(loc, status);
182         if(U_FAILURE(status)) {
183             errln("case %d: could not create calendar from %s", n, calLoc);
184         }
185 
186         if (zone.length() > 0) {
187             TimeZone * tz = TimeZone::createTimeZone(zone);
188             cal->setTimeZone(*tz);
189             format->setTimeZone(*tz);
190             delete tz;
191         }
192 
193         // parse 'date'
194         if(date.startsWith(kMILLIS)) {
195             UnicodeString millis = UnicodeString(date, kMILLIS.length());
196             useDate = TRUE;
197             fromDate = udbg_stod(millis);
198         } else if(date.startsWith(kRELATIVE_MILLIS)) {
199             UnicodeString millis = UnicodeString(date, kRELATIVE_MILLIS.length());
200             useDate = TRUE;
201             fromDate = udbg_stod(millis) + now;
202         } else if(date.startsWith(kRELATIVE_ADD)) {
203             UnicodeString add = UnicodeString(date, kRELATIVE_ADD.length());  // "add" is a string indicating which fields to add
204             if(fromSet.parseFrom(add, status)<0 || U_FAILURE(status)) {
205                 errln("case %d: could not parse date as RELATIVE_ADD calendar fields: %s", n, u_errorName(status));
206                 continue;
207             }
208             useDate=TRUE;
209             cal->clear();
210             cal->setTime(now, status);
211             for (int q=0; q<UCAL_FIELD_COUNT; q++) {
212                 if (fromSet.isSet((UCalendarDateFields)q)) {
213                     //int32_t oldv = cal->get((UCalendarDateFields)q, status);
214                     if (q == UCAL_DATE) {
215                         cal->add((UCalendarDateFields)q,
216                                     fromSet.get((UCalendarDateFields)q), status);
217                     } else {
218                         cal->set((UCalendarDateFields)q,
219                                     fromSet.get((UCalendarDateFields)q));
220                     }
221                     //int32_t newv = cal->get((UCalendarDateFields)q, status);
222                 }
223             }
224             fromDate = cal->getTime(status);
225             if(U_FAILURE(status)) {
226                 errln("case %d: could not apply date as RELATIVE_ADD calendar fields: %s", n, u_errorName(status));
227                 continue;
228             }
229         } else if(fromSet.parseFrom(date, status)<0 || U_FAILURE(status)) {
230             errln("case %d: could not parse date as calendar fields: %s", n, u_errorName(status));
231             continue;
232         }
233 
234         // now, do it.
235         if (fmt) {
236             FieldPosition pos;
237 //            logln((UnicodeString)"#"+n+" "+locale+"/"+from+" >>> "+toCalLoc+"/"
238 //                    +to);
239             cal->clear();
240             UnicodeString output;
241             output.remove();
242 
243             if(useDate) {
244 //                cal->setTime(fromDate, status);
245 //                if(U_FAILURE(status)) {
246 //                    errln("case %d: could not set time on calendar: %s", n, u_errorName(status));
247 //                    continue;
248 //                }
249                 format->format(fromDate, output, pos, status);
250             } else {
251                 fromSet.setOnCalendar(cal, status);
252                 if(U_FAILURE(status)) {
253                     errln("case %d: could not set fields on calendar: %s", n, u_errorName(status));
254                     continue;
255                 }
256                 format->format(*cal, output, pos);
257             }
258 
259             // check erro result from 'format'
260             if(U_FAILURE(status)) {
261                 errln("case %d: could not format(): %s", n, u_errorName(status)); // TODO: use 'pos'
262             }
263 //            if(pos.getBeginIndex()==0 && pos.getEndIndex()==0) { // TODO: more precise error?
264 //                errln("WARNING: case %d: format's pos returned (0,0) - error ??", n);
265 //            }
266 
267             if(output == expectStr) {
268                 logln(caseString+": format: SUCCESS! "+UnicodeString("expect=output=")+output);
269             } else {
270                 UnicodeString result;
271                 UnicodeString result2;
272                 errln(caseString+": format:  output!=expectStr, got " + *udbg_escape(output, &result) + " expected " + *udbg_escape(expectStr, &result2));
273             }
274         } else {
275             cal->clear();
276             ParsePosition pos;
277             format->parse(expectStr,*cal,pos);
278             if(useDate) {
279                 UDate gotDate = cal->getTime(status);
280                 if(U_FAILURE(status)) {
281                     errln(caseString+": parse: could not get time on calendar: "+UnicodeString(u_errorName(status)));
282                     continue;
283                 }
284                 if(gotDate == fromDate) {
285                     logln(caseString+": parse: SUCCESS! "+UnicodeString("gotDate=parseDate=")+expectStr);
286                 } else {
287                     UnicodeString expectDateStr, gotDateStr;
288                     basicFmt.format(fromDate,expectDateStr);
289                     basicFmt.format(gotDate,gotDateStr);
290                     errln(caseString+": parse: FAIL. parsed '"+expectStr+"' and got "+gotDateStr+", expected " + expectDateStr);
291                 }
292             } else {
293 //                Calendar *cal2 = cal->clone();
294 //                cal2->clear();
295 //                fromSet.setOnCalendar(cal2, status);
296                 if(U_FAILURE(status)) {
297                     errln("case %d: parse: could not set fields on calendar: %s", n, u_errorName(status));
298                     continue;
299                 }
300 
301                 CalendarFieldsSet diffSet;
302 //                diffSet.clear();
303                 if (!fromSet.matches(cal, diffSet, status)) {
304                     UnicodeString diffs = diffSet.diffFrom(fromSet, status);
305                     errln((UnicodeString)"FAIL: "+caseString
306                             +", Differences: '"+ diffs
307                             +"', status: "+ u_errorName(status));
308                 } else if (U_FAILURE(status)) {
309                     errln("FAIL: "+caseString+" parse SET SOURCE calendar Failed to match: "
310                             +u_errorName(status));
311                 } else {
312                     logln("PASS: "+caseString+" parse.");
313                 }
314 
315 
316 
317             }
318         }
319         delete cal;
320         delete format;
321 
322     }
323 //    delete basicFmt;
324 }
325 
processTest(TestData * testData)326 void DataDrivenFormatTest::processTest(TestData *testData) {
327     //Format *cal= NULL;
328     //const UChar *arguments= NULL;
329     //int32_t argLen = 0;
330     char testType[256];
331     const DataMap *settings= NULL;
332     //const UChar *type= NULL;
333     UErrorCode status = U_ZERO_ERROR;
334     UnicodeString testSetting;
335     int n = 0;
336     while (testData->nextSettings(settings, status)) {
337         status = U_ZERO_ERROR;
338         // try to get a locale
339         testSetting = settings->getString("Type", status);
340         if (U_SUCCESS(status)) {
341             if ((++n)>0) {
342                 logln("---");
343             }
344             logln(testSetting + "---");
345             testSetting.extract(0, testSetting.length(), testType, "");
346         } else {
347             errln("Unable to extract 'Type'. Skipping..");
348             continue;
349         }
350 
351         if (!strcmp(testType, "date_format")) {
352             testConvertDate(testData, settings, true);
353         } else if (!strcmp(testType, "date_parse")) {
354             testConvertDate(testData, settings, false);
355         } else {
356             errln("Unknown type: %s", testType);
357         }
358     }
359 }
360 
361 #endif
362