1 /********************************************************************
3 * Copyright (c) 1997-2013 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 (void)usePattern
; // Suppress unused warning.
118 CalendarFieldsSet fromSet
;
120 UBool useDate
= FALSE
;
122 UDate now
= Calendar::getNow();
127 sprintf(theCase
, "case %d:", n
);
128 UnicodeString
caseString(theCase
, "");
131 UnicodeString locale
= currentCase
->getString("locale", status
);
132 if (U_FAILURE(status
)) {
133 errln("case %d: No 'locale' line.", n
);
136 UnicodeString zone
= currentCase
->getString("zone", status
);
137 if (U_FAILURE(status
)) {
138 errln("case %d: No 'zone' line.", n
);
141 UnicodeString spec
= currentCase
->getString("spec", status
);
142 if(U_FAILURE(status
)) {
143 errln("case %d: No 'spec' line.", n
);
146 UnicodeString date
= currentCase
->getString("date", status
);
147 if(U_FAILURE(status
)) {
148 errln("case %d: No 'date' line.", n
);
151 UnicodeString expectStr
= currentCase
->getString("str", status
);
152 if(U_FAILURE(status
)) {
153 errln("case %d: No 'str' line.", n
);
157 DateFormat
*format
= NULL
;
160 locale
.extract(0, locale
.length(), calLoc
, (const char*)0); // default codepage. Invariant codepage doesn't have '@'!
162 if(spec
.startsWith(kPATTERN
)) {
163 pattern
= UnicodeString(spec
,kPATTERN
.length());
165 format
= new SimpleDateFormat(pattern
, loc
, status
);
166 if(U_FAILURE(status
)) {
167 errln("case %d: could not create SimpleDateFormat from pattern: %s", n
, u_errorName(status
));
171 if(styleSet
.parseFrom(spec
, status
)<0 || U_FAILURE(status
)) {
172 errln("case %d: could not parse spec as style fields: %s", n
, u_errorName(status
));
175 format
= DateFormat::createDateTimeInstance((DateFormat::EStyle
)styleSet
.getDateStyle(), (DateFormat::EStyle
)styleSet
.getTimeStyle(), loc
);
176 if(format
== NULL
) {
177 errln("case %d: could not create SimpleDateFormat from styles.", n
);
182 Calendar
*cal
= Calendar::createInstance(loc
, status
);
183 if(U_FAILURE(status
)) {
184 errln("case %d: could not create calendar from %s", n
, calLoc
);
187 if (zone
.length() > 0) {
188 TimeZone
* tz
= TimeZone::createTimeZone(zone
);
189 cal
->setTimeZone(*tz
);
190 format
->setTimeZone(*tz
);
195 if(date
.startsWith(kMILLIS
)) {
196 UnicodeString millis
= UnicodeString(date
, kMILLIS
.length());
198 fromDate
= udbg_stod(millis
);
199 } else if(date
.startsWith(kRELATIVE_MILLIS
)) {
200 UnicodeString millis
= UnicodeString(date
, kRELATIVE_MILLIS
.length());
202 fromDate
= udbg_stod(millis
) + now
;
203 } else if(date
.startsWith(kRELATIVE_ADD
)) {
204 UnicodeString add
= UnicodeString(date
, kRELATIVE_ADD
.length()); // "add" is a string indicating which fields to add
205 if(fromSet
.parseFrom(add
, status
)<0 || U_FAILURE(status
)) {
206 errln("case %d: could not parse date as RELATIVE_ADD calendar fields: %s", n
, u_errorName(status
));
211 cal
->setTime(now
, status
);
212 for (int q
=0; q
<UCAL_FIELD_COUNT
; q
++) {
213 if (fromSet
.isSet((UCalendarDateFields
)q
)) {
214 //int32_t oldv = cal->get((UCalendarDateFields)q, status);
215 if (q
== UCAL_DATE
) {
216 cal
->add((UCalendarDateFields
)q
,
217 fromSet
.get((UCalendarDateFields
)q
), status
);
219 cal
->set((UCalendarDateFields
)q
,
220 fromSet
.get((UCalendarDateFields
)q
));
222 //int32_t newv = cal->get((UCalendarDateFields)q, status);
225 fromDate
= cal
->getTime(status
);
226 if(U_FAILURE(status
)) {
227 errln("case %d: could not apply date as RELATIVE_ADD calendar fields: %s", n
, u_errorName(status
));
230 } else if(fromSet
.parseFrom(date
, status
)<0 || U_FAILURE(status
)) {
231 errln("case %d: could not parse date as calendar fields: %s", n
, u_errorName(status
));
238 // logln((UnicodeString)"#"+n+" "+locale+"/"+from+" >>> "+toCalLoc+"/"
241 UnicodeString output
;
245 // cal->setTime(fromDate, status);
246 // if(U_FAILURE(status)) {
247 // errln("case %d: could not set time on calendar: %s", n, u_errorName(status));
250 format
->format(fromDate
, output
, pos
, status
);
252 fromSet
.setOnCalendar(cal
, status
);
253 if(U_FAILURE(status
)) {
254 errln("case %d: could not set fields on calendar: %s", n
, u_errorName(status
));
257 format
->format(*cal
, output
, pos
);
260 // check erro result from 'format'
261 if(U_FAILURE(status
)) {
262 errln("case %d: could not format(): %s", n
, u_errorName(status
)); // TODO: use 'pos'
264 // if(pos.getBeginIndex()==0 && pos.getEndIndex()==0) { // TODO: more precise error?
265 // errln("WARNING: case %d: format's pos returned (0,0) - error ??", n);
268 if(output
== expectStr
) {
269 logln(caseString
+": format: SUCCESS! "+UnicodeString("expect=output=")+output
);
271 UnicodeString result
;
272 UnicodeString result2
;
273 errln(caseString
+": format: output!=expectStr, got " + *udbg_escape(output
, &result
) + " expected " + *udbg_escape(expectStr
, &result2
));
278 format
->parse(expectStr
,*cal
,pos
);
280 UDate gotDate
= cal
->getTime(status
);
281 if(U_FAILURE(status
)) {
282 errln(caseString
+": parse: could not get time on calendar: "+UnicodeString(u_errorName(status
)));
285 if(gotDate
== fromDate
) {
286 logln(caseString
+": parse: SUCCESS! "+UnicodeString("gotDate=parseDate=")+expectStr
);
288 UnicodeString expectDateStr
, gotDateStr
;
289 basicFmt
.format(fromDate
,expectDateStr
);
290 basicFmt
.format(gotDate
,gotDateStr
);
291 errln(caseString
+": parse: FAIL. parsed '"+expectStr
+"' and got "+gotDateStr
+", expected " + expectDateStr
);
294 // Calendar *cal2 = cal->clone();
296 // fromSet.setOnCalendar(cal2, status);
297 if(U_FAILURE(status
)) {
298 errln("case %d: parse: could not set fields on calendar: %s", n
, u_errorName(status
));
302 CalendarFieldsSet diffSet
;
304 if (!fromSet
.matches(cal
, diffSet
, status
)) {
305 UnicodeString diffs
= diffSet
.diffFrom(fromSet
, status
);
306 errln((UnicodeString
)"FAIL: "+caseString
307 +", Differences: '"+ diffs
308 +"', status: "+ u_errorName(status
));
309 } else if (U_FAILURE(status
)) {
310 errln("FAIL: "+caseString
+" parse SET SOURCE calendar Failed to match: "
311 +u_errorName(status
));
313 logln("PASS: "+caseString
+" parse.");
327 void DataDrivenFormatTest::processTest(TestData
*testData
) {
329 //const UChar *arguments= NULL;
330 //int32_t argLen = 0;
332 const DataMap
*settings
= NULL
;
333 //const UChar *type= NULL;
334 UErrorCode status
= U_ZERO_ERROR
;
335 UnicodeString testSetting
;
337 while (testData
->nextSettings(settings
, status
)) {
338 status
= U_ZERO_ERROR
;
339 // try to get a locale
340 testSetting
= settings
->getString("Type", status
);
341 if (U_SUCCESS(status
)) {
345 logln(testSetting
+ "---");
346 testSetting
.extract(0, testSetting
.length(), testType
, "");
348 errln("Unable to extract 'Type'. Skipping..");
352 if (!strcmp(testType
, "date_format")) {
353 testConvertDate(testData
, settings
, true);
354 } else if (!strcmp(testType
, "date_parse")) {
355 testConvertDate(testData
, settings
, false);
357 errln("Unknown type: %s", testType
);