• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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