1 /********************************************************************
2 * COPYRIGHT:
3 * Copyright (c) 1997-2007, 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 "dadrfmt.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 "unicode/dbgutil.h"
27 #include "fldset.h"
28
29
30 #include <stdio.h>
31
DataDrivenFormatTest()32 DataDrivenFormatTest::DataDrivenFormatTest() {
33 UErrorCode status = U_ZERO_ERROR;
34 driver = TestDataModule::getTestDataModule("format", *this, status);
35 }
36
~DataDrivenFormatTest()37 DataDrivenFormatTest::~DataDrivenFormatTest() {
38 delete driver;
39 }
40
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)41 void DataDrivenFormatTest::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 errln("format/DataDriven*Test data (format.res) not initialized!");
68 name = "";
69 }
70
71 }
72
73
74
75 /*
76 * Headers { "locale","spec", "date", "str"}
77 // locale: locale including calendar type
78 // spec: either 'PATTERN=y mm h' etc, or 'DATE=SHORT,TIME=LONG'
79 // date: either an unsigned long (millis), or a calendar spec ERA=0,YEAR=1, etc.. applied to the calendar type specified by the locale
80 // str: the expected unicode string
81 Cases {
82 {
83 "en_US@calendar=gregorian",
84 "DATE=SHORT,TIME=SHORT",
85 "ERA=1,YEAR=2007,MONTH=AUGUST,DATE=8,HOUR=18,MINUTE=54,SECOND=12",
86 "8/8/2007 6:54pm"
87 },
88 * */
89
90
testConvertDate(TestData * testData,const DataMap *,UBool fmt)91 void DataDrivenFormatTest::testConvertDate(TestData *testData,
92 const DataMap * /* settings */, UBool fmt) {
93 UnicodeString kPATTERN("PATTERN="); // TODO: static
94 UnicodeString kMILLIS("MILLIS="); // TODO: static
95 UnicodeString kRELATIVE_MILLIS("RELATIVE_MILLIS="); // TODO: static
96
97 UErrorCode status = U_ZERO_ERROR;
98 SimpleDateFormat basicFmt(UnicodeString("EEE MMM dd yyyy / YYYY'-W'ww-ee"),
99 status);
100 if (U_FAILURE(status)) {
101 errln("FAIL: Couldn't create basic SimpleDateFormat: %s\n",
102 u_errorName(status));
103 return;
104 }
105
106 const DataMap *currentCase= NULL;
107 // Start the processing
108 int n = 0;
109 while (testData->nextCase(currentCase, status)) {
110 char calLoc[256] = "";
111 DateTimeStyleSet styleSet;
112 UnicodeString pattern;
113 UBool usePattern = FALSE;
114 CalendarFieldsSet fromSet;
115 UDate fromDate = 0;
116 UBool useDate = FALSE;
117
118 UDate now = Calendar::getNow();
119
120 ++n;
121
122 char theCase[200];
123 sprintf(theCase, "case %d:", n);
124 UnicodeString caseString(theCase, "");
125
126 // load params
127 UnicodeString locale = currentCase->getString("locale", status);
128 if (U_FAILURE(status)) {
129 errln("case %d: No 'locale' line.", n);
130 continue;
131 }
132 UnicodeString spec = currentCase->getString("spec", status);
133 if(U_FAILURE(status)) {
134 errln("case %d: No 'spec' line.", n);
135 continue;
136 }
137 UnicodeString date = currentCase->getString("date", status);
138 if(U_FAILURE(status)) {
139 errln("case %d: No 'date' line.", n);
140 continue;
141 }
142 UnicodeString expectStr= currentCase->getString("str", status);
143 if(U_FAILURE(status)) {
144 errln("case %d: No 'str' line.", n);
145 continue;
146 }
147
148 DateFormat *format = NULL;
149
150 // Process: 'locale'
151 locale.extract(0, locale.length(), calLoc, (const char*)0); // default codepage. Invariant codepage doesn't have '@'!
152 Locale loc(calLoc);
153 if(spec.startsWith(kPATTERN)) {
154 pattern = UnicodeString(spec,kPATTERN.length());
155 usePattern = TRUE;
156 format = new SimpleDateFormat(pattern, loc, status);
157 if(U_FAILURE(status)) {
158 errln("case %d: could not create SimpleDateFormat from pattern: %s", n, u_errorName(status));
159 continue;
160 }
161 } else {
162 if(styleSet.parseFrom(spec, status)<0 || U_FAILURE(status)) {
163 errln("case %d: could not parse spec as style fields: %s", n, u_errorName(status));
164 continue;
165 }
166 format = DateFormat::createDateTimeInstance((DateFormat::EStyle)styleSet.getDateStyle(), (DateFormat::EStyle)styleSet.getTimeStyle(), loc);
167 if(format == NULL ) {
168 errln("case %d: could not create SimpleDateFormat from styles.", n);
169 continue;
170 }
171 }
172
173 // parse 'date'
174 if(date.startsWith(kMILLIS)) {
175 UnicodeString millis = UnicodeString(date, kMILLIS.length());
176 useDate = TRUE;
177 fromDate = udbg_stoi(millis);
178 } else if(date.startsWith(kRELATIVE_MILLIS)) {
179 UnicodeString millis = UnicodeString(date, kRELATIVE_MILLIS.length());
180 useDate = TRUE;
181 fromDate = udbg_stoi(millis) + now;
182 } else if(fromSet.parseFrom(date, status)<0 || U_FAILURE(status)) {
183 errln("case %d: could not parse date as calendar fields: %s", n, u_errorName(status));
184 continue;
185 }
186
187 Calendar *cal = Calendar::createInstance(loc, status);
188 if(U_FAILURE(status)) {
189 errln("case %d: could not create calendar from %s", n, calLoc);
190 }
191 // now, do it.
192 if (fmt) {
193 FieldPosition pos;
194 // logln((UnicodeString)"#"+n+" "+locale+"/"+from+" >>> "+toCalLoc+"/"
195 // +to);
196 cal->clear();
197 UnicodeString output;
198 output.remove();
199
200 if(useDate) {
201 // cal->setTime(fromDate, status);
202 // if(U_FAILURE(status)) {
203 // errln("case %d: could not set time on calendar: %s", n, u_errorName(status));
204 // continue;
205 // }
206 format->format(fromDate, output, pos, status);
207 } else {
208 fromSet.setOnCalendar(cal, status);
209 if(U_FAILURE(status)) {
210 errln("case %d: could not set fields on calendar: %s", n, u_errorName(status));
211 continue;
212 }
213 format->format(*cal, output, pos);
214 }
215
216 // check erro result from 'format'
217 if(U_FAILURE(status)) {
218 errln("case %d: could not format(): %s", n, u_errorName(status)); // TODO: use 'pos'
219 }
220 // if(pos.getBeginIndex()==0 && pos.getEndIndex()==0) { // TODO: more precise error?
221 // errln("WARNING: case %d: format's pos returned (0,0) - error ??", n);
222 // }
223
224 if(output == expectStr) {
225 logln(caseString+": format: SUCCESS! "+UnicodeString("expect=output=")+output);
226 } else {
227 UnicodeString result;
228 UnicodeString result2;
229 errln(caseString+": format: output!=expectStr, got " + *udbg_escape(output, &result) + " expected " + *udbg_escape(expectStr, &result2));
230 }
231 } else {
232 cal->clear();
233 ParsePosition pos;
234 format->parse(expectStr,*cal,pos);
235 if(useDate) {
236 UDate gotDate = cal->getTime(status);
237 if(U_FAILURE(status)) {
238 errln(caseString+": parse: could not get time on calendar: "+UnicodeString(u_errorName(status)));
239 continue;
240 }
241 if(gotDate == fromDate) {
242 logln(caseString+": parse: SUCCESS! "+UnicodeString("gotDate=parseDate=")+expectStr);
243 } else {
244 UnicodeString expectDateStr, gotDateStr;
245 basicFmt.format(fromDate,expectDateStr);
246 basicFmt.format(gotDate,gotDateStr);
247 errln(caseString+": parse: FAIL. parsed '"+expectStr+"' and got "+gotDateStr+", expected " + expectDateStr);
248 }
249 } else {
250 // Calendar *cal2 = cal->clone();
251 // cal2->clear();
252 // fromSet.setOnCalendar(cal2, status);
253 if(U_FAILURE(status)) {
254 errln("case %d: parse: could not set fields on calendar: %s", n, u_errorName(status));
255 continue;
256 }
257
258 CalendarFieldsSet diffSet;
259 // diffSet.clear();
260 if (!fromSet.matches(cal, diffSet, status)) {
261 UnicodeString diffs = diffSet.diffFrom(fromSet, status);
262 errln((UnicodeString)"FAIL: "+caseString
263 +", Differences: '"+ diffs
264 +"', status: "+ u_errorName(status));
265 } else if (U_FAILURE(status)) {
266 errln("FAIL: "+caseString+" parse SET SOURCE calendar Failed to match: "
267 +u_errorName(status));
268 } else {
269 logln("PASS: "+caseString+" parse.");
270 }
271
272
273
274 }
275 }
276 delete cal;
277 delete format;
278
279 }
280 // delete basicFmt;
281 }
282
processTest(TestData * testData)283 void DataDrivenFormatTest::processTest(TestData *testData) {
284 //Format *cal= NULL;
285 //const UChar *arguments= NULL;
286 //int32_t argLen = 0;
287 char testType[256];
288 const DataMap *settings= NULL;
289 //const UChar *type= NULL;
290 UErrorCode status = U_ZERO_ERROR;
291 UnicodeString testSetting;
292 int n = 0;
293 while (testData->nextSettings(settings, status)) {
294 status = U_ZERO_ERROR;
295 // try to get a locale
296 testSetting = settings->getString("Type", status);
297 if (U_SUCCESS(status)) {
298 if ((++n)>0) {
299 logln("---");
300 }
301 logln(testSetting + "---");
302 testSetting.extract(0, testSetting.length(), testType, "");
303 } else {
304 errln("Unable to extract 'Type'. Skipping..");
305 continue;
306 }
307
308 if (!strcmp(testType, "date_format")) {
309 testConvertDate(testData, settings, true);
310 } else if (!strcmp(testType, "date_parse")) {
311 testConvertDate(testData, settings, false);
312 } else {
313 errln("Unknown type: %s", testType);
314 }
315 }
316 }
317
318 #endif
319