]> git.saurik.com Git - apple/icu.git/blob - icuSources/test/intltest/tsdate.cpp
ICU-3.13.tar.gz
[apple/icu.git] / icuSources / test / intltest / tsdate.cpp
1 /********************************************************************
2 * COPYRIGHT:
3 * Copyright (c) 1997-2001, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************/
6
7 #include "unicode/utypes.h"
8
9 #if !UCONFIG_NO_FORMATTING
10
11 #include "unicode/datefmt.h"
12 #include "unicode/smpdtfmt.h"
13 #include "tsdate.h"
14
15 #include <float.h>
16 #include <stdlib.h>
17
18 const double IntlTestDateFormat::ONEYEAR = 365.25 * ONEDAY; // Approximate
19
20 /**
21 * This test does round-trip testing (format -> parse -> format -> parse -> etc.) of
22 * DateFormat.
23 */
24 // par is ignored throughout this file
25 void IntlTestDateFormat::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
26 {
27 if (exec) logln("TestSuite DateFormat");
28 switch (index) {
29 case 0: name = "GenericTest";
30 if (exec) {
31 logln(name);
32 fFormat = DateFormat::createInstance();
33 fTestName = "createInstance";
34 fLimit = 3;
35 testFormat(/* par */);
36 }
37 break;
38 case 1: name = "DefaultLocale";
39 if (exec) {
40 logln(name);
41 testLocale(/*par, */Locale::getDefault(), "Default Locale");
42 }
43 break;
44
45 case 2: name = "TestAvailableLocales";
46 if (exec) {
47 logln(name);
48 testAvailableLocales(/* par */);
49 }
50 break;
51
52 case 3: name = "MonsterTest";
53 if (exec) {
54 logln(name);
55 monsterTest(/*par*/);
56 }
57 break;
58
59 default: name = ""; break;
60 }
61 }
62
63 void
64 IntlTestDateFormat::testLocale(/*char* par, */const Locale& locale, const UnicodeString& localeName)
65 {
66 DateFormat::EStyle timeStyle, dateStyle;
67
68 // For patterns including only time information and a timezone, it may take
69 // up to three iterations, since the timezone may shift as the year number
70 // is determined. For other patterns, 2 iterations should suffice.
71 fLimit = 3;
72
73 for(timeStyle = (DateFormat::EStyle)0;
74 timeStyle < (DateFormat::EStyle)4;
75 timeStyle = (DateFormat::EStyle) (timeStyle+1))
76 {
77 fTestName = (UnicodeString) "Time test " + (int32_t) timeStyle + " (" + localeName + ")";
78 fFormat = DateFormat::createTimeInstance(timeStyle, locale);
79 testFormat(/* par */);
80 }
81
82 fLimit = 2;
83
84 for(dateStyle = (DateFormat::EStyle)0;
85 dateStyle < (DateFormat::EStyle)4;
86 dateStyle = (DateFormat::EStyle) (dateStyle+1))
87 {
88 fTestName = (UnicodeString) "Date test " + (int32_t) dateStyle + " (" + localeName + ")";
89 fFormat = DateFormat::createDateInstance(dateStyle, locale);
90 testFormat(/* par */);
91 }
92
93 for(dateStyle = (DateFormat::EStyle)0;
94 dateStyle < (DateFormat::EStyle)4;
95 dateStyle = (DateFormat::EStyle) (dateStyle+1))
96 {
97 for(timeStyle = (DateFormat::EStyle)0;
98 timeStyle < (DateFormat::EStyle)4;
99 timeStyle = (DateFormat::EStyle) (timeStyle+1))
100 {
101 fTestName = (UnicodeString) "DateTime test " + (int32_t) dateStyle + "/" + (int32_t) timeStyle + " (" + localeName + ")";
102 fFormat = DateFormat::createDateTimeInstance(dateStyle, timeStyle, locale);
103 testFormat(/* par */);
104 }
105 }
106 }
107
108 void IntlTestDateFormat::testFormat(/* char* par */)
109 {
110 if (fFormat == 0)
111 {
112 errln("FAIL: DateFormat creation failed");
113 return;
114 }
115
116 describeTest();
117
118 UDate now = Calendar::getNow();
119 tryDate(0);
120 tryDate(1278161801778.0);
121 tryDate(5264498352317.0); // Sunday, October 28, 2136 8:39:12 AM PST
122 tryDate(9516987689250.0); // In the year 2271
123 tryDate(now);
124 // Shift 6 months into the future, AT THE SAME TIME OF DAY.
125 // This will test the DST handling.
126 tryDate(now + 6.0*30*ONEDAY);
127
128 UDate limit = now * 10; // Arbitrary limit
129 for (int32_t i=0; i<3; ++i)
130 tryDate(uprv_floor(randDouble() * limit));
131
132 delete fFormat;
133 }
134
135 void
136 IntlTestDateFormat::describeTest()
137 {
138 // Assume it's a SimpleDateFormat and get some info
139 SimpleDateFormat *s = (SimpleDateFormat*)fFormat;
140 UnicodeString str;
141 logln(fTestName + " Pattern " + s->toPattern(str));
142 }
143
144 void IntlTestDateFormat::tryDate(UDate theDate)
145 {
146 const int32_t DEPTH = 10;
147 UDate date[DEPTH];
148 UnicodeString string[DEPTH];
149
150 int32_t dateMatch = 0;
151 int32_t stringMatch = 0;
152 UBool dump = FALSE;
153 int32_t i;
154
155 date[0] = theDate;
156 fFormat->format(theDate, string[0]);
157
158 for (i=1; i<DEPTH; ++i)
159 {
160 UErrorCode status = U_ZERO_ERROR;
161 date[i] = fFormat->parse(string[i-1], status);
162 if (U_FAILURE(status))
163 {
164 describeTest();
165 errln("**** FAIL: Parse of " + prettify(string[i-1], FALSE) + " failed.");
166 dump = TRUE;
167 break;
168 }
169 fFormat->format(date[i], string[i]);
170 if (dateMatch == 0 && date[i] == date[i-1])
171 dateMatch = i;
172 else if (dateMatch > 0 && date[i] != date[i-1])
173 {
174 describeTest();
175 errln("**** FAIL: Date mismatch after match for " + string[i]);
176 dump = TRUE;
177 break;
178 }
179 if (stringMatch == 0 && string[i] == string[i-1])
180 stringMatch = i;
181 else if (stringMatch > 0 && string[i] != string[i-1])
182 {
183 describeTest();
184 errln("**** FAIL: String mismatch after match for " + string[i]);
185 dump = TRUE;
186 break;
187 }
188 if (dateMatch > 0 && stringMatch > 0)
189 break;
190 }
191 if (i == DEPTH)
192 --i;
193
194 if (stringMatch > fLimit || dateMatch > fLimit)
195 {
196 describeTest();
197 errln((UnicodeString)"**** FAIL: No string and/or date match within " + fLimit
198 + " iterations for the Date " + string[0] + "\t(" + theDate + ").");
199 dump = TRUE;
200 }
201
202 if (dump)
203 {
204 for (int32_t k=0; k<=i; ++k)
205 {
206 logln((UnicodeString)"" + k + ": " + date[k] + " F> " +
207 string[k] + " P> ");
208 }
209 }
210 }
211
212 // Return a random double from 0.01 to 1, inclusive
213 double IntlTestDateFormat::randDouble()
214 {
215 // Assume 8-bit (or larger) rand values. Also assume
216 // that the system rand() function is very poor, which it always is.
217 double d=0.0;
218 uint32_t i;
219 char* poke = (char*)&d;
220 do {
221 do {
222 for (i=0; i < sizeof(double); ++i)
223 {
224 poke[i] = (char)(rand() & 0xFF);
225 }
226 } while (uprv_isNaN(d) || uprv_isInfinite(d));
227
228 if (d < 0.0)
229 d = -d;
230 if (d > 0.0)
231 {
232 double e = uprv_floor(uprv_log10(d));
233 if (e < -2.0)
234 d *= uprv_pow10((int32_t)(-e-2));
235 else if (e > -1.0)
236 d /= uprv_pow10((int32_t)(e+1));
237 }
238 // While this is not a real normalized number make another one.
239 } while (uprv_isNaN(d) || uprv_isInfinite(d)
240 || !((-DBL_MAX < d && d < DBL_MAX) || (d < -DBL_MIN && DBL_MIN < d)));
241 return d;
242 }
243
244 void IntlTestDateFormat::testAvailableLocales(/* char* par */)
245 {
246 int32_t count = 0;
247 const Locale* locales = DateFormat::getAvailableLocales(count);
248 logln((UnicodeString)"" + count + " available locales");
249 if (locales && count)
250 {
251 UnicodeString name;
252 UnicodeString all;
253 for (int32_t i=0; i<count; ++i)
254 {
255 if (i!=0) all += ", ";
256 all += locales[i].getName();
257 }
258 logln(all);
259 }
260 else errln((UnicodeString)"**** FAIL: Zero available locales or null array pointer");
261 }
262
263 void IntlTestDateFormat::monsterTest(/*char *par*/)
264 {
265 int32_t count;
266 const Locale* locales = DateFormat::getAvailableLocales(count);
267 if (locales && count)
268 {
269 if (quick && count > 3) {
270 logln("quick test: testing just 3 locales!");
271 count = 3;
272 }
273 for (int32_t i=0; i<count; ++i)
274 {
275 UnicodeString name = UnicodeString(locales[i].getName(), "");
276 logln((UnicodeString)"Testing " + name + "...");
277 testLocale(/*par, */locales[i], name);
278 }
279 }
280 }
281
282 #endif /* #if !UCONFIG_NO_FORMATTING */