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
24void 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 */
70void 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 */
92void 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 */
129void 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
147if (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
157if (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()
182if (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
209if (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 */
277void
278IntlTestDateFormatAPI::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