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 "dadrcal.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 
28 #include <stdio.h>
29 
DataDrivenCalendarTest()30 DataDrivenCalendarTest::DataDrivenCalendarTest() {
31     UErrorCode status = U_ZERO_ERROR;
32     driver = TestDataModule::getTestDataModule("calendar", *this, status);
33 }
34 
~DataDrivenCalendarTest()35 DataDrivenCalendarTest::~DataDrivenCalendarTest() {
36     delete driver;
37 }
38 
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)39 void DataDrivenCalendarTest::runIndexedTest(int32_t index, UBool exec,
40         const char* &name, char* /*par */) {
41     if (driver != NULL) {
42         if (exec) {
43             //  logln("Begin ");
44         }
45         const DataMap *info= NULL;
46         UErrorCode status= U_ZERO_ERROR;
47         TestData *testData = driver->createTestData(index, status);
48         if (U_SUCCESS(status)) {
49             name = testData->getName();
50             if (testData->getInfo(info, status)) {
51                 log(info->getString("Description", status));
52             }
53             if (exec) {
54                 log(name);
55                 logln("---");
56                 logln("");
57 
58                 processTest(testData);
59             }
60             delete testData;
61         } else {
62             name = "";
63         }
64     } else {
65         dataerrln("format/DataDriven*Test data (calendar.res) not initialized!");
66         name = "";
67     }
68 
69 }
70 
testOps(TestData * testData,const DataMap *)71 void DataDrivenCalendarTest::testOps(TestData *testData,
72         const DataMap * /*settings*/) {
73     UErrorCode status = U_ZERO_ERROR;
74     UBool useDate = FALSE; // TODO
75     UnicodeString kMILLIS("MILLIS="); // TODO: static
76     UDate fromDate = 0; // TODO
77     UDate toDate = 0;
78 
79     const DataMap *currentCase= NULL;
80     char toCalLoc[256] = "";
81 
82     // TODO: static strings?
83     const UnicodeString kADD("add", "");
84     const UnicodeString kROLL("roll", "");
85 
86     // Get 'from' time
87     CalendarFieldsSet fromSet, toSet, paramsSet, diffSet;
88     SimpleDateFormat fmt(UnicodeString("EEE MMM dd yyyy / YYYY'-W'ww-ee"),
89             status);
90     if (U_FAILURE(status)) {
91         dataerrln("FAIL: Couldn't create SimpleDateFormat: %s",
92                 u_errorName(status));
93         return;
94     }
95     // Start the processing
96     int n = 0;
97     while (testData->nextCase(currentCase, status)) {
98         ++n;
99         Calendar *toCalendar= NULL;
100         Calendar *fromCalendar= NULL;
101 
102         // load parameters
103         char theCase[200];
104         sprintf(theCase, "[case %d]", n);
105         UnicodeString caseString(theCase, "");
106         // build to calendar
107         //             Headers { "locale","from","operation","params","to" }
108         // #1 locale
109         const char *param = "locale";
110         UnicodeString locale;
111         UnicodeString testSetting = currentCase->getString(param, status);
112         if (U_FAILURE(status)) {
113             errln(caseString+": Unable to get param '"+param+"' "
114                     + UnicodeString(" - "));
115             continue;
116         }
117         testSetting.extract(0, testSetting.length(), toCalLoc, (const char*)0);
118         fromCalendar = Calendar::createInstance(toCalLoc, status);
119         if (U_FAILURE(status)) {
120             errln(caseString+": Unable to instantiate calendar for "
121                     +testSetting);
122             continue;
123         }
124 
125         fromSet.clear();
126         // #2 'from' info
127         param = "from";
128         UnicodeString from = testSetting=currentCase->getString(param, status);
129         if (U_FAILURE(status)) {
130             errln(caseString+": Unable to get parameter '"+param+"' "
131                     + UnicodeString(" - "));
132             continue;
133         }
134 
135         if(from.startsWith(kMILLIS)){
136         	UnicodeString millis = UnicodeString(from, kMILLIS.length());
137         	useDate = TRUE;
138         	fromDate = udbg_stod(millis);
139         } else if(fromSet.parseFrom(testSetting, status)<0 || U_FAILURE(status)){
140         	errln(caseString+": Failed to parse '"+param+"' parameter: "
141         	                    +testSetting);
142         	            continue;
143         }
144 
145         // #4 'operation' info
146         param = "operation";
147         UnicodeString operation = testSetting=currentCase->getString(param,
148                 status);
149         if (U_FAILURE(status)) {
150             errln(caseString+": Unable to get parameter '"+param+"' "
151                     + UnicodeString(" - "));
152             continue;
153         }
154         if (U_FAILURE(status)) {
155             errln(caseString+": Failed to parse '"+param+"' parameter: "
156                     +testSetting);
157             continue;
158         }
159 
160         paramsSet.clear();
161         // #3 'params' info
162         param = "params";
163         UnicodeString params = testSetting
164                 =currentCase->getString(param, status);
165         if (U_FAILURE(status)) {
166             errln(caseString+": Unable to get parameter '"+param+"' "
167                     + UnicodeString(" - "));
168             continue;
169         }
170         paramsSet.parseFrom(testSetting, status); // parse with inheritance.
171         if (U_FAILURE(status)) {
172             errln(caseString+": Failed to parse '"+param+"' parameter: "
173                     +testSetting);
174             continue;
175         }
176 
177         toSet.clear();
178         // #4 'to' info
179         param = "to";
180         UnicodeString to = testSetting=currentCase->getString(param, status);
181         if (U_FAILURE(status)) {
182             errln(caseString+": Unable to get parameter '"+param+"' "
183                     + UnicodeString(" - "));
184             continue;
185         }
186         if(to.startsWith(kMILLIS)){
187         	UnicodeString millis = UnicodeString(to, kMILLIS.length());
188             useDate = TRUE;
189             toDate = udbg_stod(millis);
190         } else if(toSet.parseFrom(testSetting, &fromSet, status)<0 || U_FAILURE(status)){
191             errln(caseString+": Failed to parse '"+param+"' parameter: "
192                    +testSetting);
193             continue;
194         }
195 
196         UnicodeString caseContentsString = locale+":  from "+from+": "
197                 +operation +" [[[ "+params+" ]]]   >>> "+to;
198         logln(caseString+": "+caseContentsString);
199 
200         // ------
201         // now, do it.
202 
203         /// prepare calendar
204         if(useDate){
205         	fromCalendar->setTime(fromDate, status);
206         	if (U_FAILURE(status)) {
207         	        	            errln(caseString+" FAIL: Failed to set time on Source calendar: "
208         	        	                    + u_errorName(status));
209         	        	            return;
210         	        	        }
211         } else {
212         	fromSet.setOnCalendar(fromCalendar, status);
213         	        if (U_FAILURE(status)) {
214         	            errln(caseString+" FAIL: Failed to set on Source calendar: "
215         	                    + u_errorName(status));
216         	            return;
217         	        }
218         }
219 
220         diffSet.clear();
221         // Is the calendar sane after being set?
222         if (!fromSet.matches(fromCalendar, diffSet, status)) {
223             UnicodeString diffs = diffSet.diffFrom(fromSet, status);
224             errln((UnicodeString)"FAIL: "+caseString
225                     +", SET SOURCE calendar was not set: Differences: "+ diffs
226                     +"', status: "+ u_errorName(status));
227         } else if (U_FAILURE(status)) {
228             errln("FAIL: "+caseString+" SET SOURCE calendar Failed to match: "
229                     +u_errorName(status));
230         } else {
231             logln("PASS: "+caseString+" SET SOURCE calendar match.");
232         }
233 
234         // to calendar - copy of from calendar
235         toCalendar = fromCalendar->clone();
236 
237         /// perform op
238         for (int q=0; q<UCAL_FIELD_COUNT; q++) {
239             if (paramsSet.isSet((UCalendarDateFields)q)) {
240                 if (operation == kROLL) {
241                     toCalendar->roll((UCalendarDateFields)q,
242                             paramsSet.get((UCalendarDateFields)q), status);
243                 } else if (operation == kADD) {
244                     toCalendar->add((UCalendarDateFields)q,
245                             paramsSet.get((UCalendarDateFields)q), status);
246                 } else {
247                     errln(caseString+ " FAIL: unknown operation "+ operation);
248                 }
249                 logln(operation + " of "+ paramsSet.get((UCalendarDateFields)q)
250                         +" -> "+u_errorName(status));
251             }
252         }
253         if (U_FAILURE(status)) {
254             errln(caseString+" FAIL: after "+operation+" of "+params+" -> "
255                     +u_errorName(status));
256             continue;
257         }
258 
259         // now - what's the result?
260         diffSet.clear();
261 
262         if(useDate){
263         	if(!(toCalendar->getTime(status)==toDate) || U_FAILURE(status)){
264         		errln("FAIL: "+caseString+" Match operation had an error: "
265         		                    +u_errorName(status));
266         	}else{
267         		logln(caseString + " SUCCESS: got=expected="+toDate);
268         		logln("PASS: "+caseString+" matched!");
269         	}
270         } else if (!toSet.matches(toCalendar, diffSet, status)) {
271             UnicodeString diffs = diffSet.diffFrom(toSet, status);
272             errln((UnicodeString)"FAIL: "+caseString+" - , "+caseContentsString
273                     +" Differences: "+ diffs +"', status: "
274                     + u_errorName(status));
275         }else if (U_FAILURE(status)) {
276             errln("FAIL: "+caseString+" Match operation had an error: "
277                     +u_errorName(status));
278         }else {
279             logln("PASS: "+caseString+" matched!");
280         }
281 
282         delete fromCalendar;
283         delete toCalendar;
284     }
285 }
286 
testConvert(int32_t n,const CalendarFieldsSet & fromSet,Calendar * fromCalendar,const CalendarFieldsSet & toSet,Calendar * toCalendar,UBool forward)287 void DataDrivenCalendarTest::testConvert(int32_t n,
288         const CalendarFieldsSet &fromSet, Calendar *fromCalendar,
289         const CalendarFieldsSet &toSet, Calendar *toCalendar, UBool forward) {
290     UErrorCode status = U_ZERO_ERROR;
291     UnicodeString thisString = (UnicodeString)"#"+n+" "+(forward ? "forward"
292             : "reverse")+" "+fromCalendar->getType()+"->"+toCalendar->getType();
293 
294     fromCalendar->clear();
295 
296     fromSet.setOnCalendar(fromCalendar, status);
297     if (U_FAILURE(status)) {
298         errln("FAIL: Failed to set on Source calendar: %s", u_errorName(status));
299         return;
300     }
301 
302     CalendarFieldsSet diffSet;
303 
304     diffSet.clear();
305     // Is the calendar sane at the first?
306     if (!fromSet.matches(fromCalendar, diffSet, status)) {
307         UnicodeString diffs = diffSet.diffFrom(fromSet, status);
308         errln((UnicodeString)"FAIL: "+thisString
309                 +", SOURCE calendar was not set: Differences: "+ diffs
310                 +"', status: "+ u_errorName(status));
311     } else if (U_FAILURE(status)) {
312         errln("FAIL: "+thisString+" SOURCE calendar Failed to match: "
313                 +u_errorName(status));
314     } else {
315         logln("PASS: "+thisString+" SOURCE calendar match.");
316     }
317 
318     //logln("Set Source calendar: " + from);
319 
320     UDate fromTime = fromCalendar->getTime(status);
321     if (U_FAILURE(status)) {
322         errln("FAIL: Failed to get Source time: %s", u_errorName(status));
323         return;
324     }
325 
326     diffSet.clear();
327     // Is the calendar sane after being set?
328     if (!fromSet.matches(fromCalendar, diffSet, status)) {
329         UnicodeString diffs = diffSet.diffFrom(fromSet, status);
330         errln((UnicodeString)"FAIL: "+thisString
331                 +", SET SOURCE calendar was not set: Differences: "+ diffs
332                 +"', status: "+ u_errorName(status));
333     } else if (U_FAILURE(status)) {
334         errln("FAIL: "+thisString+" SET SOURCE calendar Failed to match: "
335                 +u_errorName(status));
336     } else {
337         logln("PASS: "+thisString+" SET SOURCE calendar match.");
338     }
339 
340     toCalendar->clear();
341     toCalendar->setTime(fromTime, status);
342     if (U_FAILURE(status)) {
343         errln("FAIL: Failed to set Target time: %s", u_errorName(status));
344         return;
345     }
346 
347     diffSet.clear();
348     if (!toSet.matches(toCalendar, diffSet, status)) {
349         UnicodeString diffs = diffSet.diffFrom(toSet, status);
350         errln((UnicodeString)"FAIL: "+thisString+", Differences: "+ diffs
351                 +"', status: "+ u_errorName(status));
352         SimpleDateFormat fmt(UnicodeString("EEE MMM dd yyyy G"), status);
353         UnicodeString fromString;
354         fmt.format(fromTime, fromString);
355         logln("Source Time: "+fromString+", Source Calendar: "
356                 +fromCalendar->getType());
357     } else if (U_FAILURE(status)) {
358         errln("FAIL: "+thisString+" Failed to match: "+u_errorName(status));
359     } else {
360         logln("PASS: "+thisString+" match.");
361     }
362 }
363 
testConvert(TestData * testData,const DataMap * settings,UBool forward)364 void DataDrivenCalendarTest::testConvert(TestData *testData,
365         const DataMap *settings, UBool forward) {
366     UErrorCode status = U_ZERO_ERROR;
367     Calendar *toCalendar= NULL;
368     const DataMap *currentCase= NULL;
369     char toCalLoc[256] = "";
370     char fromCalLoc[256] = "";
371     // build to calendar
372     UnicodeString testSetting = settings->getString("ToCalendar", status);
373     if (U_SUCCESS(status)) {
374         testSetting.extract(0, testSetting.length(), toCalLoc, (const char*)0);
375         toCalendar = Calendar::createInstance(toCalLoc, status);
376         if (U_FAILURE(status)) {
377             dataerrln(UnicodeString("Unable to instantiate ToCalendar for ")+testSetting);
378             return;
379         }
380     }
381 
382     CalendarFieldsSet fromSet, toSet, diffSet;
383     SimpleDateFormat fmt(UnicodeString("EEE MMM dd yyyy / YYYY'-W'ww-ee"),
384             status);
385     if (U_FAILURE(status)) {
386         errcheckln(status, "FAIL: Couldn't create SimpleDateFormat: %s",
387                 u_errorName(status));
388         return;
389     }
390     // Start the processing
391     int n = 0;
392     while (testData->nextCase(currentCase, status)) {
393         ++n;
394         Calendar *fromCalendar= NULL;
395         UnicodeString locale = currentCase->getString("locale", status);
396         if (U_SUCCESS(status)) {
397             locale.extract(0, locale.length(), fromCalLoc, (const char*)0); // default codepage.  Invariant codepage doesn't have '@'!
398             fromCalendar = Calendar::createInstance(fromCalLoc, status);
399             if (U_FAILURE(status)) {
400                 errln("Unable to instantiate fromCalendar for "+locale);
401                 return;
402             }
403         } else {
404             errln("No 'locale' line.");
405             continue;
406         }
407 
408         fromSet.clear();
409         toSet.clear();
410 
411         UnicodeString from = currentCase->getString("from", status);
412         if (U_FAILURE(status)) {
413             errln("No 'from' line.");
414             continue;
415         }
416         fromSet.parseFrom(from, status);
417         if (U_FAILURE(status)) {
418             errln("Failed to parse 'from' parameter: "+from);
419             continue;
420         }
421         UnicodeString to = currentCase->getString("to", status);
422         if (U_FAILURE(status)) {
423             errln("No 'to' line.");
424             continue;
425         }
426         toSet.parseFrom(to, &fromSet, status);
427         if (U_FAILURE(status)) {
428             errln("Failed to parse 'to' parameter: "+to);
429             continue;
430         }
431 
432         // now, do it.
433         if (forward) {
434             logln((UnicodeString)"#"+n+" "+locale+"/"+from+" >>> "+toCalLoc+"/"
435                     +to);
436             testConvert(n, fromSet, fromCalendar, toSet, toCalendar, forward);
437         } else {
438             logln((UnicodeString)"#"+n+" "+locale+"/"+from+" <<< "+toCalLoc+"/"
439                     +to);
440             testConvert(n, toSet, toCalendar, fromSet, fromCalendar, forward);
441         }
442 
443         delete fromCalendar;
444     }
445     delete toCalendar;
446 }
447 
processTest(TestData * testData)448 void DataDrivenCalendarTest::processTest(TestData *testData) {
449     //Calendar *cal= NULL;
450     //const UChar *arguments= NULL;
451     //int32_t argLen = 0;
452     char testType[256];
453     const DataMap *settings= NULL;
454     //const UChar *type= NULL;
455     UErrorCode status = U_ZERO_ERROR;
456     UnicodeString testSetting;
457     int n = 0;
458     while (testData->nextSettings(settings, status)) {
459         status = U_ZERO_ERROR;
460         // try to get a locale
461         testSetting = settings->getString("Type", status);
462         if (U_SUCCESS(status)) {
463             if ((++n)>0) {
464                 logln("---");
465             }
466             logln(testSetting + "---");
467             testSetting.extract(0, testSetting.length(), testType, "");
468         } else {
469             errln("Unable to extract 'Type'. Skipping..");
470             continue;
471         }
472 
473         if (!strcmp(testType, "convert_fwd")) {
474             testConvert(testData, settings, true);
475         } else if (!strcmp(testType, "convert_rev")) {
476             testConvert(testData, settings, false);
477         } else if (!strcmp(testType, "ops")) {
478             testOps(testData, settings);
479         } else {
480             errln("Unknown type: %s", testType);
481         }
482     }
483 }
484 
485 #endif
486