1 // © 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 ********************************************************************/
8 #include "unicode/utypes.h"
10 #if !UCONFIG_NO_FORMATTING
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"
20 //TODO: put as compilation flag
21 //#define TUFMTTS_DEBUG 1
27 class TimeUnitTest
: public IntlTest
{
28 void runIndexedTest(int32_t index
, UBool exec
, const char* &name
, char* /*par*/ ) {
29 if (exec
) logln("TestSuite TimeUnitTest");
31 TESTCASE_AUTO(testBasic
);
32 TESTCASE_AUTO(testAPI
);
33 TESTCASE_AUTO(testGreekWithFallback
);
34 TESTCASE_AUTO(testGreekWithSanitization
);
35 TESTCASE_AUTO(test10219Plurals
);
36 TESTCASE_AUTO(TestBritishShortHourFallback
);
42 * Performs basic tests
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.
57 void testGreekWithFallback();
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.
68 void testGreekWithSanitization();
71 * Performs unit test for ticket 10219 making sure that plurals work
72 * correctly with rounding.
74 void test10219Plurals();
76 void TestBritishShortHourFallback();
79 extern IntlTest
*createTimeUnitTest() {
80 return new TimeUnitTest();
83 // This function is more lenient than equals operator as it considers integer 3 hours and
84 // double 3.0 hours to be equal
85 static UBool
tmaEqual(const TimeUnitAmount
& left
, const TimeUnitAmount
& right
) {
86 if (left
.getTimeUnitField() != right
.getTimeUnitField()) {
89 UErrorCode status
= U_ZERO_ERROR
;
90 if (!left
.getNumber().isNumeric() || !right
.getNumber().isNumeric()) {
93 UBool result
= left
.getNumber().getDouble(status
) == right
.getNumber().getDouble(status
);
94 if (U_FAILURE(status
)) {
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
);
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;
116 std::cout
<< "locale: " << locales
[locIndex
] << "\n";
118 for (int style
= UTMUTFMT_FULL_STYLE
;
119 style
<= UTMUTFMT_ABBREVIATED_STYLE
;
121 for (TimeUnit::UTimeUnitFields j
= TimeUnit::UTIMEUNIT_YEAR
;
122 j
< TimeUnit::UTIMEUNIT_FIELD_COUNT
;
123 j
= (TimeUnit::UTimeUnitFields
)(j
+1)) {
125 std::cout
<< "time unit: " << j
<< "\n";
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
) {
130 std::cout
<< "number: " << tests
[i
] << "\n";
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;
140 char formatResult
[1000];
141 formatted
.extract(0, formatted
.length(), formatResult
, "UTF-8");
142 std::cout
<< "format result: " << formatResult
<< "\n";
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: ");
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: ");
160 delete formats
[UTMUTFMT_FULL_STYLE
];
161 delete formats
[UTMUTFMT_ABBREVIATED_STYLE
];
167 void TimeUnitTest::testAPI() {
168 //================= TimeUnit =================
169 UErrorCode status
= U_ZERO_ERROR
;
171 TimeUnit
* tmunit
= TimeUnit::createInstance(TimeUnit::UTIMEUNIT_YEAR
, status
);
172 if (!assertSuccess("TimeUnit::createInstance", status
)) return;
174 TimeUnit
* another
= tmunit
->clone();
175 TimeUnit
third(*tmunit
);
176 TimeUnit fourth
= third
;
178 assertTrue("orig and clone are equal", (*tmunit
== *another
));
179 assertTrue("copied and assigned are equal", (third
== fourth
));
181 TimeUnit
* tmunit_m
= TimeUnit::createInstance(TimeUnit::UTIMEUNIT_MONTH
, status
);
182 assertTrue("year != month", (*tmunit
!= *tmunit_m
));
184 TimeUnit::UTimeUnitFields field
= tmunit_m
->getTimeUnitField();
185 assertTrue("field of month time unit is month", (field
== TimeUnit::UTIMEUNIT_MONTH
));
187 //===== Interoperability with MeasureUnit ======
188 MeasureUnit
**ptrs
= new MeasureUnit
*[TimeUnit::UTIMEUNIT_FIELD_COUNT
];
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;
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).
207 "Time unit should be equal to corresponding MeasureUnit",
208 MeasureUnit(*ptr
) == *ptrs
[j
]);
214 for (int i
= 0; i
< TimeUnit::UTIMEUNIT_FIELD_COUNT
; ++i
) {
220 //================= TimeUnitAmount =================
222 Formattable
formattable((int32_t)2);
223 TimeUnitAmount
tma_long(formattable
, TimeUnit::UTIMEUNIT_DAY
, status
);
224 if (!assertSuccess("TimeUnitAmount(formattable...)", status
)) return;
226 formattable
.setDouble(2);
227 TimeUnitAmount
tma_double(formattable
, TimeUnit::UTIMEUNIT_DAY
, status
);
228 if (!assertSuccess("TimeUnitAmount(formattable...)", status
)) return;
230 formattable
.setDouble(3);
231 TimeUnitAmount
tma_double_3(formattable
, TimeUnit::UTIMEUNIT_DAY
, status
);
232 if (!assertSuccess("TimeUnitAmount(formattable...)", status
)) return;
234 TimeUnitAmount
tma(2, TimeUnit::UTIMEUNIT_DAY
, status
);
235 if (!assertSuccess("TimeUnitAmount(number...)", status
)) return;
237 TimeUnitAmount
tma_h(2, TimeUnit::UTIMEUNIT_HOUR
, status
);
238 if (!assertSuccess("TimeUnitAmount(number...)", status
)) return;
240 TimeUnitAmount
second(tma
);
241 TimeUnitAmount third_tma
= tma
;
242 TimeUnitAmount
* fourth_tma
= tma
.clone();
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
));
251 assertTrue("getTimeUnitField", (tma
.getTimeUnitField() == TimeUnit::UTIMEUNIT_DAY
));
254 //================= TimeUnitFormat =================
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;
261 assertTrue("TimeUnitFormat: en and fr diff", (*tmf_en
!= tmf_fr
));
263 TimeUnitFormat tmf_assign
= *tmf_en
;
264 assertTrue("TimeUnitFormat: orig and assign are equal", (*tmf_en
== tmf_assign
));
266 TimeUnitFormat
tmf_copy(tmf_fr
);
267 assertTrue("TimeUnitFormat: orig and copy are equal", (tmf_fr
== tmf_copy
));
269 TimeUnitFormat
* tmf_clone
= tmf_en
->clone();
270 assertTrue("TimeUnitFormat: orig and clone are equal", (*tmf_en
== *tmf_clone
));
273 tmf_en
->setLocale(Locale("fr"), status
);
274 if (!assertSuccess("setLocale(fr...)", status
)) return;
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
));
285 TimeUnitFormat
* en_long
= new TimeUnitFormat(Locale("en"), UTMUTFMT_FULL_STYLE
, status
);
286 if (!assertSuccess("TimeUnitFormat(en...)", status
)) return;
289 TimeUnitFormat
* en_short
= new TimeUnitFormat(Locale("en"), UTMUTFMT_ABBREVIATED_STYLE
, status
);
290 if (!assertSuccess("TimeUnitFormat(en...)", status
)) return;
293 TimeUnitFormat
* format
= new TimeUnitFormat(status
);
294 format
->setLocale(Locale("zh"), status
);
295 format
->setNumberFormat(*numberFmt
, status
);
296 if (!assertSuccess("TimeUnitFormat(en...)", status
)) return;
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.
307 void TimeUnitTest::testGreekWithFallback() {
308 UErrorCode status
= U_ZERO_ERROR
;
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};
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};
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
);
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
,
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
};
371 for ( unsigned int locIndex
= 0;
372 locIndex
< UPRV_LENGTHOF(locales
);
375 Locale l
= Locale::createFromName(locales
[locIndex
]);
377 for ( unsigned int numberIndex
= 0;
378 numberIndex
< UPRV_LENGTHOF(numbers
);
381 for ( unsigned int styleIndex
= 0;
382 styleIndex
< UPRV_LENGTHOF(styles
);
385 for ( unsigned int unitIndex
= 0;
386 unitIndex
< UPRV_LENGTHOF(tunits
);
389 LocalPointer
<TimeUnitAmount
>tamt(new TimeUnitAmount(numbers
[numberIndex
], tunits
[unitIndex
], status
));
390 if (U_FAILURE(status
)) {
391 dataerrln("generating TimeUnitAmount Object failed.");
393 std::cout
<< "Failed to get TimeUnitAmount for " << tunits
[unitIndex
] << "\n";
398 LocalPointer
<TimeUnitFormat
> tfmt(new TimeUnitFormat(l
, styles
[styleIndex
], status
));
399 if (U_FAILURE(status
)) {
400 dataerrln("generating TimeUnitAmount Object failed.");
402 std::cout
<< "Failed to get TimeUnitFormat for " << locales
[locIndex
] << "\n";
410 fmt
.adoptObject(tamt
.orphan());
411 str
= ((Format
*)tfmt
.getAlias())->format(fmt
, str
, status
);
412 if (!assertSuccess("formatting relative time failed", status
)) {
414 std::cout
<< "Failed to format" << "\n";
420 char tmp
[128]; //output
421 char tmp1
[128]; //expected
423 u_strToUTF8(tmp
, 128, &len
, str
.getTerminatedBuffer(), str
.length(), &status
);
424 u_strToUTF8(tmp1
, 128, &len
, expected
[counter
].unescape().getTerminatedBuffer(), expected
[counter
].unescape().length(), &status
);
425 std::cout
<< "Formatted string : " << tmp
<< " expected : " << tmp1
<< "\n";
427 if (!assertEquals("formatted time string is not expected, locale: " + UnicodeString(locales
[locIndex
]) + " style: " + (int)styles
[styleIndex
] + " units: " + (int)tunits
[unitIndex
], expected
[counter
], str
)) {
440 void TimeUnitTest::testGreekWithSanitization() {
442 UErrorCode status
= U_ZERO_ERROR
;
444 NumberFormat
* numberFmt
= NumberFormat::createInstance(Locale("el"), status
);
445 if (!assertSuccess("NumberFormat::createInstance for el locale", status
, TRUE
)) return;
446 numberFmt
->setMaximumFractionDigits(1);
448 TimeUnitFormat
* timeUnitFormat
= new TimeUnitFormat(elLoc
, status
);
449 if (!assertSuccess("TimeUnitFormat::TimeUnitFormat for el locale", status
)) return;
451 timeUnitFormat
->setNumberFormat(*numberFmt
, status
);
454 delete timeUnitFormat
;
457 void TimeUnitTest::test10219Plurals() {
458 Locale
usLocale("en_US");
459 double values
[2] = {1.588, 1.011};
460 UnicodeString expected
[2][3] = {
461 {"1 minute", "1.5 minutes", "1.58 minutes"},
462 {"1 minute", "1.0 minutes", "1.01 minutes"}
464 UErrorCode status
= U_ZERO_ERROR
;
465 TimeUnitFormat
tuf(usLocale
, status
);
466 if (U_FAILURE(status
)) {
467 dataerrln("generating TimeUnitFormat Object failed: %s", u_errorName(status
));
470 LocalPointer
<DecimalFormat
> nf((DecimalFormat
*) NumberFormat::createInstance(usLocale
, status
));
471 if (U_FAILURE(status
)) {
472 dataerrln("generating NumberFormat Object failed: %s", u_errorName(status
));
475 for (int32_t j
= 0; j
< UPRV_LENGTHOF(values
); ++j
) {
476 for (int32_t i
= 0; i
< UPRV_LENGTHOF(expected
[j
]); ++i
) {
477 nf
->setMinimumFractionDigits(i
);
478 nf
->setMaximumFractionDigits(i
);
479 nf
->setRoundingMode(DecimalFormat::kRoundDown
);
480 tuf
.setNumberFormat(*nf
, status
);
481 if (U_FAILURE(status
)) {
482 dataerrln("setting NumberFormat failed: %s", u_errorName(status
));
485 UnicodeString actual
;
487 LocalPointer
<TimeUnitAmount
> tamt(
488 new TimeUnitAmount(values
[j
], TimeUnit::UTIMEUNIT_MINUTE
, status
), status
);
489 if (U_FAILURE(status
)) {
490 dataerrln("generating TimeUnitAmount Object failed: %s", u_errorName(status
));
493 fmt
.adoptObject(tamt
.orphan());
494 tuf
.format(fmt
, actual
, status
);
495 if (U_FAILURE(status
)) {
496 dataerrln("Actual formatting failed: %s", u_errorName(status
));
499 if (expected
[j
][i
] != actual
) {
500 errln("Expected " + expected
[j
][i
] + ", got " + actual
);
508 UnicodeString formattedString
= "1 minutes";
509 tuf
.parseObject(formattedString
, result
, pos
);
510 if (formattedString
.length() != pos
.getIndex()) {
511 errln("Expect parsing to go all the way to the end of the string.");
515 void TimeUnitTest::TestBritishShortHourFallback() {
516 // See ticket #11986 "incomplete fallback in MeasureFormat".
517 UErrorCode status
= U_ZERO_ERROR
;
518 Formattable
oneHour(new TimeUnitAmount(1, TimeUnit::UTIMEUNIT_HOUR
, status
));
519 Locale
en_GB("en_GB");
520 TimeUnitFormat
formatter(en_GB
, UTMUTFMT_ABBREVIATED_STYLE
, status
);
521 UnicodeString result
;
522 formatter
.format(oneHour
, result
, status
);
523 assertSuccess("TestBritishShortHourFallback()", status
);
524 assertEquals("TestBritishShortHourFallback()", UNICODE_STRING_SIMPLE("1 hr"), result
, TRUE
);