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
25void 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
39static 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 */
57void 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
121void 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 */
261void 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
397void 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
414void 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