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-2011, International Business Machines Corporation
6 * and others. All Rights Reserved.
7 ***********************************************************************/
8
9 #include "unicode/utypes.h"
10
11 #if !UCONFIG_NO_FORMATTING
12
13 #include "dtfmapts.h"
14
15 #include "unicode/datefmt.h"
16 #include "unicode/smpdtfmt.h"
17 #include "unicode/decimfmt.h"
18 #include "unicode/choicfmt.h"
19 #include "unicode/msgfmt.h"
20
21
22 // This is an API test, not a unit test. It doesn't test very many cases, and doesn't
23 // try to test the full functionality. It just calls each function in the class and
24 // verifies that it works on a basic level.
25
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)26 void IntlTestDateFormatAPI::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
27 {
28 if (exec) logln("TestSuite DateFormatAPI");
29 switch (index) {
30 case 0: name = "DateFormat API test";
31 if (exec) {
32 logln("DateFormat API test---"); logln("");
33 UErrorCode status = U_ZERO_ERROR;
34 Locale saveLocale;
35 Locale::setDefault(Locale::getEnglish(), status);
36 if(U_FAILURE(status)) {
37 errln("ERROR: Could not set default locale, test may not give correct results");
38 }
39 testAPI(/*par*/);
40 Locale::setDefault(saveLocale, status);
41 }
42 break;
43
44 case 1: name = "TestEquals";
45 if (exec) {
46 logln("TestEquals---"); logln("");
47 TestEquals();
48 }
49 break;
50
51 case 2: name = "TestNameHiding";
52 if (exec) {
53 logln("TestNameHiding---"); logln("");
54 TestNameHiding();
55 }
56 break;
57
58 case 3: name = "TestCoverage";
59 if (exec) {
60 logln("TestCoverage---"); logln("");
61 TestCoverage();
62 }
63 break;
64
65 default: name = ""; break;
66 }
67 }
68
69 /**
70 * Add better code coverage.
71 */
TestCoverage(void)72 void IntlTestDateFormatAPI::TestCoverage(void)
73 {
74 const char *LOCALES[] = {
75 "zh_CN@calendar=chinese",
76 "cop_EG@calendar=coptic",
77 "hi_IN@calendar=indian",
78 "am_ET@calendar=ethiopic"
79 };
80 int32_t numOfLocales = 4;
81
82 for (int32_t i = 0; i < numOfLocales; i++) {
83 DateFormat *df = DateFormat::createDateTimeInstance(DateFormat::kMedium, DateFormat::kMedium, Locale(LOCALES[i]));
84 if (df == NULL){
85 dataerrln("Error creating DateFormat instances.");
86 return;
87 }
88 delete df;
89 }
90 }
91 /**
92 * Test that the equals method works correctly.
93 */
TestEquals(void)94 void IntlTestDateFormatAPI::TestEquals(void)
95 {
96 UErrorCode status = U_ZERO_ERROR;
97 // Create two objects at different system times
98 DateFormat *a = DateFormat::createInstance();
99 UDate start = Calendar::getNow();
100 while (Calendar::getNow() == start) ; // Wait for time to change
101 DateFormat *b = DateFormat::createInstance();
102
103 if (a == NULL || b == NULL){
104 dataerrln("Error calling DateFormat::createInstance()");
105 delete a;
106 delete b;
107 return;
108 }
109
110 if (!(*a == *b))
111 errln("FAIL: DateFormat objects created at different times are unequal.");
112
113 SimpleDateFormat *sdtfmt = dynamic_cast<SimpleDateFormat *>(b);
114 if (sdtfmt != NULL)
115 {
116 double ONE_YEAR = 365*24*60*60*1000.0;
117 sdtfmt->set2DigitYearStart(start + 50*ONE_YEAR, status);
118 if (U_FAILURE(status))
119 errln("FAIL: setTwoDigitStartDate failed.");
120 else if (*a == *b)
121 errln("FAIL: DateFormat objects with different two digit start dates are equal.");
122 }
123 delete a;
124 delete b;
125 }
126
127 /**
128 * This test checks various generic API methods in DateFormat to achieve 100%
129 * API coverage.
130 */
testAPI()131 void IntlTestDateFormatAPI::testAPI(/* char* par */)
132 {
133 UErrorCode status = U_ZERO_ERROR;
134
135 // ======= Test constructors
136
137 logln("Testing DateFormat constructors");
138
139 DateFormat *def = DateFormat::createInstance();
140 DateFormat *fr = DateFormat::createTimeInstance(DateFormat::FULL, Locale::getFrench());
141 DateFormat *it = DateFormat::createDateInstance(DateFormat::MEDIUM, Locale::getItalian());
142 DateFormat *de = DateFormat::createDateTimeInstance(DateFormat::LONG, DateFormat::LONG, Locale::getGerman());
143
144 if (def == NULL || fr == NULL || it == NULL || de == NULL){
145 dataerrln("Error creating DateFormat instances.");
146 }
147
148 // ======= Test equality
149 if (fr != NULL && def != NULL)
150 {
151 logln("Testing equality operator");
152
153 if( *fr == *it ) {
154 errln("ERROR: == failed");
155 }
156 }
157
158 // ======= Test various format() methods
159 if (fr != NULL && it != NULL && de != NULL)
160 {
161 logln("Testing various format() methods");
162
163 UDate d = 837039928046.0;
164 Formattable fD(d, Formattable::kIsDate);
165
166 UnicodeString res1, res2, res3;
167 FieldPosition pos1(FieldPosition::DONT_CARE), pos2(FieldPosition::DONT_CARE);
168
169 status = U_ZERO_ERROR;
170 res1 = fr->format(d, res1, pos1, status);
171 if(U_FAILURE(status)) {
172 errln("ERROR: format() failed (French)");
173 }
174 logln( (UnicodeString) "" + d + " formatted to " + res1);
175
176 res2 = it->format(d, res2, pos2);
177 logln( (UnicodeString) "" + d + " formatted to " + res2);
178
179 res3 = de->format(d, res3);
180 logln( (UnicodeString) "" + d + " formatted to " + res3);
181 }
182
183 // ======= Test parse()
184 if (def != NULL)
185 {
186 logln("Testing parse()");
187
188 UnicodeString text("02/03/76 2:50 AM, CST");
189 Formattable result1;
190 UDate result2, result3;
191 ParsePosition pos(0), pos01(0);
192 def->parseObject(text, result1, pos);
193 if(result1.getType() != Formattable::kDate) {
194 errln("ERROR: parseObject() failed for " + text);
195 }
196 logln(text + " parsed into " + result1.getDate());
197
198 status = U_ZERO_ERROR;
199 result2 = def->parse(text, status);
200 if(U_FAILURE(status)) {
201 errln("ERROR: parse() failed, stopping testing");
202 return;
203 }
204 logln(text + " parsed into " + result2);
205
206 result3 = def->parse(text, pos01);
207 logln(text + " parsed into " + result3);
208 }
209
210 // ======= Test getters and setters
211 if (fr != NULL && it != NULL && de != NULL)
212 {
213 logln("Testing getters and setters");
214
215 int32_t count = 0;
216 const Locale *locales = DateFormat::getAvailableLocales(count);
217 logln((UnicodeString) "Got " + count + " locales" );
218 for(int32_t i = 0; i < count; i++) {
219 UnicodeString name;
220 name = locales[i].getName();
221 logln(name);
222 }
223
224 fr->setLenient(it->isLenient());
225 if(fr->isLenient() != it->isLenient()) {
226 errln("ERROR: setLenient() failed");
227 }
228
229 const Calendar *cal = def->getCalendar();
230 Calendar *newCal = cal->clone();
231 de->adoptCalendar(newCal);
232 it->setCalendar(*newCal);
233 if( *(de->getCalendar()) != *(it->getCalendar())) {
234 errln("ERROR: adopt or set Calendar() failed");
235 }
236
237 const NumberFormat *nf = def->getNumberFormat();
238 NumberFormat *newNf = nf->clone();
239 de->adoptNumberFormat(newNf);
240 it->setNumberFormat(*newNf);
241 if( *(de->getNumberFormat()) != *(it->getNumberFormat())) {
242 errln("ERROR: adopt or set NumberFormat() failed");
243 }
244
245 const TimeZone& tz = def->getTimeZone();
246 TimeZone *newTz = tz.clone();
247 de->adoptTimeZone(newTz);
248 it->setTimeZone(*newTz);
249 if( de->getTimeZone() != it->getTimeZone()) {
250 errln("ERROR: adopt or set TimeZone() failed");
251 }
252 }
253 // ======= Test getStaticClassID()
254
255 logln("Testing getStaticClassID()");
256
257 status = U_ZERO_ERROR;
258 DateFormat *test = new SimpleDateFormat(status);
259 if(U_FAILURE(status)) {
260 dataerrln("ERROR: Couldn't create a DateFormat - %s", u_errorName(status));
261 }
262
263 if(test->getDynamicClassID() != SimpleDateFormat::getStaticClassID()) {
264 errln("ERROR: getDynamicClassID() didn't return the expected value");
265 }
266
267 delete test;
268 delete def;
269 delete fr;
270 delete it;
271 delete de;
272 }
273
274 /**
275 * Test hiding of parse() and format() APIs in the Format hierarchy.
276 * We test the entire hierarchy, even though this test is located in
277 * the DateFormat API test.
278 */
279 void
TestNameHiding(void)280 IntlTestDateFormatAPI::TestNameHiding(void) {
281
282 // N.B.: This test passes if it COMPILES, since it's a test of
283 // compile-time name hiding.
284
285 UErrorCode status = U_ZERO_ERROR;
286 Formattable dateObj(0, Formattable::kIsDate);
287 Formattable numObj(3.1415926535897932384626433832795);
288 Formattable obj;
289 UnicodeString str;
290 FieldPosition fpos;
291 ParsePosition ppos;
292
293 // DateFormat calling Format API
294 {
295 logln("DateFormat");
296 DateFormat *dateFmt = DateFormat::createInstance();
297 if (dateFmt) {
298 dateFmt->format(dateObj, str, status);
299 dateFmt->format(dateObj, str, fpos, status);
300 delete dateFmt;
301 } else {
302 dataerrln("FAIL: Can't create DateFormat");
303 }
304 }
305
306 // SimpleDateFormat calling Format & DateFormat API
307 {
308 logln("SimpleDateFormat");
309 status = U_ZERO_ERROR;
310 SimpleDateFormat sdf(status);
311 if (U_SUCCESS(status)) {
312 // Format API
313 sdf.format(dateObj, str, status);
314 sdf.format(dateObj, str, fpos, status);
315 // DateFormat API
316 sdf.format((UDate)0, str, fpos);
317 sdf.format((UDate)0, str);
318 sdf.parse(str, status);
319 sdf.parse(str, ppos);
320 sdf.getNumberFormat();
321 } else {
322 dataerrln("FAIL: Can't create SimpleDateFormat() - %s", u_errorName(status));
323 }
324 }
325
326 // NumberFormat calling Format API
327 {
328 logln("NumberFormat");
329 status = U_ZERO_ERROR;
330 NumberFormat *fmt = NumberFormat::createInstance(status);
331 if (fmt) {
332 fmt->format(numObj, str, status);
333 fmt->format(numObj, str, fpos, status);
334 delete fmt;
335 } else {
336 dataerrln("FAIL: Can't create NumberFormat()");
337 }
338 }
339
340 // DecimalFormat calling Format & NumberFormat API
341 {
342 logln("DecimalFormat");
343 status = U_ZERO_ERROR;
344 DecimalFormat fmt(status);
345 if(U_SUCCESS(status)) {
346 // Format API
347 fmt.format(numObj, str, status);
348 fmt.format(numObj, str, fpos, status);
349 // NumberFormat API
350 fmt.format(2.71828, str);
351 fmt.format((int32_t)1234567, str);
352 fmt.format(1.41421, str, fpos);
353 fmt.format((int32_t)9876543, str, fpos);
354 fmt.parse(str, obj, ppos);
355 fmt.parse(str, obj, status);
356 } else {
357 errcheckln(status, "FAIL: Couldn't instantiate DecimalFormat, error %s. Quitting test", u_errorName(status));
358 }
359 }
360
361 // ChoiceFormat calling Format & NumberFormat API
362 {
363 logln("ChoiceFormat");
364 status = U_ZERO_ERROR;
365 ChoiceFormat fmt("0#foo|1#foos|2#foos", status);
366 // Format API
367 fmt.format(numObj, str, status);
368 fmt.format(numObj, str, fpos, status);
369 // NumberFormat API
370 fmt.format(2.71828, str);
371 fmt.format((int32_t)1234567, str);
372 fmt.format(1.41421, str, fpos);
373 fmt.format((int32_t)9876543, str, fpos);
374 fmt.parse(str, obj, ppos);
375 fmt.parse(str, obj, status);
376 }
377
378 // MessageFormat calling Format API
379 {
380 logln("MessageFormat");
381 status = U_ZERO_ERROR;
382 MessageFormat fmt("", status);
383 // Format API
384 // We use dateObj, which MessageFormat should reject.
385 // We're testing name hiding, not the format method.
386 fmt.format(dateObj, str, status);
387 fmt.format(dateObj, str, fpos, status);
388 }
389 }
390
391 #endif /* #if !UCONFIG_NO_FORMATTING */
392