1/*
2*******************************************************************************
3* Copyright (C) 2014, International Business Machines Corporation and         *
4* others. All Rights Reserved.                                                *
5*******************************************************************************
6*
7* File MEASFMTTEST.CPP
8*
9*******************************************************************************
10*/
11#include <stdio.h>
12#include <stdlib.h>
13
14#include "intltest.h"
15
16#if !UCONFIG_NO_FORMATTING
17
18#include "unicode/decimfmt.h"
19#include "unicode/measfmt.h"
20#include "unicode/measure.h"
21#include "unicode/measunit.h"
22#include "unicode/tmunit.h"
23#include "charstr.h"
24
25#define LENGTHOF(array) (int32_t)(sizeof(array) / sizeof((array)[0]))
26
27struct ExpectedResult {
28    const Measure *measures;
29    int32_t count;
30    const char *expected;
31};
32
33class MeasureFormatTest : public IntlTest {
34public:
35    MeasureFormatTest() {
36    }
37
38    void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par=0);
39private:
40    void TestBasic();
41    void TestGetAvailable();
42    void TestExamplesInDocs();
43    void TestFormatPeriodEn();
44    void Test10219FractionalPlurals();
45    void TestGreek();
46    void TestFormatSingleArg();
47    void TestFormatMeasuresZeroArg();
48    void TestMultiples();
49    void TestGram();
50    void TestCurrencies();
51    void TestFieldPosition();
52    void TestFieldPositionMultiple();
53    void TestBadArg();
54    void TestEquality();
55    void TestDoubleZero();
56    void verifyFormat(
57        const char *description,
58        const MeasureFormat &fmt,
59        const Measure *measures,
60        int32_t measureCount,
61        const char *expected);
62    void verifyFormatWithPrefix(
63        const char *description,
64        const MeasureFormat &fmt,
65        const UnicodeString &prefix,
66        const Measure *measures,
67        int32_t measureCount,
68        const char *expected);
69    void verifyFormat(
70        const char *description,
71        const MeasureFormat &fmt,
72        const ExpectedResult *expectedResults,
73        int32_t count);
74    void helperTestMultiples(
75        const Locale &locale,
76        UMeasureFormatWidth width,
77        const char *expected);
78    void verifyFieldPosition(
79        const char *description,
80        const MeasureFormat &fmt,
81        const UnicodeString &prefix,
82        const Measure *measures,
83        int32_t measureCount,
84        NumberFormat::EAlignmentFields field,
85        int32_t start,
86        int32_t end);
87};
88
89void MeasureFormatTest::runIndexedTest(
90        int32_t index, UBool exec, const char *&name, char *) {
91    if (exec) {
92        logln("TestSuite MeasureFormatTest: ");
93    }
94    TESTCASE_AUTO_BEGIN;
95    TESTCASE_AUTO(TestBasic);
96    TESTCASE_AUTO(TestGetAvailable);
97    TESTCASE_AUTO(TestExamplesInDocs);
98    TESTCASE_AUTO(TestFormatPeriodEn);
99    TESTCASE_AUTO(Test10219FractionalPlurals);
100    TESTCASE_AUTO(TestGreek);
101    TESTCASE_AUTO(TestFormatSingleArg);
102    TESTCASE_AUTO(TestFormatMeasuresZeroArg);
103    TESTCASE_AUTO(TestMultiples);
104    TESTCASE_AUTO(TestGram);
105    TESTCASE_AUTO(TestCurrencies);
106    TESTCASE_AUTO(TestFieldPosition);
107    TESTCASE_AUTO(TestFieldPositionMultiple);
108    TESTCASE_AUTO(TestBadArg);
109    TESTCASE_AUTO(TestEquality);
110    TESTCASE_AUTO(TestDoubleZero);
111    TESTCASE_AUTO_END;
112}
113
114void MeasureFormatTest::TestBasic() {
115    UErrorCode status = U_ZERO_ERROR;
116    MeasureUnit *ptr1 = MeasureUnit::createArcMinute(status);
117    MeasureUnit *ptr2 = MeasureUnit::createArcMinute(status);
118    if (!(*ptr1 == *ptr2)) {
119        errln("Expect == to work.");
120    }
121    if (*ptr1 != *ptr2) {
122        errln("Expect != to work.");
123    }
124    MeasureUnit *ptr3 = MeasureUnit::createMeter(status);
125    if (*ptr1 == *ptr3) {
126        errln("Expect == to work.");
127    }
128    if (!(*ptr1 != *ptr3)) {
129        errln("Expect != to work.");
130    }
131    MeasureUnit *ptr4 = (MeasureUnit *) ptr1->clone();
132    if (*ptr1 != *ptr4) {
133        errln("Expect clone to work.");
134    }
135    MeasureUnit stack;
136    stack = *ptr1;
137    if (*ptr1 != stack) {
138        errln("Expect assignment to work.");
139    }
140
141    delete ptr1;
142    delete ptr2;
143    delete ptr3;
144    delete ptr4;
145}
146
147void MeasureFormatTest::TestGetAvailable() {
148    MeasureUnit *units = NULL;
149    UErrorCode status = U_ZERO_ERROR;
150    int32_t totalCount = MeasureUnit::getAvailable(units, 0, status);
151    while (status == U_BUFFER_OVERFLOW_ERROR) {
152        status = U_ZERO_ERROR;
153        delete [] units;
154        units = new MeasureUnit[totalCount];
155        totalCount = MeasureUnit::getAvailable(units, totalCount, status);
156    }
157    if (U_FAILURE(status)) {
158        dataerrln("Failure creating format object - %s", u_errorName(status));
159        delete [] units;
160        return;
161    }
162    if (totalCount < 200) {
163        errln("Expect at least 200 measure units including currencies.");
164    }
165    delete [] units;
166    StringEnumeration *types = MeasureUnit::getAvailableTypes(status);
167    if (U_FAILURE(status)) {
168        dataerrln("Failure getting types - %s", u_errorName(status));
169        delete types;
170        return;
171    }
172    if (types->count(status) < 10) {
173        errln("Expect at least 10 distinct unit types.");
174    }
175    units = NULL;
176    int32_t unitCapacity = 0;
177    int32_t unitCountSum = 0;
178    for (
179            const char* type = types->next(NULL, status);
180            type != NULL;
181            type = types->next(NULL, status)) {
182        int32_t unitCount = MeasureUnit::getAvailable(type, units, unitCapacity, status);
183        while (status == U_BUFFER_OVERFLOW_ERROR) {
184            status = U_ZERO_ERROR;
185            delete [] units;
186            units = new MeasureUnit[unitCount];
187            unitCapacity = unitCount;
188            unitCount = MeasureUnit::getAvailable(type, units, unitCapacity, status);
189        }
190        if (U_FAILURE(status)) {
191            dataerrln("Failure getting units - %s", u_errorName(status));
192            delete [] units;
193            delete types;
194            return;
195        }
196        if (unitCount < 1) {
197            errln("Expect at least one unit count per type.");
198        }
199        unitCountSum += unitCount;
200    }
201    if (unitCountSum != totalCount) {
202        errln("Expected total unit count to equal sum of unit counts by type.");
203    }
204    delete [] units;
205    delete types;
206}
207
208void MeasureFormatTest::TestExamplesInDocs() {
209    UErrorCode status = U_ZERO_ERROR;
210    MeasureFormat fmtFr(Locale::getFrench(), UMEASFMT_WIDTH_SHORT, status);
211    MeasureFormat fmtFrFull(
212            Locale::getFrench(), UMEASFMT_WIDTH_WIDE, status);
213    MeasureFormat fmtFrNarrow(
214            Locale::getFrench(), UMEASFMT_WIDTH_NARROW, status);
215    MeasureFormat fmtEn(Locale::getUS(), UMEASFMT_WIDTH_WIDE, status);
216    if (!assertSuccess("Error creating formatters", status)) {
217        return;
218    }
219    Measure measureC(23, MeasureUnit::createCelsius(status), status);
220    Measure measureF(70, MeasureUnit::createFahrenheit(status), status);
221    Measure feetAndInches[] = {
222            Measure(70, MeasureUnit::createFoot(status), status),
223            Measure(5.3, MeasureUnit::createInch(status), status)};
224    Measure footAndInch[] = {
225            Measure(1, MeasureUnit::createFoot(status), status),
226            Measure(1, MeasureUnit::createInch(status), status)};
227    Measure inchAndFeet[] = {
228            Measure(1, MeasureUnit::createInch(status), status),
229            Measure(2, MeasureUnit::createFoot(status), status)};
230    if (!assertSuccess("Error creating measurements.", status)) {
231        return;
232    }
233    verifyFormat(
234            "Celsius",
235            fmtFr,
236            &measureC,
237            1,
238            "23 \\u00B0C");
239    verifyFormatWithPrefix(
240            "Celsius",
241            fmtFr,
242            "Prefix: ",
243            &measureC,
244            1,
245            "Prefix: 23 \\u00B0C");
246    verifyFormat(
247            "Fahrenheit",
248            fmtFr,
249            &measureF,
250            1,
251            "70 \\u00B0F");
252    verifyFormat(
253            "Feet and inches",
254            fmtFrFull,
255            feetAndInches,
256            LENGTHOF(feetAndInches),
257            "70 pieds et 5,3 pouces");
258    verifyFormatWithPrefix(
259            "Feet and inches",
260            fmtFrFull,
261            "Prefix: ",
262            feetAndInches,
263            LENGTHOF(feetAndInches),
264            "Prefix: 70 pieds et 5,3 pouces");
265    verifyFormat(
266            "Foot and inch",
267            fmtFrFull,
268            footAndInch,
269            LENGTHOF(footAndInch),
270            "1 pied et 1 pouce");
271    verifyFormat(
272            "Foot and inch narrow",
273            fmtFrNarrow,
274            footAndInch,
275            LENGTHOF(footAndInch),
276            "1\\u2032 1\\u2033");
277    verifyFormat(
278            "Inch and feet",
279            fmtEn,
280            inchAndFeet,
281            LENGTHOF(inchAndFeet),
282            "1 inch, 2 feet");
283}
284
285void MeasureFormatTest::TestFormatPeriodEn() {
286    UErrorCode status = U_ZERO_ERROR;
287    Measure t_19m[] = {Measure(19, MeasureUnit::createMinute(status), status)};
288    Measure t_1h_23_5s[] = {
289            Measure(1.0, MeasureUnit::createHour(status), status),
290            Measure(23.5, MeasureUnit::createSecond(status), status)
291    };
292    Measure t_1h_23_5m[] = {
293            Measure(1.0, MeasureUnit::createHour(status), status),
294            Measure(23.5, MeasureUnit::createMinute(status), status)
295    };
296    Measure t_1h_0m_23s[] = {
297            Measure(
298                    1.0,
299                    TimeUnit::createInstance(
300                            TimeUnit::UTIMEUNIT_HOUR, status),
301                    status),
302            Measure(
303                    0.0,
304                    TimeUnit::createInstance(
305                            TimeUnit::UTIMEUNIT_MINUTE, status),
306                     status),
307            Measure(
308                    23,
309                    TimeUnit::createInstance(
310                            TimeUnit::UTIMEUNIT_SECOND, status),
311                    status)
312    };
313    Measure t_2y_5M_3w_4d[] = {
314            Measure(2.0, MeasureUnit::createYear(status), status),
315            Measure(5.0, MeasureUnit::createMonth(status), status),
316            Measure(3.0, MeasureUnit::createWeek(status), status),
317            Measure(4.0, MeasureUnit::createDay(status), status)
318    };
319    Measure t_1m_59_9996s[] = {
320            Measure(1.0, MeasureUnit::createMinute(status), status),
321            Measure(59.9996, MeasureUnit::createSecond(status), status)
322    };
323    Measure t_5h_17m[] = {
324            Measure(5.0, MeasureUnit::createHour(status), status),
325            Measure(17.0, MeasureUnit::createMinute(status), status)
326    };
327    Measure t_neg5h_17m[] = {
328            Measure(-5.0, MeasureUnit::createHour(status), status),
329            Measure(17.0, MeasureUnit::createMinute(status), status)
330    };
331    Measure t_19m_28s[] = {
332            Measure(19.0, MeasureUnit::createMinute(status), status),
333            Measure(28.0, MeasureUnit::createSecond(status), status)
334    };
335    Measure t_0h_0m_9s[] = {
336            Measure(0.0, MeasureUnit::createHour(status), status),
337            Measure(0.0, MeasureUnit::createMinute(status), status),
338            Measure(9.0, MeasureUnit::createSecond(status), status)
339    };
340    Measure t_0h_0m_17s[] = {
341            Measure(0.0, MeasureUnit::createHour(status), status),
342            Measure(0.0, MeasureUnit::createMinute(status), status),
343            Measure(17.0, MeasureUnit::createSecond(status), status)
344    };
345    Measure t_6h_56_92m[] = {
346            Measure(6.0, MeasureUnit::createHour(status), status),
347            Measure(56.92, MeasureUnit::createMinute(status), status)
348    };
349    Measure t_3h_4s_5m[] = {
350            Measure(3.0, MeasureUnit::createHour(status), status),
351            Measure(4.0, MeasureUnit::createSecond(status), status),
352            Measure(5.0, MeasureUnit::createMinute(status), status)
353    };
354    Measure t_6_7h_56_92m[] = {
355            Measure(6.7, MeasureUnit::createHour(status), status),
356            Measure(56.92, MeasureUnit::createMinute(status), status)
357    };
358
359    Measure t_3h_5h[] = {
360            Measure(3.0, MeasureUnit::createHour(status), status),
361            Measure(5.0, MeasureUnit::createHour(status), status)
362    };
363
364    if (!assertSuccess("Error creating Measure objects", status)) {
365        return;
366    }
367
368    ExpectedResult fullData[] = {
369            {t_1m_59_9996s, LENGTHOF(t_1m_59_9996s), "1 minute, 59.9996 seconds"},
370            {t_19m, LENGTHOF(t_19m), "19 minutes"},
371            {t_1h_23_5s, LENGTHOF(t_1h_23_5s), "1 hour, 23.5 seconds"},
372            {t_1h_23_5m, LENGTHOF(t_1h_23_5m), "1 hour, 23.5 minutes"},
373            {t_1h_0m_23s, LENGTHOF(t_1h_0m_23s), "1 hour, 0 minutes, 23 seconds"},
374            {t_2y_5M_3w_4d, LENGTHOF(t_2y_5M_3w_4d), "2 years, 5 months, 3 weeks, 4 days"}};
375
376    ExpectedResult abbrevData[] = {
377            {t_1m_59_9996s, LENGTHOF(t_1m_59_9996s), "1 min, 59.9996 secs"},
378            {t_19m, LENGTHOF(t_19m), "19 mins"},
379            {t_1h_23_5s, LENGTHOF(t_1h_23_5s), "1 hr, 23.5 secs"},
380            {t_1h_23_5m, LENGTHOF(t_1h_23_5m), "1 hr, 23.5 mins"},
381            {t_1h_0m_23s, LENGTHOF(t_1h_0m_23s), "1 hr, 0 mins, 23 secs"},
382            {t_2y_5M_3w_4d, LENGTHOF(t_2y_5M_3w_4d), "2 yrs, 5 mths, 3 wks, 4 days"}};
383
384    ExpectedResult narrowData[] = {
385            {t_1m_59_9996s, LENGTHOF(t_1m_59_9996s), "1m 59.9996s"},
386            {t_19m, LENGTHOF(t_19m), "19m"},
387            {t_1h_23_5s, LENGTHOF(t_1h_23_5s), "1h 23.5s"},
388            {t_1h_23_5m, LENGTHOF(t_1h_23_5m), "1h 23.5m"},
389            {t_1h_0m_23s, LENGTHOF(t_1h_0m_23s), "1h 0m 23s"},
390            {t_2y_5M_3w_4d, LENGTHOF(t_2y_5M_3w_4d), "2y 5m 3w 4d"}};
391
392    ExpectedResult numericData[] = {
393            {t_1m_59_9996s, LENGTHOF(t_1m_59_9996s), "1:59.9996"},
394            {t_19m, LENGTHOF(t_19m), "19m"},
395            {t_1h_23_5s, LENGTHOF(t_1h_23_5s), "1:00:23.5"},
396            {t_1h_23_5m, LENGTHOF(t_1h_23_5m), "1:23.5"},
397            {t_1h_0m_23s, LENGTHOF(t_1h_0m_23s), "1:00:23"},
398            {t_5h_17m, LENGTHOF(t_5h_17m), "5:17"},
399            {t_neg5h_17m, LENGTHOF(t_neg5h_17m), "-5h 17m"},
400            {t_19m_28s, LENGTHOF(t_19m_28s), "19:28"},
401            {t_2y_5M_3w_4d, LENGTHOF(t_2y_5M_3w_4d), "2y 5m 3w 4d"},
402            {t_0h_0m_9s, LENGTHOF(t_0h_0m_9s), "0:00:09"},
403            {t_6h_56_92m, LENGTHOF(t_6h_56_92m), "6:56.92"},
404            {t_6_7h_56_92m, LENGTHOF(t_6_7h_56_92m), "6:56.92"},
405            {t_3h_4s_5m, LENGTHOF(t_3h_4s_5m), "3h 4s 5m"},
406            {t_3h_5h, LENGTHOF(t_3h_5h), "3h 5h"}};
407
408    ExpectedResult fullDataDe[] = {
409            {t_1m_59_9996s, LENGTHOF(t_1m_59_9996s), "1 Minute und 59,9996 Sekunden"},
410            {t_19m, LENGTHOF(t_19m), "19 Minuten"},
411            {t_1h_23_5s, LENGTHOF(t_1h_23_5s), "1 Stunde und 23,5 Sekunden"},
412            {t_1h_23_5m, LENGTHOF(t_1h_23_5m), "1 Stunde und 23,5 Minuten"},
413            {t_1h_0m_23s, LENGTHOF(t_1h_0m_23s), "1 Stunde, 0 Minuten und 23 Sekunden"},
414            {t_2y_5M_3w_4d, LENGTHOF(t_2y_5M_3w_4d), "2 Jahre, 5 Monate, 3 Wochen und 4 Tage"}};
415
416    ExpectedResult numericDataDe[] = {
417            {t_1m_59_9996s, LENGTHOF(t_1m_59_9996s), "1:59,9996"},
418            {t_19m, LENGTHOF(t_19m), "19 Min."},
419            {t_1h_23_5s, LENGTHOF(t_1h_23_5s), "1:00:23,5"},
420            {t_1h_23_5m, LENGTHOF(t_1h_23_5m), "1:23,5"},
421            {t_1h_0m_23s, LENGTHOF(t_1h_0m_23s), "1:00:23"},
422            {t_5h_17m, LENGTHOF(t_5h_17m), "5:17"},
423            {t_19m_28s, LENGTHOF(t_19m_28s), "19:28"},
424            {t_2y_5M_3w_4d, LENGTHOF(t_2y_5M_3w_4d), "2 J, 5 M, 3 W und 4 T"},
425            {t_0h_0m_17s, LENGTHOF(t_0h_0m_17s), "0:00:17"},
426            {t_6h_56_92m, LENGTHOF(t_6h_56_92m), "6:56,92"},
427            {t_3h_5h, LENGTHOF(t_3h_5h), "3 Std., 5 Std."}};
428
429    Locale en(Locale::getEnglish());
430    LocalPointer<NumberFormat> nf(NumberFormat::createInstance(en, status));
431    if (U_FAILURE(status)) {
432        dataerrln("Error creating number format en object - %s", u_errorName(status));
433        return;
434    }
435    nf->setMaximumFractionDigits(4);
436    MeasureFormat mf(en, UMEASFMT_WIDTH_WIDE, (NumberFormat *) nf->clone(), status);
437    if (!assertSuccess("Error creating measure format en WIDE", status)) {
438        return;
439    }
440    verifyFormat("en WIDE", mf, fullData, LENGTHOF(fullData));
441
442    // exercise copy constructor
443    {
444        MeasureFormat mf2(mf);
445        verifyFormat("en WIDE copy", mf2, fullData, LENGTHOF(fullData));
446    }
447    // exercise clone
448    {
449        MeasureFormat *mf3 = (MeasureFormat *) mf.clone();
450        verifyFormat("en WIDE copy", *mf3, fullData, LENGTHOF(fullData));
451        delete mf3;
452    }
453    mf = MeasureFormat(en, UMEASFMT_WIDTH_SHORT, (NumberFormat *) nf->clone(), status);
454    if (!assertSuccess("Error creating measure format en SHORT", status)) {
455        return;
456    }
457    verifyFormat("en SHORT", mf, abbrevData, LENGTHOF(abbrevData));
458    mf = MeasureFormat(en, UMEASFMT_WIDTH_NARROW, (NumberFormat *) nf->clone(), status);
459    if (!assertSuccess("Error creating measure format en NARROW", status)) {
460        return;
461    }
462    verifyFormat("en NARROW", mf, narrowData, LENGTHOF(narrowData));
463    mf = MeasureFormat(en, UMEASFMT_WIDTH_NUMERIC, (NumberFormat *) nf->clone(), status);
464    if (!assertSuccess("Error creating measure format en NUMERIC", status)) {
465        return;
466    }
467    verifyFormat("en NUMERIC", mf, numericData, LENGTHOF(numericData));
468
469    Locale de(Locale::getGerman());
470    nf.adoptInstead(NumberFormat::createInstance(de, status));
471    if (!assertSuccess("Error creating number format de object", status)) {
472        return;
473    }
474    nf->setMaximumFractionDigits(4);
475    mf = MeasureFormat(de, UMEASFMT_WIDTH_WIDE, (NumberFormat *) nf->clone(), status);
476    if (!assertSuccess("Error creating measure format de WIDE", status)) {
477        return;
478    }
479    verifyFormat("de WIDE", mf, fullDataDe, LENGTHOF(fullDataDe));
480    mf = MeasureFormat(de, UMEASFMT_WIDTH_NUMERIC, (NumberFormat *) nf->clone(), status);
481    if (!assertSuccess("Error creating measure format de NUMERIC", status)) {
482        return;
483    }
484    verifyFormat("de NUMERIC", mf, numericDataDe, LENGTHOF(numericDataDe));
485}
486
487void MeasureFormatTest::Test10219FractionalPlurals() {
488    Locale en(Locale::getEnglish());
489    double values[] = {1.588, 1.011};
490    const char *expected[2][3] = {
491            {"1 minute", "1.5 minutes", "1.58 minutes"},
492            {"1 minute", "1.0 minutes", "1.01 minutes"}
493    };
494    UErrorCode status = U_ZERO_ERROR;
495    for (int j = 0; j < LENGTHOF(values); j++) {
496        for (int i = 0; i < LENGTHOF(expected[j]); i++) {
497            DecimalFormat *df =
498                (DecimalFormat *) NumberFormat::createInstance(en, status);
499            if (U_FAILURE(status)) {
500                dataerrln("Error creating Number format - %s", u_errorName(status));
501                return;
502            }
503            df->setRoundingMode(DecimalFormat::kRoundDown);
504            df->setMinimumFractionDigits(i);
505            df->setMaximumFractionDigits(i);
506            MeasureFormat mf(en, UMEASFMT_WIDTH_WIDE, df, status);
507            if (!assertSuccess("Error creating Measure format", status)) {
508                return;
509            }
510            Measure measure(values[j], MeasureUnit::createMinute(status), status);
511            if (!assertSuccess("Error creating Measure unit", status)) {
512                return;
513            }
514            verifyFormat("Test10219", mf, &measure, 1, expected[j][i]);
515        }
516    }
517}
518
519static MeasureUnit toMeasureUnit(MeasureUnit *adopted) {
520    MeasureUnit result(*adopted);
521    delete adopted;
522    return result;
523}
524
525void MeasureFormatTest::TestGreek() {
526    Locale locales[] = {Locale("el_GR"), Locale("el")};
527    UErrorCode status = U_ZERO_ERROR;
528    MeasureUnit units[] = {
529        toMeasureUnit(MeasureUnit::createSecond(status)),
530        toMeasureUnit(MeasureUnit::createMinute(status)),
531        toMeasureUnit(MeasureUnit::createHour(status)),
532        toMeasureUnit(MeasureUnit::createDay(status)),
533        toMeasureUnit(MeasureUnit::createWeek(status)),
534        toMeasureUnit(MeasureUnit::createMonth(status)),
535        toMeasureUnit(MeasureUnit::createYear(status))};
536    if (!assertSuccess("Error creating Measure units", status)) {
537        return;
538    }
539    UMeasureFormatWidth styles[] = {
540            UMEASFMT_WIDTH_WIDE,
541            UMEASFMT_WIDTH_SHORT};
542    int32_t numbers[] = {1, 7};
543    const char *expected[] = {
544        "1 \\u03B4\\u03B5\\u03C5\\u03C4\\u03B5\\u03C1\\u03CC\\u03BB\\u03B5\\u03C0\\u03C4\\u03BF",
545        "1 \\u03BB\\u03B5\\u03C0\\u03C4\\u03CC",
546        "1 \\u03CE\\u03C1\\u03B1",
547        "1 \\u03B7\\u03BC\\u03AD\\u03C1\\u03B1",
548        "1 \\u03B5\\u03B2\\u03B4\\u03BF\\u03BC\\u03AC\\u03B4\\u03B1",
549        "1 \\u03BC\\u03AE\\u03BD\\u03B1\\u03C2",
550        "1 \\u03AD\\u03C4\\u03BF\\u03C2",
551        "1 \\u03B4\\u03B5\\u03C5\\u03C4.",
552        "1 \\u03BB\\u03B5\\u03C0.",
553        "1 \\u03CE\\u03C1\\u03B1",
554        "1 \\u03B7\\u03BC\\u03AD\\u03C1\\u03B1",
555        "1 \\u03B5\\u03B2\\u03B4.",
556        "1 \\u03BC\\u03AE\\u03BD.",
557        "1 \\u03AD\\u03C4\\u03BF\\u03C2",
558        "7 \\u03B4\\u03B5\\u03C5\\u03C4\\u03B5\\u03C1\\u03CC\\u03BB\\u03B5\\u03C0\\u03C4\\u03B1",
559        "7 \\u03BB\\u03B5\\u03C0\\u03C4\\u03AC",
560        "7 \\u03CE\\u03C1\\u03B5\\u03C2",
561        "7 \\u03B7\\u03BC\\u03AD\\u03C1\\u03B5\\u03C2",
562        "7 \\u03B5\\u03B2\\u03B4\\u03BF\\u03BC\\u03AC\\u03B4\\u03B5\\u03C2",
563        "7 \\u03BC\\u03AE\\u03BD\\u03B5\\u03C2",
564        "7 \\u03AD\\u03C4\\u03B7",
565        "7 \\u03B4\\u03B5\\u03C5\\u03C4.",
566        "7 \\u03BB\\u03B5\\u03C0.",
567        "7 \\u03CE\\u03C1\\u03B5\\u03C2",
568        "7 \\u03B7\\u03BC\\u03AD\\u03C1\\u03B5\\u03C2",
569        "7 \\u03B5\\u03B2\\u03B4.",
570        "7 \\u03BC\\u03AE\\u03BD.",
571        "7 \\u03AD\\u03C4\\u03B7",
572        "1 \\u03B4\\u03B5\\u03C5\\u03C4\\u03B5\\u03C1\\u03CC\\u03BB\\u03B5\\u03C0\\u03C4\\u03BF",
573        "1 \\u03BB\\u03B5\\u03C0\\u03C4\\u03CC",
574        "1 \\u03CE\\u03C1\\u03B1",
575        "1 \\u03B7\\u03BC\\u03AD\\u03C1\\u03B1",
576        "1 \\u03B5\\u03B2\\u03B4\\u03BF\\u03BC\\u03AC\\u03B4\\u03B1",
577        "1 \\u03BC\\u03AE\\u03BD\\u03B1\\u03C2",
578        "1 \\u03AD\\u03C4\\u03BF\\u03C2",
579        "1 \\u03B4\\u03B5\\u03C5\\u03C4.",
580        "1 \\u03BB\\u03B5\\u03C0.",
581        "1 \\u03CE\\u03C1\\u03B1",
582        "1 \\u03B7\\u03BC\\u03AD\\u03C1\\u03B1",
583        "1 \\u03B5\\u03B2\\u03B4.",
584        "1 \\u03BC\\u03AE\\u03BD.",
585        "1 \\u03AD\\u03C4\\u03BF\\u03C2",
586        "7 \\u03B4\\u03B5\\u03C5\\u03C4\\u03B5\\u03C1\\u03CC\\u03BB\\u03B5\\u03C0\\u03C4\\u03B1",
587        "7 \\u03BB\\u03B5\\u03C0\\u03C4\\u03AC",
588        "7 \\u03CE\\u03C1\\u03B5\\u03C2",
589        "7 \\u03B7\\u03BC\\u03AD\\u03C1\\u03B5\\u03C2",
590        "7 \\u03B5\\u03B2\\u03B4\\u03BF\\u03BC\\u03AC\\u03B4\\u03B5\\u03C2",
591        "7 \\u03BC\\u03AE\\u03BD\\u03B5\\u03C2",
592        "7 \\u03AD\\u03C4\\u03B7",
593        "7 \\u03B4\\u03B5\\u03C5\\u03C4.",
594        "7 \\u03BB\\u03B5\\u03C0.",
595        "7 \\u03CE\\u03C1\\u03B5\\u03C2",
596        "7 \\u03B7\\u03BC\\u03AD\\u03C1\\u03B5\\u03C2",
597        "7 \\u03B5\\u03B2\\u03B4.",
598        "7 \\u03BC\\u03AE\\u03BD.",
599        "7 \\u03AD\\u03C4\\u03B7"};
600
601    int32_t counter = 0;
602    for (int32_t locIndex = 0; locIndex < LENGTHOF(locales); ++locIndex ) {
603        for( int32_t numIndex = 0; numIndex < LENGTHOF(numbers); ++numIndex ) {
604            for ( int32_t styleIndex = 0; styleIndex < LENGTHOF(styles); ++styleIndex ) {
605                for ( int32_t unitIndex = 0; unitIndex < LENGTHOF(units); ++unitIndex ) {
606                    Measure measure(numbers[numIndex], new MeasureUnit(units[unitIndex]), status);
607                    if (!assertSuccess("Error creating Measure", status)) {
608                        return;
609                    }
610                    MeasureFormat fmt(locales[locIndex], styles[styleIndex], status);
611                    if (!assertSuccess("Error creating Measure format", status)) {
612                        return;
613                    }
614                    verifyFormat("TestGreek", fmt, &measure, 1, expected[counter]);
615                    ++counter;
616                }
617            }
618        }
619    }
620}
621
622void MeasureFormatTest::TestFormatSingleArg() {
623    UErrorCode status = U_ZERO_ERROR;
624    MeasureFormat fmt("en", UMEASFMT_WIDTH_WIDE, status);
625    if (!assertSuccess("Error creating formatter", status)) {
626        return;
627    }
628    UnicodeString buffer;
629    FieldPosition pos(0);
630    fmt.format(
631            new Measure(3.5, MeasureUnit::createFoot(status), status),
632            buffer,
633            pos,
634            status);
635    if (!assertSuccess("Error formatting", status)) {
636        return;
637    }
638    assertEquals(
639            "TestFormatSingleArg",
640            UnicodeString("3.5 feet"),
641            buffer);
642}
643
644void MeasureFormatTest::TestFormatMeasuresZeroArg() {
645    UErrorCode status = U_ZERO_ERROR;
646    MeasureFormat fmt("en", UMEASFMT_WIDTH_WIDE, status);
647    verifyFormat("TestFormatMeasuresZeroArg", fmt, NULL, 0, "");
648}
649
650void MeasureFormatTest::TestMultiples() {
651    Locale ru("ru");
652    Locale en("en");
653    helperTestMultiples(en, UMEASFMT_WIDTH_WIDE, "2 miles, 1 foot, 2.3 inches");
654    helperTestMultiples(en, UMEASFMT_WIDTH_SHORT, "2 mi, 1 ft, 2.3 in");
655    helperTestMultiples(en, UMEASFMT_WIDTH_NARROW, "2mi 1\\u2032 2.3\\u2033");
656    helperTestMultiples(ru, UMEASFMT_WIDTH_WIDE, "2 \\u043C\\u0438\\u043B\\u0438, 1 \\u0444\\u0443\\u0442 \\u0438 2,3 \\u0434\\u044E\\u0439\\u043C\\u0430");
657    helperTestMultiples(ru, UMEASFMT_WIDTH_SHORT, "2 \\u043C\\u0438\\u043B\\u0438, 1 \\u0444\\u0443\\u0442, 2,3 \\u0434\\u044E\\u0439\\u043C\\u0430");
658    helperTestMultiples(ru, UMEASFMT_WIDTH_NARROW, "2 \\u043C\\u0438\\u043B\\u044C 1 \\u0444\\u0443\\u0442 2,3 \\u0434\\u044E\\u0439\\u043C\\u0430");
659}
660
661void MeasureFormatTest::helperTestMultiples(
662        const Locale &locale,
663        UMeasureFormatWidth width,
664        const char *expected) {
665    UErrorCode status = U_ZERO_ERROR;
666    FieldPosition pos(0);
667    MeasureFormat fmt(locale, width, status);
668    if (!assertSuccess("Error creating format object", status)) {
669        return;
670    }
671    Measure measures[] = {
672            Measure(2, MeasureUnit::createMile(status), status),
673            Measure(1, MeasureUnit::createFoot(status), status),
674            Measure(2.3, MeasureUnit::createInch(status), status)};
675    if (!assertSuccess("Error creating measures", status)) {
676        return;
677    }
678    UnicodeString buffer;
679    fmt.formatMeasures(measures, LENGTHOF(measures), buffer, pos, status);
680    if (!assertSuccess("Error formatting measures", status)) {
681        return;
682    }
683    assertEquals("TestMultiples", UnicodeString(expected).unescape(), buffer);
684}
685
686void MeasureFormatTest::TestGram() {
687    UErrorCode status = U_ZERO_ERROR;
688    MeasureFormat fmt("en", UMEASFMT_WIDTH_SHORT, status);
689    if (!assertSuccess("Error creating format object", status)) {
690        return;
691    }
692    Measure gram(1, MeasureUnit::createGram(status), status);
693    Measure gforce(1, MeasureUnit::createGForce(status), status);
694    if (!assertSuccess("Error creating measures", status)) {
695        return;
696    }
697    verifyFormat("TestGram", fmt, &gram, 1, "1 g");
698    verifyFormat("TestGram", fmt, &gforce, 1, "1 G");
699}
700
701void MeasureFormatTest::TestCurrencies() {
702    UChar USD[] = {'U', 'S', 'D', 0};
703    UErrorCode status = U_ZERO_ERROR;
704    CurrencyAmount USD_1(1.0, USD, status);
705    CurrencyAmount USD_2(2.0, USD, status);
706    CurrencyAmount USD_NEG_1(-1.0, USD, status);
707    if (!assertSuccess("Error creating measures", status)) {
708        return;
709    }
710    Locale en("en");
711    MeasureFormat fmt(en, UMEASFMT_WIDTH_WIDE, status);
712    if (!assertSuccess("Error creating format object", status)) {
713        return;
714    }
715    verifyFormat("TestCurrenciesWide", fmt, &USD_NEG_1, 1, "-1.00 US dollars");
716    verifyFormat("TestCurrenciesWide", fmt, &USD_1, 1, "1.00 US dollars");
717    verifyFormat("TestCurrenciesWide", fmt, &USD_2, 1, "2.00 US dollars");
718    fmt = MeasureFormat(en, UMEASFMT_WIDTH_SHORT, status);
719    if (!assertSuccess("Error creating format object", status)) {
720        return;
721    }
722    verifyFormat("TestCurrenciesShort", fmt, &USD_NEG_1, 1, "-USD1.00");
723    verifyFormat("TestCurrenciesShort", fmt, &USD_1, 1, "USD1.00");
724    verifyFormat("TestCurrenciesShort", fmt, &USD_2, 1, "USD2.00");
725    fmt = MeasureFormat(en, UMEASFMT_WIDTH_NARROW, status);
726    if (!assertSuccess("Error creating format object", status)) {
727        return;
728    }
729    verifyFormat("TestCurrenciesNarrow", fmt, &USD_NEG_1, 1, "-$1.00");
730    verifyFormat("TestCurrenciesNarrow", fmt, &USD_1, 1, "$1.00");
731    verifyFormat("TestCurrenciesNarrow", fmt, &USD_2, 1, "$2.00");
732    fmt = MeasureFormat(en, UMEASFMT_WIDTH_NUMERIC, status);
733    if (!assertSuccess("Error creating format object", status)) {
734        return;
735    }
736    verifyFormat("TestCurrenciesNumeric", fmt, &USD_NEG_1, 1, "-$1.00");
737    verifyFormat("TestCurrenciesNumeric", fmt, &USD_1, 1, "$1.00");
738    verifyFormat("TestCurrenciesNumeric", fmt, &USD_2, 1, "$2.00");
739}
740
741void MeasureFormatTest::TestFieldPosition() {
742    UErrorCode status = U_ZERO_ERROR;
743    MeasureFormat fmt("en", UMEASFMT_WIDTH_SHORT, status);
744    if (!assertSuccess("Error creating format object", status)) {
745        return;
746    }
747    Measure measure(43.5, MeasureUnit::createFoot(status), status);
748    if (!assertSuccess("Error creating measure object 1", status)) {
749        return;
750    }
751    UnicodeString prefix("123456: ");
752    verifyFieldPosition(
753            "",
754            fmt,
755            prefix,
756            &measure,
757            1,
758            NumberFormat::kDecimalSeparatorField,
759            10,
760            11);
761    measure = Measure(43, MeasureUnit::createFoot(status), status);
762    if (!assertSuccess("Error creating measure object 2", status)) {
763        return;
764    }
765    verifyFieldPosition(
766            "",
767            fmt,
768            prefix,
769            &measure,
770            1,
771            NumberFormat::kDecimalSeparatorField,
772            0,
773            0);
774}
775
776void MeasureFormatTest::TestFieldPositionMultiple() {
777    UErrorCode status = U_ZERO_ERROR;
778    MeasureFormat fmt("en", UMEASFMT_WIDTH_SHORT, status);
779    if (!assertSuccess("Error creating format object", status)) {
780        return;
781    }
782    Measure first[] = {
783            Measure(354, MeasureUnit::createMeter(status), status),
784            Measure(23, MeasureUnit::createCentimeter(status), status)};
785    Measure second[] = {
786            Measure(354, MeasureUnit::createMeter(status), status),
787            Measure(23, MeasureUnit::createCentimeter(status), status),
788            Measure(5.4, MeasureUnit::createMillimeter(status), status)};
789    Measure third[] = {
790            Measure(3, MeasureUnit::createMeter(status), status),
791            Measure(23, MeasureUnit::createCentimeter(status), status),
792            Measure(5, MeasureUnit::createMillimeter(status), status)};
793    if (!assertSuccess("Error creating measure objects", status)) {
794        return;
795    }
796    UnicodeString prefix("123456: ");
797    verifyFieldPosition(
798            "Integer",
799            fmt,
800            prefix,
801            first,
802            LENGTHOF(first),
803            NumberFormat::kIntegerField,
804            8,
805            11);
806    verifyFieldPosition(
807            "Decimal separator",
808            fmt,
809            prefix,
810            second,
811            LENGTHOF(second),
812            NumberFormat::kDecimalSeparatorField,
813            23,
814            24);
815    verifyFieldPosition(
816            "no decimal separator",
817            fmt,
818            prefix,
819            third,
820            LENGTHOF(third),
821            NumberFormat::kDecimalSeparatorField,
822            0,
823            0);
824}
825
826void MeasureFormatTest::TestBadArg() {
827    UErrorCode status = U_ZERO_ERROR;
828    MeasureFormat fmt("en", UMEASFMT_WIDTH_SHORT, status);
829    if (!assertSuccess("Error creating format object", status)) {
830        return;
831    }
832    FieldPosition pos(0);
833    UnicodeString buffer;
834    fmt.format(
835            9.3,
836            buffer,
837            pos,
838            status);
839    if (status != U_ILLEGAL_ARGUMENT_ERROR) {
840        errln("Expected ILLEGAL_ARGUMENT_ERROR");
841    }
842}
843
844void MeasureFormatTest::TestEquality() {
845    UErrorCode status = U_ZERO_ERROR;
846    NumberFormat* nfeq = NumberFormat::createInstance("en", status);
847    NumberFormat* nfne = NumberFormat::createInstance("fr", status);
848    MeasureFormat fmt("en", UMEASFMT_WIDTH_SHORT, status);
849    MeasureFormat fmtEq2("en", UMEASFMT_WIDTH_SHORT, nfeq, status);
850    MeasureFormat fmtne1("en", UMEASFMT_WIDTH_WIDE, status);
851    MeasureFormat fmtne2("fr", UMEASFMT_WIDTH_SHORT, status);
852    MeasureFormat fmtne3("en", UMEASFMT_WIDTH_SHORT, nfne, status);
853    if (U_FAILURE(status)) {
854        dataerrln("Error creating MeasureFormats - %s", u_errorName(status));
855        return;
856    }
857    MeasureFormat fmtEq(fmt);
858    assertTrue("Equal", fmt == fmtEq);
859    assertTrue("Equal2", fmt == fmtEq2);
860    assertFalse("Equal Neg", fmt != fmtEq);
861    assertTrue("Not Equal 1", fmt != fmtne1);
862    assertFalse("Not Equal Neg 1", fmt == fmtne1);
863    assertTrue("Not Equal 2", fmt != fmtne2);
864    assertTrue("Not Equal 3", fmt != fmtne3);
865}
866
867void MeasureFormatTest::TestDoubleZero() {
868    UErrorCode status = U_ZERO_ERROR;
869    Measure measures[] = {
870        Measure(4.7, MeasureUnit::createHour(status), status),
871        Measure(23, MeasureUnit::createMinute(status), status),
872        Measure(16, MeasureUnit::createSecond(status), status)};
873    Locale en("en");
874    NumberFormat *nf = NumberFormat::createInstance(en, status);
875    MeasureFormat fmt("en", UMEASFMT_WIDTH_WIDE, nf, status);
876    UnicodeString appendTo;
877    FieldPosition pos(FieldPosition::DONT_CARE);
878    if (U_FAILURE(status)) {
879        dataerrln("Error creating formatter - %s", u_errorName(status));
880        return;
881    }
882    nf->setMinimumFractionDigits(2);
883    nf->setMaximumFractionDigits(2);
884    fmt.formatMeasures(measures, LENGTHOF(measures), appendTo, pos, status);
885    if (!assertSuccess("Error formatting", status)) {
886        return;
887    }
888    assertEquals(
889            "TestDoubleZero",
890            UnicodeString("4 hours, 23 minutes, 16.00 seconds"),
891            appendTo);
892    measures[0] = Measure(-4.7, MeasureUnit::createHour(status), status);
893    appendTo.remove();
894    fmt.formatMeasures(measures, LENGTHOF(measures), appendTo, pos, status);
895    if (!assertSuccess("Error formatting", status)) {
896        return;
897    }
898    assertEquals(
899            "TestDoubleZero",
900            UnicodeString("-4 hours, 23 minutes, 16.00 seconds"),
901            appendTo);
902}
903
904void MeasureFormatTest::verifyFieldPosition(
905        const char *description,
906        const MeasureFormat &fmt,
907        const UnicodeString &prefix,
908        const Measure *measures,
909        int32_t measureCount,
910        NumberFormat::EAlignmentFields field,
911        int32_t start,
912        int32_t end) {
913    // 8 char lead
914    UnicodeString result(prefix);
915    FieldPosition pos(field);
916    UErrorCode status = U_ZERO_ERROR;
917    CharString ch;
918    const char *descPrefix = ch.append(description, status)
919            .append(": ", status).data();
920    CharString beginIndex;
921    beginIndex.append(descPrefix, status).append("beginIndex", status);
922    CharString endIndex;
923    endIndex.append(descPrefix, status).append("endIndex", status);
924    fmt.formatMeasures(measures, measureCount, result, pos, status);
925    if (!assertSuccess("Error formatting", status)) {
926        return;
927    }
928    assertEquals(beginIndex.data(), start, pos.getBeginIndex());
929    assertEquals(endIndex.data(), end, pos.getEndIndex());
930}
931
932void MeasureFormatTest::verifyFormat(
933        const char *description,
934        const MeasureFormat &fmt,
935        const Measure *measures,
936        int32_t measureCount,
937        const char *expected) {
938    verifyFormatWithPrefix(
939            description,
940            fmt,
941            "",
942            measures,
943            measureCount,
944            expected);
945}
946
947void MeasureFormatTest::verifyFormatWithPrefix(
948        const char *description,
949        const MeasureFormat &fmt,
950        const UnicodeString &prefix,
951        const Measure *measures,
952        int32_t measureCount,
953        const char *expected) {
954    UnicodeString result(prefix);
955    FieldPosition pos(0);
956    UErrorCode status = U_ZERO_ERROR;
957    fmt.formatMeasures(measures, measureCount, result, pos, status);
958    if (!assertSuccess("Error formatting", status)) {
959        return;
960    }
961    assertEquals(description, UnicodeString(expected).unescape(), result);
962}
963
964void MeasureFormatTest::verifyFormat(
965        const char *description,
966        const MeasureFormat &fmt,
967        const ExpectedResult *expectedResults,
968        int32_t count) {
969    for (int32_t i = 0; i < count; ++i) {
970        verifyFormat(description, fmt, expectedResults[i].measures, expectedResults[i].count, expectedResults[i].expected);
971    }
972}
973
974extern IntlTest *createMeasureFormatTest() {
975    return new MeasureFormatTest();
976}
977
978#endif
979
980