1 /********************************************************************
3 * Copyright (c) 1997-2010,2012, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************/
7 /***********************************************************************
9 * Date Name Description
10 * 07/09/2007 srl Copied from dadrcoll.cpp
11 ***********************************************************************/
13 #include "unicode/utypes.h"
15 #if !UCONFIG_NO_FORMATTING
17 #include "unicode/tstdtmod.h"
20 #include "unicode/calendar.h"
23 #include "unicode/schriter.h"
24 #include "unicode/regex.h"
25 #include "unicode/smpdtfmt.h"
32 DataDrivenFormatTest::DataDrivenFormatTest() {
33 UErrorCode status
= U_ZERO_ERROR
;
34 driver
= TestDataModule::getTestDataModule("format", *this, status
);
37 DataDrivenFormatTest::~DataDrivenFormatTest() {
41 void DataDrivenFormatTest::runIndexedTest(int32_t index
, UBool exec
,
42 const char* &name
, char* /*par */) {
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
));
60 processTest(testData
);
67 dataerrln("format/DataDriven*Test data (format.res) not initialized!");
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
84 "en_US@calendar=gregorian",
86 "DATE=SHORT,TIME=SHORT",
87 "ERA=1,YEAR=2007,MONTH=AUGUST,DATE=8,HOUR=18,MINUTE=54,SECOND=12",
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
100 UErrorCode status
= U_ZERO_ERROR
;
101 SimpleDateFormat
basicFmt(UnicodeString("EEE MMM dd yyyy / YYYY'-W'ww-ee"),
103 if (U_FAILURE(status
)) {
104 dataerrln("FAIL: Couldn't create basic SimpleDateFormat: %s",
105 u_errorName(status
));
109 const DataMap
*currentCase
= NULL
;
110 // Start the processing
112 while (testData
->nextCase(currentCase
, status
)) {
113 char calLoc
[256] = "";
114 DateTimeStyleSet styleSet
;
115 UnicodeString pattern
;
116 UBool usePattern
= FALSE
;
117 CalendarFieldsSet fromSet
;
119 UBool useDate
= FALSE
;
121 UDate now
= Calendar::getNow();
126 sprintf(theCase
, "case %d:", n
);
127 UnicodeString
caseString(theCase
, "");
130 UnicodeString locale
= currentCase
->getString("locale", status
);
131 if (U_FAILURE(status
)) {
132 errln("case %d: No 'locale' line.", n
);
135 UnicodeString zone
= currentCase
->getString("zone", status
);
136 if (U_FAILURE(status
)) {
137 errln("case %d: No 'zone' line.", n
);
140 UnicodeString spec
= currentCase
->getString("spec", status
);
141 if(U_FAILURE(status
)) {
142 errln("case %d: No 'spec' line.", n
);
145 UnicodeString date
= currentCase
->getString("date", status
);
146 if(U_FAILURE(status
)) {
147 errln("case %d: No 'date' line.", n
);
150 UnicodeString expectStr
= currentCase
->getString("str", status
);
151 if(U_FAILURE(status
)) {
152 errln("case %d: No 'str' line.", n
);
156 DateFormat
*format
= NULL
;
159 locale
.extract(0, locale
.length(), calLoc
, (const char*)0); // default codepage. Invariant codepage doesn't have '@'!
161 if(spec
.startsWith(kPATTERN
)) {
162 pattern
= UnicodeString(spec
,kPATTERN
.length());
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
));
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
));
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
);
181 Calendar
*cal
= Calendar::createInstance(loc
, status
);
182 if(U_FAILURE(status
)) {
183 errln("case %d: could not create calendar from %s", n
, calLoc
);
186 if (zone
.length() > 0) {
187 TimeZone
* tz
= TimeZone::createTimeZone(zone
);
188 cal
->setTimeZone(*tz
);
189 format
->setTimeZone(*tz
);
194 if(date
.startsWith(kMILLIS
)) {
195 UnicodeString millis
= UnicodeString(date
, kMILLIS
.length());
197 fromDate
= udbg_stod(millis
);
198 } else if(date
.startsWith(kRELATIVE_MILLIS
)) {
199 UnicodeString millis
= UnicodeString(date
, kRELATIVE_MILLIS
.length());
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
));
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
);
218 cal
->set((UCalendarDateFields
)q
,
219 fromSet
.get((UCalendarDateFields
)q
));
221 //int32_t newv = cal->get((UCalendarDateFields)q, status);
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
));
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
));
237 // logln((UnicodeString)"#"+n+" "+locale+"/"+from+" >>> "+toCalLoc+"/"
240 UnicodeString output
;
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));
249 format
->format(fromDate
, output
, pos
, status
);
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
));
256 format
->format(*cal
, output
, pos
);
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'
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);
267 if(output
== expectStr
) {
268 logln(caseString
+": format: SUCCESS! "+UnicodeString("expect=output=")+output
);
270 UnicodeString result
;
271 UnicodeString result2
;
272 errln(caseString
+": format: output!=expectStr, got " + *udbg_escape(output
, &result
) + " expected " + *udbg_escape(expectStr
, &result2
));
277 format
->parse(expectStr
,*cal
,pos
);
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
)));
284 if(gotDate
== fromDate
) {
285 logln(caseString
+": parse: SUCCESS! "+UnicodeString("gotDate=parseDate=")+expectStr
);
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
);
293 // Calendar *cal2 = cal->clone();
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
));
301 CalendarFieldsSet diffSet
;
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
));
312 logln("PASS: "+caseString
+" parse.");
326 void DataDrivenFormatTest::processTest(TestData
*testData
) {
328 //const UChar *arguments= NULL;
329 //int32_t argLen = 0;
331 const DataMap
*settings
= NULL
;
332 //const UChar *type= NULL;
333 UErrorCode status
= U_ZERO_ERROR
;
334 UnicodeString testSetting
;
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
)) {
344 logln(testSetting
+ "---");
345 testSetting
.extract(0, testSetting
.length(), testType
, "");
347 errln("Unable to extract 'Type'. Skipping..");
351 if (!strcmp(testType
, "date_format")) {
352 testConvertDate(testData
, settings
, true);
353 } else if (!strcmp(testType
, "date_parse")) {
354 testConvertDate(testData
, settings
, false);
356 errln("Unknown type: %s", testType
);