• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
4  * Copyright (c) 2008-2016, International Business Machines Corporation and
5  * others. All Rights Reserved.
6  ********************************************************************/
7 
8 #include "unicode/utypes.h"
9 
10 #if !UCONFIG_NO_FORMATTING
11 
12 #include "unicode/decimfmt.h"
13 #include "unicode/tmunit.h"
14 #include "unicode/tmutamt.h"
15 #include "unicode/tmutfmt.h"
16 #include "unicode/ustring.h"
17 #include "cmemory.h"
18 #include "intltest.h"
19 
20 //TODO: put as compilation flag
21 //#define TUFMTTS_DEBUG 1
22 
23 #ifdef TUFMTTS_DEBUG
24 #include <iostream>
25 #endif
26 
27 class TimeUnitTest : public IntlTest {
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)28     void runIndexedTest(int32_t index, UBool exec, const char* &name, char* /*par*/ ) {
29         if (exec) logln("TestSuite TimeUnitTest");
30         TESTCASE_AUTO_BEGIN;
31         TESTCASE_AUTO(testBasic);
32         TESTCASE_AUTO(testAPI);
33         TESTCASE_AUTO(testGreekWithFallback);
34         TESTCASE_AUTO(testGreekWithSanitization);
35         TESTCASE_AUTO(test10219Plurals);
36         TESTCASE_AUTO(TestBritishShortHourFallback);
37         TESTCASE_AUTO_END;
38     }
39 
40 public:
41     /**
42      * Performs basic tests
43      **/
44     void testBasic();
45 
46     /**
47      * Performs API tests
48      **/
49     void testAPI();
50 
51     /**
52      * Performs tests for Greek
53      * This tests that requests for short unit names correctly fall back
54      * to long unit names for a locale where the locale data does not
55      * provide short unit names. As of CLDR 1.9, Greek is one such language.
56      **/
57     void testGreekWithFallback();
58 
59     /**
60      * Performs tests for Greek
61      * This tests that if the plural count listed in time unit format does not
62      * match those in the plural rules for the locale, those plural count in
63      * time unit format will be ingored and subsequently, fall back will kick in
64      * which is tested above.
65      * Without data sanitization, setNumberFormat() would crash.
66      * As of CLDR shiped in ICU4.8, Greek is one such language.
67      */
68     void testGreekWithSanitization();
69 
70     /**
71      * Performs unit test for ticket 10219 making sure that plurals work
72      * correctly with rounding.
73      */
74     void test10219Plurals();
75 
76     void TestBritishShortHourFallback();
77 };
78 
createTimeUnitTest()79 extern IntlTest *createTimeUnitTest() {
80     return new TimeUnitTest();
81 }
82 
83 // This function is more lenient than equals operator as it considers integer 3 hours and
84 // double 3.0 hours to be equal
tmaEqual(const TimeUnitAmount & left,const TimeUnitAmount & right)85 static UBool tmaEqual(const TimeUnitAmount& left, const TimeUnitAmount& right) {
86     if (left.getTimeUnitField() != right.getTimeUnitField()) {
87         return FALSE;
88     }
89     UErrorCode status = U_ZERO_ERROR;
90     if (!left.getNumber().isNumeric() || !right.getNumber().isNumeric()) {
91         return FALSE;
92     }
93     UBool result = left.getNumber().getDouble(status) == right.getNumber().getDouble(status);
94     if (U_FAILURE(status)) {
95         return FALSE;
96     }
97     return result;
98 }
99 
100 /**
101  * Test basic
102  */
testBasic()103 void TimeUnitTest::testBasic() {
104     const char* locales[] = {"en", "sl", "fr", "zh", "ar", "ru", "zh_Hant", "pa"};
105     for ( unsigned int locIndex = 0;
106           locIndex < UPRV_LENGTHOF(locales);
107           ++locIndex ) {
108         UErrorCode status = U_ZERO_ERROR;
109         Locale loc(locales[locIndex]);
110         TimeUnitFormat** formats = new TimeUnitFormat*[2];
111         formats[UTMUTFMT_FULL_STYLE] = new TimeUnitFormat(loc, status);
112         if (!assertSuccess("TimeUnitFormat(full)", status, TRUE)) return;
113         formats[UTMUTFMT_ABBREVIATED_STYLE] = new TimeUnitFormat(loc, UTMUTFMT_ABBREVIATED_STYLE, status);
114         if (!assertSuccess("TimeUnitFormat(short)", status)) return;
115 #ifdef TUFMTTS_DEBUG
116         std::cout << "locale: " << locales[locIndex] << "\n";
117 #endif
118         for (int style = UTMUTFMT_FULL_STYLE;
119              style <= UTMUTFMT_ABBREVIATED_STYLE;
120              ++style) {
121           for (TimeUnit::UTimeUnitFields j = TimeUnit::UTIMEUNIT_YEAR;
122              j < TimeUnit::UTIMEUNIT_FIELD_COUNT;
123              j = (TimeUnit::UTimeUnitFields)(j+1)) {
124 #ifdef TUFMTTS_DEBUG
125             std::cout << "time unit: " << j << "\n";
126 #endif
127             double tests[] = {0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 5, 10, 100, 101.35};
128             for (unsigned int i = 0; i < UPRV_LENGTHOF(tests); ++i) {
129 #ifdef TUFMTTS_DEBUG
130                 std::cout << "number: " << tests[i] << "\n";
131 #endif
132                 TimeUnitAmount* source = new TimeUnitAmount(tests[i], j, status);
133                 if (!assertSuccess("TimeUnitAmount()", status)) return;
134                 UnicodeString formatted;
135                 Formattable formattable;
136                 formattable.adoptObject(source);
137                 formatted = ((Format*)formats[style])->format(formattable, formatted, status);
138                 if (!assertSuccess("format()", status)) return;
139 #ifdef TUFMTTS_DEBUG
140                 char formatResult[1000];
141                 formatted.extract(0, formatted.length(), formatResult, "UTF-8");
142                 std::cout << "format result: " << formatResult << "\n";
143 #endif
144                 Formattable result;
145                 ((Format*)formats[style])->parseObject(formatted, result, status);
146                 if (!assertSuccess("parseObject()", status)) return;
147                 if (!tmaEqual(*((TimeUnitAmount *)result.getObject()), *((TimeUnitAmount *) formattable.getObject()))) {
148                     dataerrln("No round trip: ");
149                 }
150                 // other style parsing
151                 Formattable result_1;
152                 ((Format*)formats[1-style])->parseObject(formatted, result_1, status);
153                 if (!assertSuccess("parseObject()", status)) return;
154                 if (!tmaEqual(*((TimeUnitAmount *)result_1.getObject()), *((TimeUnitAmount *) formattable.getObject()))) {
155                     dataerrln("No round trip: ");
156                 }
157             }
158           }
159         }
160         delete formats[UTMUTFMT_FULL_STYLE];
161         delete formats[UTMUTFMT_ABBREVIATED_STYLE];
162         delete[] formats;
163     }
164 }
165 
166 
testAPI()167 void TimeUnitTest::testAPI() {
168     //================= TimeUnit =================
169     UErrorCode status = U_ZERO_ERROR;
170 
171     TimeUnit* tmunit = TimeUnit::createInstance(TimeUnit::UTIMEUNIT_YEAR, status);
172     if (!assertSuccess("TimeUnit::createInstance", status)) return;
173 
174     TimeUnit* another = (TimeUnit*)tmunit->clone();
175     TimeUnit third(*tmunit);
176     TimeUnit fourth = third;
177 
178     assertTrue("orig and clone are equal", (*tmunit == *another));
179     assertTrue("copied and assigned are equal", (third == fourth));
180 
181     TimeUnit* tmunit_m = TimeUnit::createInstance(TimeUnit::UTIMEUNIT_MONTH, status);
182     assertTrue("year != month", (*tmunit != *tmunit_m));
183 
184     TimeUnit::UTimeUnitFields field = tmunit_m->getTimeUnitField();
185     assertTrue("field of month time unit is month", (field == TimeUnit::UTIMEUNIT_MONTH));
186 
187     //===== Interoperability with MeasureUnit ======
188     MeasureUnit **ptrs = new MeasureUnit *[TimeUnit::UTIMEUNIT_FIELD_COUNT];
189 
190     ptrs[TimeUnit::UTIMEUNIT_YEAR] = MeasureUnit::createYear(status);
191     ptrs[TimeUnit::UTIMEUNIT_MONTH] = MeasureUnit::createMonth(status);
192     ptrs[TimeUnit::UTIMEUNIT_DAY] = MeasureUnit::createDay(status);
193     ptrs[TimeUnit::UTIMEUNIT_WEEK] = MeasureUnit::createWeek(status);
194     ptrs[TimeUnit::UTIMEUNIT_HOUR] = MeasureUnit::createHour(status);
195     ptrs[TimeUnit::UTIMEUNIT_MINUTE] = MeasureUnit::createMinute(status);
196     ptrs[TimeUnit::UTIMEUNIT_SECOND] = MeasureUnit::createSecond(status);
197     if (!assertSuccess("TimeUnit::createInstance", status)) return;
198 
199     for (TimeUnit::UTimeUnitFields j = TimeUnit::UTIMEUNIT_YEAR;
200             j < TimeUnit::UTIMEUNIT_FIELD_COUNT;
201             j = (TimeUnit::UTimeUnitFields)(j+1)) {
202         MeasureUnit *ptr = TimeUnit::createInstance(j, status);
203         if (!assertSuccess("TimeUnit::createInstance", status)) return;
204         // We have to convert *ptr to a MeasureUnit or else == will fail over
205         // differing types (TimeUnit vs. MeasureUnit).
206         assertTrue(
207                 "Time unit should be equal to corresponding MeasureUnit",
208                 MeasureUnit(*ptr) == *ptrs[j]);
209         delete ptr;
210     }
211     delete tmunit;
212     delete another;
213     delete tmunit_m;
214     for (int i = 0; i < TimeUnit::UTIMEUNIT_FIELD_COUNT; ++i) {
215         delete ptrs[i];
216     }
217     delete [] ptrs;
218 
219     //
220     //================= TimeUnitAmount =================
221 
222     Formattable formattable((int32_t)2);
223     TimeUnitAmount tma_long(formattable, TimeUnit::UTIMEUNIT_DAY, status);
224     if (!assertSuccess("TimeUnitAmount(formattable...)", status)) return;
225 
226     formattable.setDouble(2);
227     TimeUnitAmount tma_double(formattable, TimeUnit::UTIMEUNIT_DAY, status);
228     if (!assertSuccess("TimeUnitAmount(formattable...)", status)) return;
229 
230     formattable.setDouble(3);
231     TimeUnitAmount tma_double_3(formattable, TimeUnit::UTIMEUNIT_DAY, status);
232     if (!assertSuccess("TimeUnitAmount(formattable...)", status)) return;
233 
234     TimeUnitAmount tma(2, TimeUnit::UTIMEUNIT_DAY, status);
235     if (!assertSuccess("TimeUnitAmount(number...)", status)) return;
236 
237     TimeUnitAmount tma_h(2, TimeUnit::UTIMEUNIT_HOUR, status);
238     if (!assertSuccess("TimeUnitAmount(number...)", status)) return;
239 
240     TimeUnitAmount second(tma);
241     TimeUnitAmount third_tma = tma;
242     TimeUnitAmount* fourth_tma = (TimeUnitAmount*)tma.clone();
243 
244     assertTrue("orig and copy are equal", (second == tma));
245     assertTrue("clone and assigned are equal", (third_tma == *fourth_tma));
246     assertTrue("different if number diff", (tma_double != tma_double_3));
247     assertTrue("different if number type diff", (tma_double != tma_long));
248     assertTrue("different if time unit diff", (tma != tma_h));
249     assertTrue("same even different constructor", (tma_double == tma));
250 
251     assertTrue("getTimeUnitField", (tma.getTimeUnitField() == TimeUnit::UTIMEUNIT_DAY));
252     delete fourth_tma;
253     //
254     //================= TimeUnitFormat =================
255     //
256     TimeUnitFormat* tmf_en = new TimeUnitFormat(Locale("en"), status);
257     if (!assertSuccess("TimeUnitFormat(en...)", status, TRUE)) return;
258     TimeUnitFormat tmf_fr(Locale("fr"), status);
259     if (!assertSuccess("TimeUnitFormat(fr...)", status)) return;
260 
261     assertTrue("TimeUnitFormat: en and fr diff", (*tmf_en != tmf_fr));
262 
263     TimeUnitFormat tmf_assign = *tmf_en;
264     assertTrue("TimeUnitFormat: orig and assign are equal", (*tmf_en == tmf_assign));
265 
266     TimeUnitFormat tmf_copy(tmf_fr);
267     assertTrue("TimeUnitFormat: orig and copy are equal", (tmf_fr == tmf_copy));
268 
269     TimeUnitFormat* tmf_clone = (TimeUnitFormat*)tmf_en->clone();
270     assertTrue("TimeUnitFormat: orig and clone are equal", (*tmf_en == *tmf_clone));
271     delete tmf_clone;
272 
273     tmf_en->setLocale(Locale("fr"), status);
274     if (!assertSuccess("setLocale(fr...)", status)) return;
275 
276     NumberFormat* numberFmt = NumberFormat::createInstance(
277                                  Locale("fr"), status);
278     if (!assertSuccess("NumberFormat::createInstance()", status)) return;
279     tmf_en->setNumberFormat(*numberFmt, status);
280     if (!assertSuccess("setNumberFormat(en...)", status)) return;
281     assertTrue("TimeUnitFormat: setLocale", (*tmf_en == tmf_fr));
282 
283     delete tmf_en;
284 
285     TimeUnitFormat* en_long = new TimeUnitFormat(Locale("en"), UTMUTFMT_FULL_STYLE, status);
286     if (!assertSuccess("TimeUnitFormat(en...)", status)) return;
287     delete en_long;
288 
289     TimeUnitFormat* en_short = new TimeUnitFormat(Locale("en"), UTMUTFMT_ABBREVIATED_STYLE, status);
290     if (!assertSuccess("TimeUnitFormat(en...)", status)) return;
291     delete en_short;
292 
293     TimeUnitFormat* format = new TimeUnitFormat(status);
294     format->setLocale(Locale("zh"), status);
295     format->setNumberFormat(*numberFmt, status);
296     if (!assertSuccess("TimeUnitFormat(en...)", status)) return;
297     delete numberFmt;
298     delete format;
299 }
300 
301 /* @bug 7902
302  * Tests for Greek Language.
303  * This tests that requests for short unit names correctly fall back
304  * to long unit names for a locale where the locale data does not
305  * provide short unit names. As of CLDR 1.9, Greek is one such language.
306  */
testGreekWithFallback()307 void TimeUnitTest::testGreekWithFallback() {
308     UErrorCode status = U_ZERO_ERROR;
309 
310     const char* locales[] = {"el-GR", "el"};
311     TimeUnit::UTimeUnitFields tunits[] = {TimeUnit::UTIMEUNIT_SECOND, TimeUnit::UTIMEUNIT_MINUTE, TimeUnit::UTIMEUNIT_HOUR, TimeUnit::UTIMEUNIT_DAY, TimeUnit::UTIMEUNIT_MONTH, TimeUnit::UTIMEUNIT_YEAR};
312     UTimeUnitFormatStyle styles[] = {UTMUTFMT_FULL_STYLE, UTMUTFMT_ABBREVIATED_STYLE};
313     const int numbers[] = {1, 7};
314 
315     const UChar oneSecond[] = {0x0031, 0x0020, 0x03b4, 0x03b5, 0x03c5, 0x03c4, 0x03b5, 0x03c1, 0x03cc, 0x03bb, 0x03b5, 0x03c0, 0x03c4, 0x03bf, 0};
316     const UChar oneSecondShort[] = {0x0031, 0x0020, 0x03b4, 0x03b5, 0x03c5, 0x03c4, 0x002e, 0};
317     const UChar oneMinute[] = {0x0031, 0x0020, 0x03bb, 0x03b5, 0x03c0, 0x03c4, 0x03cc, 0};
318     const UChar oneMinuteShort[] = {0x0031, 0x0020, 0x03bb, 0x03b5, 0x03c0, 0x002e, 0};
319     const UChar oneHour[] = {0x0031, 0x0020, 0x03ce, 0x03c1, 0x03b1, 0};
320     const UChar oneDay[] = {0x0031, 0x0020, 0x03b7, 0x03bc, 0x03ad, 0x03c1, 0x03b1, 0};
321     const UChar oneMonth[] = {0x0031, 0x0020, 0x03bc, 0x03ae, 0x03bd, 0x03b1, 0x03c2, 0};
322     const UChar oneMonthShort[] = {0x0031, 0x0020, 0x03bc, 0x03ae, 0x03bd, 0x002e, 0};
323     const UChar oneYear[] = {0x0031, 0x0020, 0x03ad, 0x03c4, 0x03bf, 0x03c2, 0};
324     const UChar oneYearShort[] = {0x0031, 0x0020, 0x03ad, 0x03c4, 0x002e, 0};
325     const UChar sevenSeconds[] = {0x0037, 0x0020, 0x03b4, 0x03b5, 0x03c5, 0x03c4, 0x03b5, 0x03c1, 0x03cc, 0x03bb, 0x03b5, 0x03c0, 0x03c4, 0x03b1, 0};
326     const UChar sevenSecondsShort[] = {0x0037, 0x0020, 0x03b4, 0x03b5, 0x03c5, 0x03c4, 0x002e, 0};
327     const UChar sevenMinutes[] = {0x0037, 0x0020, 0x03bb, 0x03b5, 0x03c0, 0x03c4, 0x03ac, 0};
328     const UChar sevenMinutesShort[] = {0x0037, 0x0020, 0x03bb, 0x03b5, 0x03c0, 0x002e, 0};
329     const UChar sevenHours[] = {0x0037, 0x0020, 0x03ce, 0x03c1, 0x03b5, 0x03c2, 0};
330     const UChar sevenHoursShort[] = {0x0037, 0x0020, 0x03ce, 0x03c1, 0x002e, 0};
331     const UChar sevenDays[] = {0x0037, 0x0020, 0x03b7, 0x03bc, 0x03ad, 0x03c1, 0x03b5, 0x03c2, 0};
332     const UChar sevenMonths[] = {0x0037, 0x0020, 0x03bc, 0x03ae, 0x03bd, 0x03b5, 0x3c2, 0};
333     const UChar sevenMonthsShort[] = {0x0037, 0x0020, 0x03bc, 0x03ae, 0x03bd, 0x002e, 0};
334     const UChar sevenYears[] = {0x0037, 0x0020, 0x03ad, 0x03c4, 0x03b7, 0};
335     const UChar sevenYearsShort[] = {0x0037, 0x0020, 0x03ad, 0x03c4, 0x002e, 0};
336 
337     const UnicodeString oneSecondStr(oneSecond);
338     const UnicodeString oneSecondShortStr(oneSecondShort);
339     const UnicodeString oneMinuteStr(oneMinute);
340     const UnicodeString oneMinuteShortStr(oneMinuteShort);
341     const UnicodeString oneHourStr(oneHour);
342     const UnicodeString oneDayStr(oneDay);
343     const UnicodeString oneMonthStr(oneMonth);
344     const UnicodeString oneMonthShortStr(oneMonthShort);
345     const UnicodeString oneYearStr(oneYear);
346     const UnicodeString oneYearShortStr(oneYearShort);
347     const UnicodeString sevenSecondsStr(sevenSeconds);
348     const UnicodeString sevenSecondsShortStr(sevenSecondsShort);
349     const UnicodeString sevenMinutesStr(sevenMinutes);
350     const UnicodeString sevenMinutesShortStr(sevenMinutesShort);
351     const UnicodeString sevenHoursStr(sevenHours);
352     const UnicodeString sevenHoursShortStr(sevenHoursShort);
353     const UnicodeString sevenDaysStr(sevenDays);
354     const UnicodeString sevenMonthsStr(sevenMonths);
355     const UnicodeString sevenMonthsShortStr(sevenMonthsShort);
356     const UnicodeString sevenYearsStr(sevenYears);
357     const UnicodeString sevenYearsShortStr(sevenYearsShort);
358 
359     const UnicodeString expected[] = {
360             oneSecondStr, oneMinuteStr, oneHourStr, oneDayStr, oneMonthStr, oneYearStr,
361             oneSecondShortStr, oneMinuteShortStr, oneHourStr, oneDayStr, oneMonthShortStr, oneYearShortStr,
362             sevenSecondsStr, sevenMinutesStr, sevenHoursStr, sevenDaysStr, sevenMonthsStr, sevenYearsStr,
363             sevenSecondsShortStr, sevenMinutesShortStr, sevenHoursShortStr, sevenDaysStr, sevenMonthsShortStr, sevenYearsShortStr,
364 
365             oneSecondStr, oneMinuteStr, oneHourStr, oneDayStr, oneMonthStr, oneYearStr,
366             oneSecondShortStr, oneMinuteShortStr, oneHourStr, oneDayStr, oneMonthShortStr, oneYearShortStr,
367             sevenSecondsStr, sevenMinutesStr, sevenHoursStr, sevenDaysStr, sevenMonthsStr, sevenYearsStr,
368             sevenSecondsShortStr, sevenMinutesShortStr, sevenHoursShortStr, sevenDaysStr, sevenMonthsShortStr, sevenYearsShortStr};
369 
370     int counter = 0;
371     for ( unsigned int locIndex = 0;
372         locIndex < UPRV_LENGTHOF(locales);
373         ++locIndex ) {
374 
375         Locale l = Locale::createFromName(locales[locIndex]);
376 
377         for ( unsigned int numberIndex = 0;
378             numberIndex < UPRV_LENGTHOF(numbers);
379             ++numberIndex ) {
380 
381             for ( unsigned int styleIndex = 0;
382                 styleIndex < UPRV_LENGTHOF(styles);
383                 ++styleIndex ) {
384 
385                 for ( unsigned int unitIndex = 0;
386                     unitIndex < UPRV_LENGTHOF(tunits);
387                     ++unitIndex ) {
388 
389                     TimeUnitAmount *tamt = new TimeUnitAmount(numbers[numberIndex], tunits[unitIndex], status);
390                     if (U_FAILURE(status)) {
391                         dataerrln("generating TimeUnitAmount Object failed.");
392 #ifdef TUFMTTS_DEBUG
393                         std::cout << "Failed to get TimeUnitAmount for " << tunits[unitIndex] << "\n";
394 #endif
395                         return;
396                     }
397 
398                     TimeUnitFormat *tfmt = new TimeUnitFormat(l, styles[styleIndex], status);
399                     if (U_FAILURE(status)) {
400                         dataerrln("generating TimeUnitAmount Object failed.");
401 #ifdef TUFMTTS_DEBUG
402                        std::cout <<  "Failed to get TimeUnitFormat for " << locales[locIndex] << "\n";
403 #endif
404                        return;
405                     }
406 
407                     Formattable fmt;
408                     UnicodeString str;
409 
410                     fmt.adoptObject(tamt);
411                     str = ((Format *)tfmt)->format(fmt, str, status);
412                     if (!assertSuccess("formatting relative time failed", status)) {
413                         delete tfmt;
414 #ifdef TUFMTTS_DEBUG
415                         std::cout <<  "Failed to format" << "\n";
416 #endif
417                         return;
418                     }
419 
420 #ifdef TUFMTTS_DEBUG
421                     char tmp[128];    //output
422                     char tmp1[128];    //expected
423                     int len = 0;
424                     u_strToUTF8(tmp, 128, &len, str.getTerminatedBuffer(), str.length(), &status);
425                     u_strToUTF8(tmp1, 128, &len, expected[counter].unescape().getTerminatedBuffer(), expected[counter].unescape().length(), &status);
426                     std::cout <<  "Formatted string : " << tmp << " expected : " << tmp1 << "\n";
427 #endif
428                     if (!assertEquals("formatted time string is not expected, locale: " + UnicodeString(locales[locIndex]) + " style: " + (int)styles[styleIndex] + " units: " + (int)tunits[unitIndex], expected[counter], str)) {
429                         delete tfmt;
430                         str.remove();
431                         return;
432                     }
433                     delete tfmt;
434                     str.remove();
435                     ++counter;
436                 }
437             }
438         }
439     }
440 }
441 
442 // Test bug9042
testGreekWithSanitization()443 void TimeUnitTest::testGreekWithSanitization() {
444 
445     UErrorCode status = U_ZERO_ERROR;
446     Locale elLoc("el");
447     NumberFormat* numberFmt = NumberFormat::createInstance(Locale("el"), status);
448     if (!assertSuccess("NumberFormat::createInstance for el locale", status, TRUE)) return;
449     numberFmt->setMaximumFractionDigits(1);
450 
451     TimeUnitFormat* timeUnitFormat = new TimeUnitFormat(elLoc, status);
452     if (!assertSuccess("TimeUnitFormat::TimeUnitFormat for el locale", status)) return;
453 
454     timeUnitFormat->setNumberFormat(*numberFmt, status);
455 
456     delete numberFmt;
457     delete timeUnitFormat;
458 }
459 
test10219Plurals()460 void TimeUnitTest::test10219Plurals() {
461     Locale usLocale("en_US");
462     double values[2] = {1.588, 1.011};
463     UnicodeString expected[2][3] = {
464         {"1 minute", "1.5 minutes", "1.58 minutes"},
465         {"1 minute", "1.0 minutes", "1.01 minutes"}
466     };
467     UErrorCode status = U_ZERO_ERROR;
468     TimeUnitFormat tuf(usLocale, status);
469     if (U_FAILURE(status)) {
470         dataerrln("generating TimeUnitFormat Object failed: %s", u_errorName(status));
471         return;
472     }
473     LocalPointer<DecimalFormat> nf((DecimalFormat *) NumberFormat::createInstance(usLocale, status));
474     if (U_FAILURE(status)) {
475         dataerrln("generating NumberFormat Object failed: %s", u_errorName(status));
476         return;
477     }
478     for (int32_t j = 0; j < UPRV_LENGTHOF(values); ++j) {
479         for (int32_t i = 0; i < UPRV_LENGTHOF(expected[j]); ++i) {
480             nf->setMinimumFractionDigits(i);
481             nf->setMaximumFractionDigits(i);
482             nf->setRoundingMode(DecimalFormat::kRoundDown);
483             tuf.setNumberFormat(*nf, status);
484             if (U_FAILURE(status)) {
485                 dataerrln("setting NumberFormat failed: %s", u_errorName(status));
486                 return;
487             }
488             UnicodeString actual;
489             Formattable fmt;
490             LocalPointer<TimeUnitAmount> tamt(
491                 new TimeUnitAmount(values[j], TimeUnit::UTIMEUNIT_MINUTE, status), status);
492             if (U_FAILURE(status)) {
493                 dataerrln("generating TimeUnitAmount Object failed: %s", u_errorName(status));
494                 return;
495             }
496             fmt.adoptObject(tamt.orphan());
497             tuf.format(fmt, actual, status);
498             if (U_FAILURE(status)) {
499                 dataerrln("Actual formatting failed: %s", u_errorName(status));
500                 return;
501             }
502             if (expected[j][i] != actual) {
503                 errln("Expected " + expected[j][i] + ", got " + actual);
504             }
505         }
506     }
507 
508     // test parsing
509     Formattable result;
510     ParsePosition pos;
511     UnicodeString formattedString = "1 minutes";
512     tuf.parseObject(formattedString, result, pos);
513     if (formattedString.length() != pos.getIndex()) {
514         errln("Expect parsing to go all the way to the end of the string.");
515     }
516 }
517 
TestBritishShortHourFallback()518 void TimeUnitTest::TestBritishShortHourFallback() {
519     // See ticket #11986 "incomplete fallback in MeasureFormat".
520     UErrorCode status = U_ZERO_ERROR;
521     Formattable oneHour(new TimeUnitAmount(1, TimeUnit::UTIMEUNIT_HOUR, status));
522     Locale en_GB("en_GB");
523     TimeUnitFormat formatter(en_GB, UTMUTFMT_ABBREVIATED_STYLE, status);
524     UnicodeString result;
525     formatter.format(oneHour, result, status);
526     assertSuccess("TestBritishShortHourFallback()", status);
527     assertEquals("TestBritishShortHourFallback()", UNICODE_STRING_SIMPLE("1 hr"), result, TRUE);
528 }
529 
530 #endif
531