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