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