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