• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
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","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 
testConvertDate(TestData * testData,const DataMap *,UBool fmt)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 
processTest(TestData * testData)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