1 /********************************************************************
2 * Copyright (c) 2008-2013, International Business Machines Corporation and
3 * others. All Rights Reserved.
4 ********************************************************************/
5
6 #include "unicode/utypes.h"
7
8 #if !UCONFIG_NO_FORMATTING
9
10 #include "unicode/tmunit.h"
11 #include "unicode/tmutamt.h"
12 #include "unicode/tmutfmt.h"
13 #include "tufmtts.h"
14 #include "unicode/ustring.h"
15
16 //TODO: put as compilation flag
17 //#define TUFMTTS_DEBUG 1
18
19 #ifdef TUFMTTS_DEBUG
20 #include <iostream>
21 #endif
22
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)23 void TimeUnitTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ ) {
24 if (exec) logln("TestSuite TimeUnitTest");
25 switch (index) {
26 TESTCASE(0, testBasic);
27 TESTCASE(1, testAPI);
28 TESTCASE(2, testGreekWithFallback);
29 TESTCASE(3, testGreekWithSanitization);
30 default: name = ""; break;
31 }
32 }
33
34 /**
35 * Test basic
36 */
testBasic()37 void TimeUnitTest::testBasic() {
38 const char* locales[] = {"en", "sl", "fr", "zh", "ar", "ru", "zh_Hant", "pa"};
39 for ( unsigned int locIndex = 0;
40 locIndex < sizeof(locales)/sizeof(locales[0]);
41 ++locIndex ) {
42 UErrorCode status = U_ZERO_ERROR;
43 Locale loc(locales[locIndex]);
44 TimeUnitFormat** formats = new TimeUnitFormat*[2];
45 formats[UTMUTFMT_FULL_STYLE] = new TimeUnitFormat(loc, status);
46 if (!assertSuccess("TimeUnitFormat(full)", status, TRUE)) return;
47 formats[UTMUTFMT_ABBREVIATED_STYLE] = new TimeUnitFormat(loc, UTMUTFMT_ABBREVIATED_STYLE, status);
48 if (!assertSuccess("TimeUnitFormat(short)", status)) return;
49 #ifdef TUFMTTS_DEBUG
50 std::cout << "locale: " << locales[locIndex] << "\n";
51 #endif
52 for (int style = UTMUTFMT_FULL_STYLE;
53 style <= UTMUTFMT_ABBREVIATED_STYLE;
54 ++style) {
55 for (TimeUnit::UTimeUnitFields j = TimeUnit::UTIMEUNIT_YEAR;
56 j < TimeUnit::UTIMEUNIT_FIELD_COUNT;
57 j = (TimeUnit::UTimeUnitFields)(j+1)) {
58 #ifdef TUFMTTS_DEBUG
59 std::cout << "time unit: " << j << "\n";
60 #endif
61 double tests[] = {0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 5, 10, 100, 101.35};
62 for (unsigned int i = 0; i < sizeof(tests)/sizeof(tests[0]); ++i) {
63 #ifdef TUFMTTS_DEBUG
64 std::cout << "number: " << tests[i] << "\n";
65 #endif
66 TimeUnitAmount* source = new TimeUnitAmount(tests[i], j, status);
67 if (!assertSuccess("TimeUnitAmount()", status)) return;
68 UnicodeString formatted;
69 Formattable formattable;
70 formattable.adoptObject(source);
71 formatted = ((Format*)formats[style])->format(formattable, formatted, status);
72 if (!assertSuccess("format()", status)) return;
73 #ifdef TUFMTTS_DEBUG
74 char formatResult[1000];
75 formatted.extract(0, formatted.length(), formatResult, "UTF-8");
76 std::cout << "format result: " << formatResult << "\n";
77 #endif
78 Formattable result;
79 ((Format*)formats[style])->parseObject(formatted, result, status);
80 if (!assertSuccess("parseObject()", status)) return;
81 if (result != formattable) {
82 dataerrln("No round trip: ");
83 }
84 // other style parsing
85 Formattable result_1;
86 ((Format*)formats[1-style])->parseObject(formatted, result_1, status);
87 if (!assertSuccess("parseObject()", status)) return;
88 if (result_1 != formattable) {
89 dataerrln("No round trip: ");
90 }
91 }
92 }
93 }
94 delete formats[UTMUTFMT_FULL_STYLE];
95 delete formats[UTMUTFMT_ABBREVIATED_STYLE];
96 delete[] formats;
97 }
98 }
99
100
testAPI()101 void TimeUnitTest::testAPI() {
102 //================= TimeUnit =================
103 UErrorCode status = U_ZERO_ERROR;
104
105 TimeUnit* tmunit = TimeUnit::createInstance(TimeUnit::UTIMEUNIT_YEAR, status);
106 if (!assertSuccess("TimeUnit::createInstance", status)) return;
107
108 TimeUnit* another = (TimeUnit*)tmunit->clone();
109 TimeUnit third(*tmunit);
110 TimeUnit fourth = third;
111
112 assertTrue("orig and clone are equal", (*tmunit == *another));
113 assertTrue("copied and assigned are equal", (third == fourth));
114
115 TimeUnit* tmunit_m = TimeUnit::createInstance(TimeUnit::UTIMEUNIT_MONTH, status);
116 assertTrue("year != month", (*tmunit != *tmunit_m));
117
118 TimeUnit::UTimeUnitFields field = tmunit_m->getTimeUnitField();
119 assertTrue("field of month time unit is month", (field == TimeUnit::UTIMEUNIT_MONTH));
120
121 delete tmunit;
122 delete another;
123 delete tmunit_m;
124 //
125 //================= TimeUnitAmount =================
126
127 Formattable formattable((int32_t)2);
128 TimeUnitAmount tma_long(formattable, TimeUnit::UTIMEUNIT_DAY, status);
129 if (!assertSuccess("TimeUnitAmount(formattable...)", status)) return;
130
131 formattable.setDouble(2);
132 TimeUnitAmount tma_double(formattable, TimeUnit::UTIMEUNIT_DAY, status);
133 if (!assertSuccess("TimeUnitAmount(formattable...)", status)) return;
134
135 formattable.setDouble(3);
136 TimeUnitAmount tma_double_3(formattable, TimeUnit::UTIMEUNIT_DAY, status);
137 if (!assertSuccess("TimeUnitAmount(formattable...)", status)) return;
138
139 TimeUnitAmount tma(2, TimeUnit::UTIMEUNIT_DAY, status);
140 if (!assertSuccess("TimeUnitAmount(number...)", status)) return;
141
142 TimeUnitAmount tma_h(2, TimeUnit::UTIMEUNIT_HOUR, status);
143 if (!assertSuccess("TimeUnitAmount(number...)", status)) return;
144
145 TimeUnitAmount second(tma);
146 TimeUnitAmount third_tma = tma;
147 TimeUnitAmount* fourth_tma = (TimeUnitAmount*)tma.clone();
148
149 assertTrue("orig and copy are equal", (second == tma));
150 assertTrue("clone and assigned are equal", (third_tma == *fourth_tma));
151 assertTrue("different if number diff", (tma_double != tma_double_3));
152 assertTrue("different if number type diff", (tma_double != tma_long));
153 assertTrue("different if time unit diff", (tma != tma_h));
154 assertTrue("same even different constructor", (tma_double == tma));
155
156 assertTrue("getTimeUnitField", (tma.getTimeUnitField() == TimeUnit::UTIMEUNIT_DAY));
157 delete fourth_tma;
158 //
159 //================= TimeUnitFormat =================
160 //
161 TimeUnitFormat* tmf_en = new TimeUnitFormat(Locale("en"), status);
162 if (!assertSuccess("TimeUnitFormat(en...)", status, TRUE)) return;
163 TimeUnitFormat tmf_fr(Locale("fr"), status);
164 if (!assertSuccess("TimeUnitFormat(fr...)", status)) return;
165
166 assertTrue("TimeUnitFormat: en and fr diff", (*tmf_en != tmf_fr));
167
168 TimeUnitFormat tmf_assign = *tmf_en;
169 assertTrue("TimeUnitFormat: orig and assign are equal", (*tmf_en == tmf_assign));
170
171 TimeUnitFormat tmf_copy(tmf_fr);
172 assertTrue("TimeUnitFormat: orig and copy are equal", (tmf_fr == tmf_copy));
173
174 TimeUnitFormat* tmf_clone = (TimeUnitFormat*)tmf_en->clone();
175 assertTrue("TimeUnitFormat: orig and clone are equal", (*tmf_en == *tmf_clone));
176 delete tmf_clone;
177
178 tmf_en->setLocale(Locale("fr"), status);
179 if (!assertSuccess("setLocale(fr...)", status)) return;
180
181 NumberFormat* numberFmt = NumberFormat::createInstance(
182 Locale("fr"), status);
183 if (!assertSuccess("NumberFormat::createInstance()", status)) return;
184 tmf_en->setNumberFormat(*numberFmt, status);
185 if (!assertSuccess("setNumberFormat(en...)", status)) return;
186 assertTrue("TimeUnitFormat: setLocale", (*tmf_en == tmf_fr));
187
188 delete tmf_en;
189
190 TimeUnitFormat* en_long = new TimeUnitFormat(Locale("en"), UTMUTFMT_FULL_STYLE, status);
191 if (!assertSuccess("TimeUnitFormat(en...)", status)) return;
192 delete en_long;
193
194 TimeUnitFormat* en_short = new TimeUnitFormat(Locale("en"), UTMUTFMT_ABBREVIATED_STYLE, status);
195 if (!assertSuccess("TimeUnitFormat(en...)", status)) return;
196 delete en_short;
197
198 TimeUnitFormat* format = new TimeUnitFormat(status);
199 format->setLocale(Locale("zh"), status);
200 format->setNumberFormat(*numberFmt, status);
201 if (!assertSuccess("TimeUnitFormat(en...)", status)) return;
202 delete numberFmt;
203 delete format;
204 }
205
206 /* @bug 7902
207 * Tests for Greek Language.
208 * This tests that requests for short unit names correctly fall back
209 * to long unit names for a locale where the locale data does not
210 * provide short unit names. As of CLDR 1.9, Greek is one such language.
211 */
testGreekWithFallback()212 void TimeUnitTest::testGreekWithFallback() {
213 UErrorCode status = U_ZERO_ERROR;
214
215 const char* locales[] = {"el-GR", "el"};
216 TimeUnit::UTimeUnitFields tunits[] = {TimeUnit::UTIMEUNIT_SECOND, TimeUnit::UTIMEUNIT_MINUTE, TimeUnit::UTIMEUNIT_HOUR, TimeUnit::UTIMEUNIT_DAY, TimeUnit::UTIMEUNIT_MONTH, TimeUnit::UTIMEUNIT_YEAR};
217 UTimeUnitFormatStyle styles[] = {UTMUTFMT_FULL_STYLE, UTMUTFMT_ABBREVIATED_STYLE};
218 const int numbers[] = {1, 7};
219
220 const UChar oneSecond[] = {0x0031, 0x0020, 0x03b4, 0x03b5, 0x03c5, 0x03c4, 0x03b5, 0x03c1, 0x03cc, 0x03bb, 0x03b5, 0x03c0, 0x03c4, 0x03bf, 0};
221 const UChar oneSecondShort[] = {0x0031, 0x0020, 0x03b4, 0x03b5, 0x03c5, 0x03c4, 0x002e, 0};
222 const UChar oneMinute[] = {0x0031, 0x0020, 0x03bb, 0x03b5, 0x03c0, 0x03c4, 0x03cc, 0};
223 const UChar oneMinuteShort[] = {0x0031, 0x0020, 0x03bb, 0x03b5, 0x03c0, 0x002e, 0};
224 const UChar oneHour[] = {0x0031, 0x0020, 0x03ce, 0x03c1, 0x03b1, 0};
225 const UChar oneDay[] = {0x0031, 0x0020, 0x03b7, 0x03bc, 0x03ad, 0x03c1, 0x03b1, 0};
226 const UChar oneMonth[] = {0x0031, 0x0020, 0x03bc, 0x03ae, 0x03bd, 0x03b1, 0x03c2, 0};
227 const UChar oneMonthShort[] = {0x0031, 0x0020, 0x03bc, 0x03ae, 0x03bd, 0x002e, 0};
228 const UChar oneYear[] = {0x0031, 0x0020, 0x03ad, 0x03c4, 0x03bf, 0x03c2, 0};
229 const UChar sevenSeconds[] = {0x0037, 0x0020, 0x03b4, 0x03b5, 0x03c5, 0x03c4, 0x03b5, 0x03c1, 0x03cc, 0x03bb, 0x03b5, 0x03c0, 0x03c4, 0x03b1, 0};
230 const UChar sevenSecondsShort[] = {0x0037, 0x0020, 0x03b4, 0x03b5, 0x03c5, 0x03c4, 0x002e, 0};
231 const UChar sevenMinutes[] = {0x0037, 0x0020, 0x03bb, 0x03b5, 0x03c0, 0x03c4, 0x03ac, 0};
232 const UChar sevenMinutesShort[] = {0x0037, 0x0020, 0x03bb, 0x03b5, 0x03c0, 0x002e, 0};
233 const UChar sevenHours[] = {0x0037, 0x0020, 0x03ce, 0x03c1, 0x03b5, 0x03c2, 0};
234 const UChar sevenDays[] = {0x0037, 0x0020, 0x03b7, 0x03bc, 0x03ad, 0x03c1, 0x03b5, 0x03c2, 0};
235 const UChar sevenMonths[] = {0x0037, 0x0020, 0x03bc, 0x03ae, 0x03bd, 0x03b5, 0x3c2, 0};
236 const UChar sevenMonthsShort[] = {0x0037, 0x0020, 0x03bc, 0x03ae, 0x03bd, 0x002e, 0};
237 const UChar sevenYears[] = {0x0037, 0x0020, 0x03ad, 0x03c4, 0x03b7, 0};
238
239 const UnicodeString oneSecondStr(oneSecond);
240 const UnicodeString oneSecondShortStr(oneSecondShort);
241 const UnicodeString oneMinuteStr(oneMinute);
242 const UnicodeString oneMinuteShortStr(oneMinuteShort);
243 const UnicodeString oneHourStr(oneHour);
244 const UnicodeString oneDayStr(oneDay);
245 const UnicodeString oneMonthStr(oneMonth);
246 const UnicodeString oneMonthShortStr(oneMonthShort);
247 const UnicodeString oneYearStr(oneYear);
248 const UnicodeString sevenSecondsStr(sevenSeconds);
249 const UnicodeString sevenSecondsShortStr(sevenSecondsShort);
250 const UnicodeString sevenMinutesStr(sevenMinutes);
251 const UnicodeString sevenMinutesShortStr(sevenMinutesShort);
252 const UnicodeString sevenHoursStr(sevenHours);
253 const UnicodeString sevenDaysStr(sevenDays);
254 const UnicodeString sevenMonthsStr(sevenMonths);
255 const UnicodeString sevenMonthsShortStr(sevenMonthsShort);
256 const UnicodeString sevenYearsStr(sevenYears);
257
258 const UnicodeString expected[] = {oneSecondStr, oneMinuteStr, oneHourStr, oneDayStr, oneMonthStr, oneYearStr,
259 oneSecondShortStr, oneMinuteShortStr, oneHourStr, oneDayStr, oneMonthShortStr, oneYearStr,
260 sevenSecondsStr, sevenMinutesStr, sevenHoursStr, sevenDaysStr, sevenMonthsStr, sevenYearsStr,
261 sevenSecondsShortStr, sevenMinutesShortStr, sevenHoursStr, sevenDaysStr, sevenMonthsShortStr, sevenYearsStr,
262 oneSecondStr, oneMinuteStr, oneHourStr, oneDayStr, oneMonthStr, oneYearStr,
263 oneSecondShortStr, oneMinuteShortStr, oneHourStr, oneDayStr, oneMonthShortStr, oneYearStr,
264 sevenSecondsStr, sevenMinutesStr, sevenHoursStr, sevenDaysStr, sevenMonthsStr, sevenYearsStr,
265 sevenSecondsShortStr, sevenMinutesShortStr, sevenHoursStr, sevenDaysStr, sevenMonthsShortStr, sevenYearsStr};
266
267 int counter = 0;
268 for ( unsigned int locIndex = 0;
269 locIndex < sizeof(locales)/sizeof(locales[0]);
270 ++locIndex ) {
271
272 Locale l = Locale::createFromName(locales[locIndex]);
273
274 for ( unsigned int numberIndex = 0;
275 numberIndex < sizeof(numbers)/sizeof(int);
276 ++numberIndex ) {
277
278 for ( unsigned int styleIndex = 0;
279 styleIndex < sizeof(styles)/sizeof(styles[0]);
280 ++styleIndex ) {
281
282 for ( unsigned int unitIndex = 0;
283 unitIndex < sizeof(tunits)/sizeof(tunits[0]);
284 ++unitIndex ) {
285
286 TimeUnitAmount *tamt = new TimeUnitAmount(numbers[numberIndex], tunits[unitIndex], status);
287 if (U_FAILURE(status)) {
288 dataerrln("generating TimeUnitAmount Object failed.");
289 #ifdef TUFMTTS_DEBUG
290 std::cout << "Failed to get TimeUnitAmount for " << tunits[unitIndex] << "\n";
291 #endif
292 return;
293 }
294
295 TimeUnitFormat *tfmt = new TimeUnitFormat(l, styles[styleIndex], status);
296 if (U_FAILURE(status)) {
297 dataerrln("generating TimeUnitAmount Object failed.");
298 #ifdef TUFMTTS_DEBUG
299 std::cout << "Failed to get TimeUnitFormat for " << locales[locIndex] << "\n";
300 #endif
301 return;
302 }
303
304 Formattable fmt;
305 UnicodeString str;
306
307 fmt.adoptObject(tamt);
308 str = ((Format *)tfmt)->format(fmt, str, status);
309 if (!assertSuccess("formatting relative time failed", status)) {
310 delete tfmt;
311 #ifdef TUFMTTS_DEBUG
312 std::cout << "Failed to format" << "\n";
313 #endif
314 return;
315 }
316
317 #ifdef TUFMTTS_DEBUG
318 char tmp[128]; //output
319 char tmp1[128]; //expected
320 int len = 0;
321 u_strToUTF8(tmp, 128, &len, str.getTerminatedBuffer(), str.length(), &status);
322 u_strToUTF8(tmp1, 128, &len, expected[counter].unescape().getTerminatedBuffer(), expected[counter].unescape().length(), &status);
323 std::cout << "Formatted string : " << tmp << " expected : " << tmp1 << "\n";
324 #endif
325 if (!assertEquals("formatted time string is not expected, locale: " + UnicodeString(locales[locIndex]) + " style: " + (int)styles[styleIndex] + " units: " + (int)tunits[unitIndex], expected[counter], str)) {
326 delete tfmt;
327 str.remove();
328 return;
329 }
330 delete tfmt;
331 str.remove();
332 ++counter;
333 }
334 }
335 }
336 }
337 }
338
339 // Test bug9042
testGreekWithSanitization()340 void TimeUnitTest::testGreekWithSanitization() {
341
342 UErrorCode status = U_ZERO_ERROR;
343 Locale elLoc("el");
344 NumberFormat* numberFmt = NumberFormat::createInstance(Locale("el"), status);
345 if (!assertSuccess("NumberFormat::createInstance for el locale", status, TRUE)) return;
346 numberFmt->setMaximumFractionDigits(1);
347
348 TimeUnitFormat* timeUnitFormat = new TimeUnitFormat(elLoc, status);
349 if (!assertSuccess("TimeUnitFormat::TimeUnitFormat for el locale", status)) return;
350
351 timeUnitFormat->setNumberFormat(*numberFmt, status);
352
353 delete numberFmt;
354 delete timeUnitFormat;
355 }
356
357 #endif
358