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
30DataDrivenCalendarTest::DataDrivenCalendarTest() {
31    UErrorCode status = U_ZERO_ERROR;
32    driver = TestDataModule::getTestDataModule("calendar", *this, status);
33}
34
35DataDrivenCalendarTest::~DataDrivenCalendarTest() {
36    delete driver;
37}
38
39void 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
71void 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
287void 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
364void 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
448void 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