1// © 2016 and later: Unicode, Inc. and others.
2// License & terms of use: http://www.unicode.org/copyright.html
3/********************************************************************
4 * COPYRIGHT:
5 * Copyright (c) 1997-2016, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 ********************************************************************
8 * File TMSGFMT.CPP
9 *
10 * Modification History:
11 *
12 *   Date        Name        Description
13 *   03/24/97    helena      Converted from Java.
14 *   07/11/97    helena      Updated to work on AIX.
15 *   08/04/97    jfitz       Updated to intltest
16 *******************************************************************/
17
18#include "unicode/utypes.h"
19
20#if !UCONFIG_NO_FORMATTING
21
22#include "tmsgfmt.h"
23#include "cmemory.h"
24
25#include "unicode/format.h"
26#include "unicode/decimfmt.h"
27#include "unicode/localpointer.h"
28#include "unicode/locid.h"
29#include "unicode/msgfmt.h"
30#include "unicode/numfmt.h"
31#include "unicode/choicfmt.h"
32#include "unicode/messagepattern.h"
33#include "unicode/selfmt.h"
34#include "unicode/gregocal.h"
35#include "unicode/strenum.h"
36#include <stdio.h>
37
38void
39TestMessageFormat::runIndexedTest(int32_t index, UBool exec,
40                                  const char* &name, char* /*par*/) {
41    TESTCASE_AUTO_BEGIN;
42    TESTCASE_AUTO(testBug1);
43    TESTCASE_AUTO(testBug2);
44    TESTCASE_AUTO(sample);
45    TESTCASE_AUTO(PatternTest);
46    TESTCASE_AUTO(testStaticFormat);
47    TESTCASE_AUTO(testSimpleFormat);
48    TESTCASE_AUTO(testMsgFormatChoice);
49    TESTCASE_AUTO(testCopyConstructor);
50    TESTCASE_AUTO(testAssignment);
51    TESTCASE_AUTO(testClone);
52    TESTCASE_AUTO(testEquals);
53    TESTCASE_AUTO(testNotEquals);
54    TESTCASE_AUTO(testSetLocale);
55    TESTCASE_AUTO(testFormat);
56    TESTCASE_AUTO(testParse);
57    TESTCASE_AUTO(testAdopt);
58    TESTCASE_AUTO(testCopyConstructor2);
59    TESTCASE_AUTO(TestUnlimitedArgsAndSubformats);
60    TESTCASE_AUTO(TestRBNF);
61    TESTCASE_AUTO(TestTurkishCasing);
62    TESTCASE_AUTO(testAutoQuoteApostrophe);
63    TESTCASE_AUTO(testMsgFormatPlural);
64    TESTCASE_AUTO(testMsgFormatSelect);
65    TESTCASE_AUTO(testApostropheInPluralAndSelect);
66    TESTCASE_AUTO(TestApostropheMode);
67    TESTCASE_AUTO(TestCompatibleApostrophe);
68    TESTCASE_AUTO(testCoverage);
69    TESTCASE_AUTO(testGetFormatNames);
70    TESTCASE_AUTO(TestTrimArgumentName);
71    TESTCASE_AUTO(TestSelectOrdinal);
72    TESTCASE_AUTO(TestDecimals);
73    TESTCASE_AUTO(TestArgIsPrefixOfAnother);
74    TESTCASE_AUTO_END;
75}
76
77void TestMessageFormat::testBug3()
78{
79    double myNumber = -123456;
80    DecimalFormat *form = 0;
81    Locale locale[] = {
82        Locale("ar", "", ""),
83        Locale("be", "", ""),
84        Locale("bg", "", ""),
85        Locale("ca", "", ""),
86        Locale("cs", "", ""),
87        Locale("da", "", ""),
88        Locale("de", "", ""),
89        Locale("de", "AT", ""),
90        Locale("de", "CH", ""),
91        Locale("el", "", ""),       // 10
92        Locale("en", "CA", ""),
93        Locale("en", "GB", ""),
94        Locale("en", "IE", ""),
95        Locale("en", "US", ""),
96        Locale("es", "", ""),
97        Locale("et", "", ""),
98        Locale("fi", "", ""),
99        Locale("fr", "", ""),
100        Locale("fr", "BE", ""),
101        Locale("fr", "CA", ""),     // 20
102        Locale("fr", "CH", ""),
103        Locale("he", "", ""),
104        Locale("hr", "", ""),
105        Locale("hu", "", ""),
106        Locale("is", "", ""),
107        Locale("it", "", ""),
108        Locale("it", "CH", ""),
109        Locale("ja", "", ""),
110        Locale("ko", "", ""),
111        Locale("lt", "", ""),       // 30
112        Locale("lv", "", ""),
113        Locale("mk", "", ""),
114        Locale("nl", "", ""),
115        Locale("nl", "BE", ""),
116        Locale("no", "", ""),
117        Locale("pl", "", ""),
118        Locale("pt", "", ""),
119        Locale("ro", "", ""),
120        Locale("ru", "", ""),
121        Locale("sh", "", ""),       // 40
122        Locale("sk", "", ""),
123        Locale("sl", "", ""),
124        Locale("sq", "", ""),
125        Locale("sr", "", ""),
126        Locale("sv", "", ""),
127        Locale("tr", "", ""),
128        Locale("uk", "", ""),
129        Locale("zh", "", ""),
130        Locale("zh", "TW", "")      // 49
131    };
132    int32_t i;
133    for (i= 0; i < 49; i++) {
134        UnicodeString buffer;
135        logln(locale[i].getDisplayName(buffer));
136        UErrorCode success = U_ZERO_ERROR;
137//        form = (DecimalFormat*)NumberFormat::createCurrencyInstance(locale[i], success);
138        form = (DecimalFormat*)NumberFormat::createInstance(locale[i], success);
139        if (U_FAILURE(success)) {
140            errln("Err: Number Format ");
141            logln("Number format creation failed.");
142            continue;
143        }
144        Formattable result;
145        FieldPosition pos(FieldPosition::DONT_CARE);
146        buffer.remove();
147        form->format(myNumber, buffer, pos);
148        success = U_ZERO_ERROR;
149        ParsePosition parsePos;
150        form->parse(buffer, result, parsePos);
151        logln(UnicodeString(" -> ") /* + << dec*/ + toString(result) + UnicodeString("[supposed output for result]"));
152        if (U_FAILURE(success)) {
153            errln("Err: Number Format parse");
154            logln("Number format parse failed.");
155        }
156        delete form;
157    }
158}
159
160void TestMessageFormat::testBug1()
161{
162    const double limit[] = {0.0, 1.0, 2.0};
163    const UnicodeString formats[] = {"0.0<=Arg<1.0",
164                               "1.0<=Arg<2.0",
165                               "2.0<-Arg"};
166    ChoiceFormat *cf = new ChoiceFormat(limit, formats, 3);
167    FieldPosition status(FieldPosition::DONT_CARE);
168    UnicodeString toAppendTo;
169    cf->format((int32_t)1, toAppendTo, status);
170    if (toAppendTo != "1.0<=Arg<2.0") {
171        errln("ChoiceFormat cmp in testBug1");
172    }
173    logln(toAppendTo);
174    delete cf;
175}
176
177void TestMessageFormat::testBug2()
178{
179    UErrorCode status = U_ZERO_ERROR;
180    UnicodeString result;
181    // {sfb} use double format in pattern, so result will match (not strictly necessary)
182    const UnicodeString pattern = "There {0,choice,0#are no files|1#is one file|1<are {0, number} files} on disk {1}. ";
183    logln("The input pattern : " + pattern);
184    MessageFormat *fmt = new MessageFormat(pattern, status);
185    if (U_FAILURE(status)) {
186        dataerrln("MessageFormat pattern creation failed. - %s", u_errorName(status));
187        return;
188    }
189    logln("The output pattern is : " + fmt->toPattern(result));
190    if (pattern != result) {
191        errln("MessageFormat::toPattern() failed.");
192    }
193    delete fmt;
194}
195
196#if 0
197#if defined(_DEBUG)
198//----------------------------------------------------
199// console I/O
200//----------------------------------------------------
201
202#include <iostream>
203std::ostream& operator<<(std::ostream& stream,  const Formattable&   obj);
204
205#include "unicode/datefmt.h"
206#include <stdlib.h>
207#include <string.h>
208
209IntlTest&
210operator<<( IntlTest&           stream,
211            const Formattable&  obj)
212{
213    static DateFormat *defDateFormat = 0;
214
215    UnicodeString buffer;
216    switch(obj.getType()) {
217        case Formattable::kDate :
218            if (defDateFormat == 0) {
219                defDateFormat = DateFormat::createInstance();
220            }
221            defDateFormat->format(obj.getDate(), buffer);
222            stream << buffer;
223            break;
224        case Formattable::kDouble :
225            char convert[20];
226            sprintf( convert, "%lf", obj.getDouble() );
227            stream << convert << "D";
228            break;
229        case Formattable::kLong :
230            stream << obj.getLong() << "L";
231            break;
232        case Formattable::kString:
233            stream << "\"" << obj.getString(buffer) << "\"";
234            break;
235        case Formattable::kArray:
236            int32_t i, count;
237            const Formattable* array;
238            array = obj.getArray(count);
239            stream << "[";
240            for (i=0; i<count; ++i) stream << array[i] << ( (i==(count-1)) ? "" : ", " );
241            stream << "]";
242            break;
243        default:
244            stream << "INVALID_Formattable";
245    }
246    return stream;
247}
248#endif /* defined(_DEBUG) */
249#endif
250
251void TestMessageFormat::PatternTest()
252{
253    Formattable testArgs[] = {
254        Formattable(double(1)), Formattable(double(3456)),
255            Formattable("Disk"), Formattable(UDate((int32_t)1000000000L), Formattable::kIsDate)
256    };
257    UnicodeString testCases[] = {
258       "Quotes '', '{', 'a' {0} '{0}'",
259       "Quotes '', '{', 'a' {0,number} '{0}'",
260       "'{'1,number,'#',##} {1,number,'#',##}",
261       "There are {1} files on {2} at {3}.",
262       "On {2}, there are {1} files, with {0,number,currency}.",
263       "'{1,number,percent}', {1,number,percent},",
264       "'{1,date,full}', {1,date,full},",
265       "'{3,date,full}', {3,date,full},",
266       "'{1,number,#,##}' {1,number,#,##}",
267    };
268
269    // ICU 4.8 returns the original pattern (testCases),
270    // rather than toPattern() reconstituting a new, equivalent pattern string (testResultPatterns).
271    /*UnicodeString testResultPatterns[] = {
272        "Quotes '', '{', a {0} '{'0}",
273        "Quotes '', '{', a {0,number} '{'0}",
274        "'{'1,number,#,##} {1,number,'#'#,##}",
275        "There are {1} files on {2} at {3}.",
276        "On {2}, there are {1} files, with {0,number,currency}.",
277        "'{'1,number,percent}, {1,number,percent},",
278        "'{'1,date,full}, {1,date,full},",
279        "'{'3,date,full}, {3,date,full},",
280        "'{'1,number,#,##} {1,number,#,##}"
281    };*/
282
283    UnicodeString testResultStrings[] = {
284        "Quotes ', {, 'a' 1 {0}",
285        "Quotes ', {, 'a' 1 {0}",
286        "{1,number,'#',##} #34,56",
287        "There are 3,456 files on Disk at 1/12/70, 5:46 AM.",
288        "On Disk, there are 3,456 files, with $1.00.",
289        "{1,number,percent}, 345,600%,",
290        "{1,date,full}, Wednesday, December 31, 1969,",
291        "{3,date,full}, Monday, January 12, 1970,",
292        "{1,number,#,##} 34,56"
293    };
294
295
296    for (int32_t i = 0; i < 9; ++i) {
297        //it_out << "\nPat in:  " << testCases[i]);
298
299        MessageFormat *form = 0;
300        UErrorCode success = U_ZERO_ERROR;
301        UnicodeString buffer;
302        form = new MessageFormat(testCases[i], Locale::getUS(), success);
303        if (U_FAILURE(success)) {
304            dataerrln("MessageFormat creation failed.#1 - %s", u_errorName(success));
305            logln(((UnicodeString)"MessageFormat for ") + testCases[i] + " creation failed.\n");
306            continue;
307        }
308        // ICU 4.8 returns the original pattern (testCases),
309        // rather than toPattern() reconstituting a new, equivalent pattern string (testResultPatterns).
310        if (form->toPattern(buffer) != testCases[i]) {
311            // Note: An alternative test would be to build MessagePattern objects for
312            // both the input and output patterns and compare them, taking SKIP_SYNTAX etc.
313            // into account.
314            // (Too much trouble...)
315            errln(UnicodeString("TestMessageFormat::PatternTest failed test #2, i = ") + i);
316            //form->toPattern(buffer);
317            errln(((UnicodeString)" Orig: ") + testCases[i]);
318            errln(((UnicodeString)" Exp:  ") + testCases[i]);
319            errln(((UnicodeString)" Got:  ") + buffer);
320        }
321
322        //it_out << "Pat out: " << form->toPattern(buffer));
323        UnicodeString result;
324        int32_t count = 4;
325        FieldPosition fieldpos(FieldPosition::DONT_CARE);
326        form->format(testArgs, count, result, fieldpos, success);
327        if (U_FAILURE(success)) {
328            dataerrln("MessageFormat failed test #3 - %s", u_errorName(success));
329            logln("TestMessageFormat::PatternTest failed test #3");
330            continue;
331        }
332        if (result != testResultStrings[i]) {
333            errln("TestMessageFormat::PatternTest failed test #4");
334            logln("TestMessageFormat::PatternTest failed #4.");
335            logln(UnicodeString("    Result: ") + result );
336            logln(UnicodeString("  Expected: ") + testResultStrings[i] );
337        }
338
339
340        //it_out << "Result:  " << result);
341#if 0
342        /* TODO: Look at this test and see if this is still a valid test */
343        logln("---------------- test parse ----------------");
344
345        form->toPattern(buffer);
346        logln("MSG pattern for parse: " + buffer);
347
348        int32_t parseCount = 0;
349        Formattable* values = form->parse(result, parseCount, success);
350        if (U_FAILURE(success)) {
351            errln("MessageFormat failed test #5");
352            logln(UnicodeString("MessageFormat failed test #5 with error code ")+(int32_t)success);
353        } else if (parseCount != count) {
354            errln("MSG count not %d as expected. Got %d", count, parseCount);
355        }
356        UBool failed = FALSE;
357        for (int32_t j = 0; j < parseCount; ++j) {
358             if (values == 0 || testArgs[j] != values[j]) {
359                errln(((UnicodeString)"MSG testargs[") + j + "]: " + toString(testArgs[j]));
360                errln(((UnicodeString)"MSG values[") + j + "]  : " + toString(values[j]));
361                failed = TRUE;
362             }
363        }
364        if (failed)
365            errln("MessageFormat failed test #6");
366#endif
367        delete form;
368    }
369}
370
371void TestMessageFormat::sample()
372{
373    MessageFormat *form = 0;
374    UnicodeString buffer1, buffer2;
375    UErrorCode success = U_ZERO_ERROR;
376    form = new MessageFormat("There are {0} files on {1}", success);
377    if (U_FAILURE(success)) {
378        errln("Err: Message format creation failed");
379        logln("Sample message format creation failed.");
380        return;
381    }
382    UnicodeString abc("abc");
383    UnicodeString def("def");
384    Formattable testArgs1[] = { abc, def };
385    FieldPosition fieldpos(FieldPosition::DONT_CARE);
386    assertEquals("format",
387                 "There are abc files on def",
388                 form->format(testArgs1, 2, buffer2, fieldpos, success));
389    assertSuccess("format", success);
390    delete form;
391}
392
393void TestMessageFormat::testStaticFormat()
394{
395    UErrorCode err = U_ZERO_ERROR;
396    Formattable arguments[] = {
397        (int32_t)7,
398        Formattable(UDate(8.71068e+011), Formattable::kIsDate),
399        "a disturbance in the Force"
400        };
401
402    UnicodeString result;
403    result = MessageFormat::format(
404        "At {1,time} on {1,date}, there was {2} on planet {0,number,integer}.",
405        arguments,
406        3,
407        result,
408        err);
409
410    if (U_FAILURE(err)) {
411        dataerrln("TestMessageFormat::testStaticFormat #1 - %s", u_errorName(err));
412        logln(UnicodeString("TestMessageFormat::testStaticFormat failed test #1 with error code ")+(int32_t)err);
413        return;
414    }
415
416    const UnicodeString expected(
417            "At 12:20:00 PM on Aug 8, 1997, there was a disturbance in the Force on planet 7.", "");
418    if (result != expected) {
419        errln("TestMessageFormat::testStaticFormat failed on test");
420        logln( UnicodeString("     Result: ") + result );
421        logln( UnicodeString("   Expected: ") + expected );
422    }
423}
424
425/* When the default locale is tr, make sure that the pattern can still be parsed. */
426void TestMessageFormat::TestTurkishCasing()
427{
428    UErrorCode err = U_ZERO_ERROR;
429    Locale  saveDefaultLocale;
430    Locale::setDefault( Locale("tr"), err );
431
432    Formattable arguments[] = {
433        (int32_t)7,
434        Formattable(UDate(8.71068e+011), Formattable::kIsDate),
435        "a disturbance in the Force"
436        };
437
438    UnicodeString result;
439    result = MessageFormat::format(
440        "At {1,TIME} on {1,DATE,SHORT}, there was {2} on planet {0,NUMBER,INTEGER}.",
441        arguments,
442        3,
443        result,
444        err);
445
446    if (U_FAILURE(err)) {
447        dataerrln("TestTurkishCasing #1 with error code %s", u_errorName(err));
448        return;
449    }
450
451    const UnicodeString expected(
452            "At 12:20:00 on 8.08.1997, there was a disturbance in the Force on planet 7.", "");
453    if (result != expected) {
454        errln("TestTurkishCasing failed on test");
455        errln( UnicodeString("     Result: ") + result );
456        errln( UnicodeString("   Expected: ") + expected );
457    }
458    Locale::setDefault( saveDefaultLocale, err );
459}
460
461void TestMessageFormat::testSimpleFormat(/* char* par */)
462{
463    logln("running TestMessageFormat::testSimpleFormat");
464
465    UErrorCode err = U_ZERO_ERROR;
466
467    Formattable testArgs1[] = {(int32_t)0, "MyDisk"};
468    Formattable testArgs2[] = {(int32_t)1, "MyDisk"};
469    Formattable testArgs3[] = {(int32_t)12, "MyDisk"};
470
471    MessageFormat* form = new MessageFormat(
472        "The disk \"{1}\" contains {0} file(s).", err);
473
474    UnicodeString string;
475    FieldPosition ignore(FieldPosition::DONT_CARE);
476    form->format(testArgs1, 2, string, ignore, err);
477    if (U_FAILURE(err) || string != "The disk \"MyDisk\" contains 0 file(s).") {
478        dataerrln(UnicodeString("TestMessageFormat::testSimpleFormat failed on test #1 - ") + u_errorName(err));
479    }
480
481    ignore.setField(FieldPosition::DONT_CARE);
482    string.remove();
483    form->format(testArgs2, 2, string, ignore, err);
484    if (U_FAILURE(err) || string != "The disk \"MyDisk\" contains 1 file(s).") {
485        logln(string);
486        dataerrln(UnicodeString("TestMessageFormat::testSimpleFormat failed on test #2")+string + " - " + u_errorName(err));
487    }
488
489    ignore.setField(FieldPosition::DONT_CARE);
490    string.remove();
491    form->format(testArgs3, 2, string, ignore, err);
492    if (U_FAILURE(err) || string != "The disk \"MyDisk\" contains 12 file(s).") {
493        dataerrln(UnicodeString("TestMessageFormat::testSimpleFormat failed on test #3")+string + " - " + u_errorName(err));
494    }
495
496    delete form;
497 }
498
499void TestMessageFormat::testMsgFormatChoice(/* char* par */)
500{
501    logln("running TestMessageFormat::testMsgFormatChoice");
502
503    UErrorCode err = U_ZERO_ERROR;
504
505    MessageFormat* form = new MessageFormat("The disk \"{1}\" contains {0}.", err);
506    double filelimits[] = {0,1,2};
507    UnicodeString filepart[] = {"no files","one file","{0,number} files"};
508    ChoiceFormat* fileform = new ChoiceFormat(filelimits, filepart, 3);
509    form->setFormat(1,*fileform); // NOT zero, see below
510        //is the format adopted?
511
512    FieldPosition ignore(FieldPosition::DONT_CARE);
513    UnicodeString string;
514    Formattable testArgs1[] = {(int32_t)0, "MyDisk"};
515    form->format(testArgs1, 2, string, ignore, err);
516    if (string != "The disk \"MyDisk\" contains no files.") {
517        errln("TestMessageFormat::testMsgFormatChoice failed on test #1");
518    }
519
520    ignore.setField(FieldPosition::DONT_CARE);
521    string.remove();
522    Formattable testArgs2[] = {(int32_t)1, "MyDisk"};
523    form->format(testArgs2, 2, string, ignore, err);
524    if (string != "The disk \"MyDisk\" contains one file.") {
525        errln("TestMessageFormat::testMsgFormatChoice failed on test #2");
526    }
527
528    ignore.setField(FieldPosition::DONT_CARE);
529    string.remove();
530    Formattable testArgs3[] = {(int32_t)1273, "MyDisk"};
531    form->format(testArgs3, 2, string, ignore, err);
532    if (string != "The disk \"MyDisk\" contains 1,273 files.") {
533        dataerrln("TestMessageFormat::testMsgFormatChoice failed on test #3 - %s", u_errorName(err));
534    }
535
536    delete form;
537    delete fileform;
538}
539
540
541void TestMessageFormat::testMsgFormatPlural(/* char* par */)
542{
543    logln("running TestMessageFormat::testMsgFormatPlural");
544
545    UErrorCode err = U_ZERO_ERROR;
546    UnicodeString t1("{0, plural, one{C''est # fichier} other{Ce sont # fichiers}} dans la liste.");
547    UnicodeString t2("{argument, plural, one{C''est # fichier} other {Ce sont # fichiers}} dans la liste.");
548    UnicodeString t3("There {0, plural, one{is # zavod}few{are {0, number,###.0} zavoda} other{are # zavodov}} in the directory.");
549    UnicodeString t4("There {argument, plural, one{is # zavod}few{are {argument, number,###.0} zavoda} other{are #zavodov}} in the directory.");
550    UnicodeString t5("{0, plural, one {{0, number,C''est #,##0.0# fichier}} other {Ce sont # fichiers}} dans la liste.");
551    MessageFormat* mfNum = new MessageFormat(t1, Locale("fr"), err);
552    if (U_FAILURE(err)) {
553        dataerrln("TestMessageFormat::testMsgFormatPlural #1 - argumentIndex - %s", u_errorName(err));
554        logln(UnicodeString("TestMessageFormat::testMsgFormatPlural #1 with error code ")+(int32_t)err);
555        return;
556    }
557    Formattable testArgs1((int32_t)0);
558    FieldPosition ignore(FieldPosition::DONT_CARE);
559    UnicodeString numResult1;
560    mfNum->format(&testArgs1, 1, numResult1, ignore, err);
561
562    MessageFormat* mfAlpha = new MessageFormat(t2, Locale("fr"), err);
563    UnicodeString argName[] = {UnicodeString("argument")};
564    UnicodeString argNameResult;
565    mfAlpha->format(argName, &testArgs1, 1, argNameResult, err);
566    if (U_FAILURE(err)) {
567        dataerrln("TestMessageFormat::testMsgFormatPlural #1 - argumentName - %s", u_errorName(err));
568        logln(UnicodeString("TestMessageFormat::testMsgFormatPlural #1 with error code ")+(int32_t)err);
569        delete mfNum;
570        return;
571    }
572    if ( numResult1 != argNameResult){
573        errln("TestMessageFormat::testMsgFormatPlural #1");
574        logln(UnicodeString("The results of argumentName and argumentIndex are not the same."));
575    }
576    if ( numResult1 != UnicodeString("C\'est 0 fichier dans la liste.")) {
577        errln("TestMessageFormat::testMsgFormatPlural #1");
578        logln(UnicodeString("The results of argumentName and argumentIndex are not the same."));
579    }
580    err = U_ZERO_ERROR;
581
582    delete mfNum;
583    delete mfAlpha;
584
585    MessageFormat* mfNum2 = new MessageFormat(t3, Locale("uk"), err);
586    numResult1.remove();
587    Formattable testArgs2((int32_t)4);
588    mfNum2->format(&testArgs2, 1, numResult1, ignore, err);
589    MessageFormat* mfAlpha2 = new MessageFormat(t4, Locale("uk"), err);
590    argNameResult.remove();
591    mfAlpha2->format(argName, &testArgs2, 1, argNameResult, err);
592
593    if (U_FAILURE(err)) {
594        errln("TestMessageFormat::testMsgFormatPlural #2 - argumentName");
595        logln(UnicodeString("TestMessageFormat::testMsgFormatPlural #2 with error code ")+(int32_t)err);
596        delete mfNum2;
597        return;
598    }
599    if ( numResult1 != argNameResult){
600        errln("TestMessageFormat::testMsgFormatPlural #2");
601        logln(UnicodeString("The results of argumentName and argumentIndex are not the same."));
602    }
603    if ( numResult1 != UnicodeString("There are 4,0 zavoda in the directory.")) {
604        errln("TestMessageFormat::testMsgFormatPlural #2");
605        logln(UnicodeString("The results of argumentName and argumentIndex are not the same."));
606    }
607
608    delete mfNum2;
609    delete mfAlpha2;
610
611    // nested formats
612    err = U_ZERO_ERROR;
613    MessageFormat* msgFmt = new MessageFormat(t5, Locale("fr"), err);
614    if (U_FAILURE(err)) {
615        errln("TestMessageFormat::test nested PluralFormat with argumentName");
616        logln(UnicodeString("TestMessageFormat::test nested PluralFormat with error code ")+(int32_t)err);
617        delete msgFmt;
618        return;
619    }
620    Formattable testArgs3((int32_t)0);
621    argNameResult.remove();
622    msgFmt->format(&testArgs3, 1, argNameResult, ignore, err);
623    if (U_FAILURE(err)) {
624        errln("TestMessageFormat::test nested PluralFormat with argumentName");
625    }
626    if ( argNameResult!= UnicodeString("C'est 0,0 fichier dans la liste.")) {
627        errln(UnicodeString("TestMessageFormat::test nested named PluralFormat: ") + argNameResult);
628        logln(UnicodeString("The unexpected nested named PluralFormat."));
629    }
630    delete msgFmt;
631}
632
633void TestMessageFormat::testApostropheInPluralAndSelect() {
634    UErrorCode errorCode = U_ZERO_ERROR;
635    MessageFormat msgFmt(UNICODE_STRING_SIMPLE(
636        "abc_{0,plural,other{#'#'#'{'#''}}_def_{1,select,other{sel'}'ect''}}_xyz"),
637        Locale::getEnglish(),
638        errorCode);
639    if (U_FAILURE(errorCode)) {
640        errln("MessageFormat constructor failed - %s\n", u_errorName(errorCode));
641        return;
642    }
643    UnicodeString expected = UNICODE_STRING_SIMPLE("abc_3#3{3'_def_sel}ect'_xyz");
644    Formattable args[] = { (int32_t)3, UNICODE_STRING_SIMPLE("x") };
645    internalFormat(
646        &msgFmt, args, 2, expected,
647        "MessageFormat with apostrophes in plural/select arguments failed:\n");
648}
649
650void TestMessageFormat::internalFormat(MessageFormat* msgFmt ,
651        Formattable* args , int32_t numOfArgs ,
652        UnicodeString expected, const char* errMsg)
653{
654        UnicodeString result;
655        FieldPosition ignore(FieldPosition::DONT_CARE);
656        UErrorCode status = U_ZERO_ERROR;
657
658        //Format with passed arguments
659        msgFmt->format( args , numOfArgs , result, ignore, status);
660        if (U_FAILURE(status)) {
661            dataerrln( "%s error while formatting with ErrorCode as %s" ,errMsg, u_errorName(status) );
662        }
663        //Compare expected with obtained result
664        if ( result!= expected ) {
665            UnicodeString err = UnicodeString(errMsg);
666            err+= UnicodeString(":Unexpected Result \n Expected: " + expected + "\n Obtained: " + result + "\n");
667            dataerrln(err);
668        }
669}
670
671MessageFormat* TestMessageFormat::internalCreate(
672        UnicodeString pattern ,Locale locale ,UErrorCode &status ,  char* errMsg)
673{
674    //Create the MessageFormat with simple SelectFormat
675    MessageFormat* msgFmt = new MessageFormat(pattern, locale, status);
676    if (U_FAILURE(status)) {
677        dataerrln( "%s error while constructing with ErrorCode as %s" ,errMsg, u_errorName(status) );
678        logln(UnicodeString("TestMessageFormat::testMsgFormatSelect #1 with error code ")+(int32_t)status);
679        return NULL;
680    }
681    return msgFmt;
682}
683
684void TestMessageFormat::testMsgFormatSelect(/* char* par */)
685{
686    logln("running TestMessageFormat::testMsgFormatSelect");
687
688    UErrorCode err = U_ZERO_ERROR;
689    //French Pattern
690    UnicodeString t1("{0} est {1, select, female {all\\u00E9e} other {all\\u00E9}} \\u00E0 Paris.");
691
692    err = U_ZERO_ERROR;
693    //Create the MessageFormat with simple French pattern
694    MessageFormat* msgFmt1 = internalCreate(t1.unescape(), Locale("fr"),err,(char*)"From TestMessageFormat::TestSelectFormat create t1");
695    if (!U_FAILURE(err)) {
696        //Arguments
697        Formattable testArgs10[] = {"Kirti","female"};
698        Formattable testArgs11[] = {"Victor","other"};
699        Formattable testArgs12[] = {"Ash","unknown"};
700        Formattable* testArgs[] = {testArgs10,testArgs11,testArgs12};
701        UnicodeString exp[] = {
702            "Kirti est all\\u00E9e \\u00E0 Paris." ,
703            "Victor est all\\u00E9 \\u00E0 Paris.",
704            "Ash est all\\u00E9 \\u00E0 Paris."};
705        //Format
706        for( int i=0; i< 3; i++){
707            internalFormat( msgFmt1 , testArgs[i], 2, exp[i].unescape() ,(char*)"From TestMessageFormat::testSelectFormat format t1");
708        }
709    }
710    delete msgFmt1;
711
712    //Quoted French Pattern
713    UnicodeString t2("{0} est {1, select, female {all\\u00E9e c''est} other {all\\u00E9 c''est}} \\u00E0 Paris.");
714    err = U_ZERO_ERROR;
715    //Create the MessageFormat with Quoted French pattern
716    MessageFormat* msgFmt2 = internalCreate(t2.unescape(), Locale("fr"),err,(char*)"From TestMessageFormat::TestSelectFormat create t2");
717    if (!U_FAILURE(err)) {
718        //Arguments
719        Formattable testArgs10[] = {"Kirti","female"};
720        Formattable testArgs11[] = {"Victor","other"};
721        Formattable testArgs12[] = {"Ash","male"};
722        Formattable* testArgs[] = {testArgs10,testArgs11,testArgs12};
723        UnicodeString exp[] = {
724            "Kirti est all\\u00E9e c'est \\u00E0 Paris." ,
725            "Victor est all\\u00E9 c'est \\u00E0 Paris.",
726            "Ash est all\\u00E9 c'est \\u00E0 Paris."};
727        //Format
728        for( int i=0; i< 3; i++){
729            internalFormat( msgFmt2 , testArgs[i], 2, exp[i].unescape() ,(char*)"From TestMessageFormat::testSelectFormat format t2");
730        }
731    }
732    delete msgFmt2;
733
734    //English Pattern
735    UnicodeString t3("{0, select , male {MALE FR company} female {FEMALE FR company} other {FR otherValue}} published new books.");
736    err = U_ZERO_ERROR;
737    //Create the MessageFormat with English pattern
738    MessageFormat* msgFmt3 = internalCreate(t3, Locale("en"),err,(char*)"From TestMessageFormat::TestSelectFormat create t3");
739    if (!U_FAILURE(err)) {
740        //Arguments
741        Formattable testArgs10[] = {"female"};
742        Formattable testArgs11[] = {"other"};
743        Formattable testArgs12[] = {"male"};
744        Formattable* testArgs[] = {testArgs10,testArgs11,testArgs12};
745        UnicodeString exp[] = {
746            "FEMALE FR company published new books." ,
747            "FR otherValue published new books.",
748            "MALE FR company published new books."};
749        //Format
750        for( int i=0; i< 3; i++){
751            internalFormat( msgFmt3 , testArgs[i], 1, exp[i] ,(char*)"From TestMessageFormat::testSelectFormat format t3");
752        }
753    }
754    delete msgFmt3;
755
756    //Nested patterns with plural, number ,choice ,select format etc.
757    //Select Format with embedded number format
758    UnicodeString t4("{0} est {1, select, female {{2,number,integer} all\\u00E9e} other {all\\u00E9}} \\u00E0 Paris.");
759    err = U_ZERO_ERROR;
760    //Create the MessageFormat with Select Format with embedded number format (nested pattern)
761    MessageFormat* msgFmt4 = internalCreate(t4.unescape(), Locale("fr"),err,(char*)"From TestMessageFormat::TestSelectFormat create t4");
762    if (!U_FAILURE(err)) {
763        //Arguments
764        Formattable testArgs10[] = {"Kirti","female",(int32_t)6};
765        Formattable testArgs11[] = {"Kirti","female",100.100};
766        Formattable testArgs12[] = {"Kirti","other",(int32_t)6};
767        Formattable* testArgs[] = {testArgs10,testArgs11,testArgs12};
768        UnicodeString exp[] = {
769            "Kirti est 6 all\\u00E9e \\u00E0 Paris." ,
770            "Kirti est 100 all\\u00E9e \\u00E0 Paris.",
771            "Kirti est all\\u00E9 \\u00E0 Paris."};
772        //Format
773        for( int i=0; i< 3; i++){
774            internalFormat( msgFmt4 , testArgs[i], 3, exp[i].unescape() ,(char*)"From TestMessageFormat::testSelectFormat format t4");
775        }
776    }
777    delete msgFmt4;
778
779    //Plural format with embedded select format
780    UnicodeString t5("{0} {1, plural, one {est {2, select, female {all\\u00E9e} other {all\\u00E9}}} other {sont {2, select, female {all\\u00E9es} other {all\\u00E9s}}}} \\u00E0 Paris.");
781    err = U_ZERO_ERROR;
782    //Create the MessageFormat with Plural format with embedded select format(nested pattern)
783    MessageFormat* msgFmt5 = internalCreate(t5.unescape(), Locale("fr"),err,(char*)"From TestMessageFormat::TestSelectFormat create t5");
784    // with no data the above should fail but it seems to construct an invalid MessageFormat with no reported error. See #13079
785    if (!U_FAILURE(err)) {
786        //Arguments
787        Formattable testArgs10[] = {"Kirti",(int32_t)6,"female"};
788        Formattable testArgs11[] = {"Kirti",(int32_t)1,"female"};
789        Formattable testArgs12[] = {"Ash",(int32_t)1,"other"};
790        Formattable testArgs13[] = {"Ash",(int32_t)5,"other"};
791        Formattable* testArgs[] = {testArgs10,testArgs11,testArgs12,testArgs13};
792        UnicodeString exp[] = {
793            "Kirti sont all\\u00E9es \\u00E0 Paris." ,
794            "Kirti est all\\u00E9e \\u00E0 Paris.",
795            "Ash est all\\u00E9 \\u00E0 Paris.",
796            "Ash sont all\\u00E9s \\u00E0 Paris."};
797        //Format
798        for( int i=0; i< 4; i++){
799            internalFormat( msgFmt5 , testArgs[i], 3, exp[i].unescape() ,(char*)"From TestMessageFormat::testSelectFormat format t5");
800        }
801    }
802    delete msgFmt5;
803
804    err = U_ZERO_ERROR;
805    //Select, plural, and number formats heavily nested
806    UnicodeString t6("{0} und {1, select, female {{2, plural, one {{3, select, female {ihre Freundin} other {ihr Freund}} } other {ihre {2, number, integer} {3, select, female {Freundinnen} other {Freunde}} } }} other{{2, plural, one {{3, select, female {seine Freundin} other {sein Freund}}} other {seine {2, number, integer} {3, select, female {Freundinnen} other {Freunde}}}}} } gingen nach Paris.");
807    //Create the MessageFormat with Select, plural, and number formats heavily nested
808    MessageFormat* msgFmt6 = internalCreate(t6, Locale("de"),err,(char*)"From TestMessageFormat::TestSelectFormat create t6");
809    if (!U_FAILURE(err)) {
810        //Arguments
811        Formattable testArgs10[] = {"Kirti","other",(int32_t)1,"other"};
812        Formattable testArgs11[] = {"Kirti","other",(int32_t)6,"other"};
813        Formattable testArgs12[] = {"Kirti","other",(int32_t)1,"female"};
814        Formattable testArgs13[] = {"Kirti","other",(int32_t)3,"female"};
815        Formattable testArgs14[] = {"Kirti","female",(int32_t)1,"female"};
816        Formattable testArgs15[] = {"Kirti","female",(int32_t)5,"female"};
817        Formattable testArgs16[] = {"Kirti","female",(int32_t)1,"other"};
818        Formattable testArgs17[] = {"Kirti","female",(int32_t)5,"other"};
819        Formattable testArgs18[] = {"Kirti","mixed",(int32_t)1,"mixed"};
820        Formattable testArgs19[] = {"Kirti","mixed",(int32_t)1,"other"};
821        Formattable testArgs20[] = {"Kirti","female",(int32_t)1,"mixed"};
822        Formattable testArgs21[] = {"Kirti","mixed",(int32_t)5,"mixed"};
823        Formattable testArgs22[] = {"Kirti","mixed",(int32_t)5,"other"};
824        Formattable testArgs23[] = {"Kirti","female",(int32_t)5,"mixed"};
825        Formattable* testArgs[] = {testArgs10,testArgs11,testArgs12,testArgs13,
826                                   testArgs14,testArgs15,testArgs16,testArgs17,
827                                   testArgs18,testArgs19,testArgs20,testArgs21,
828                                   testArgs22,testArgs23 };
829        UnicodeString exp[] = {
830            "Kirti und sein Freund gingen nach Paris." ,
831            "Kirti und seine 6 Freunde gingen nach Paris." ,
832            "Kirti und seine Freundin gingen nach Paris.",
833            "Kirti und seine 3 Freundinnen gingen nach Paris.",
834            "Kirti und ihre Freundin  gingen nach Paris.",
835            "Kirti und ihre 5 Freundinnen  gingen nach Paris.",
836            "Kirti und ihr Freund  gingen nach Paris.",
837            "Kirti und ihre 5 Freunde  gingen nach Paris.",
838            "Kirti und sein Freund gingen nach Paris.",
839            "Kirti und sein Freund gingen nach Paris.",
840            "Kirti und ihr Freund  gingen nach Paris.",
841            "Kirti und seine 5 Freunde gingen nach Paris." ,
842            "Kirti und seine 5 Freunde gingen nach Paris." ,
843            "Kirti und ihre 5 Freunde  gingen nach Paris."
844        };
845        //Format
846        for( int i=0; i< 14; i++){
847            internalFormat( msgFmt6 , testArgs[i], 4, exp[i] ,(char*)"From TestMessageFormat::testSelectFormat format t6");
848        }
849    }
850    delete msgFmt6;
851}
852
853//---------------------------------
854//  API Tests
855//---------------------------------
856
857void TestMessageFormat::testCopyConstructor()
858{
859    UErrorCode success = U_ZERO_ERROR;
860    MessageFormat *x = new MessageFormat("There are {0} files on {1}", success);
861    MessageFormat *z = new MessageFormat("There are {0} files on {1} created", success);
862    MessageFormat *y = 0;
863    y = new MessageFormat(*x);
864    if ( (*x == *y) &&
865         (*x != *z) &&
866         (*y != *z) )
867         logln("First test (operator ==): Passed!");
868    else {
869        errln("TestMessageFormat::testCopyConstructor failed #1");
870        logln("First test (operator ==): Failed!");
871    }
872    if ( ((*x == *y) && (*y == *x)) &&
873         ((*x != *z) && (*z != *x)) &&
874         ((*y != *z) && (*z != *y)) )
875        logln("Second test (equals): Passed!");
876    else {
877        errln("TestMessageFormat::testCopyConstructor failed #2");
878        logln("Second test (equals): Failed!");
879    }
880
881    delete x;
882    delete y;
883    delete z;
884}
885
886
887void TestMessageFormat::testAssignment()
888{
889    UErrorCode success = U_ZERO_ERROR;
890    MessageFormat *x = new MessageFormat("There are {0} files on {1}", success);
891    MessageFormat *z = new MessageFormat("There are {0} files on {1} created", success);
892    MessageFormat *y = new MessageFormat("There are {0} files on {1} created", success);
893    *y = *x;
894    if ( (*x == *y) &&
895         (*x != *z) &&
896         (*y != *z) )
897        logln("First test (operator ==): Passed!");
898    else {
899        errln( "TestMessageFormat::testAssignment failed #1");
900        logln("First test (operator ==): Failed!");
901    }
902    if ( ((*x == *y) && (*y == *x)) &&
903         ((*x != *z) && (*z != *x)) &&
904         ((*y != *z) && (*z != *y)) )
905        logln("Second test (equals): Passed!");
906    else {
907        errln("TestMessageFormat::testAssignment failed #2");
908        logln("Second test (equals): Failed!");
909    }
910
911    delete x;
912    delete y;
913    delete z;
914}
915
916void TestMessageFormat::testClone()
917{
918    UErrorCode success = U_ZERO_ERROR;
919    MessageFormat *x = new MessageFormat("There are {0} files on {1}", success);
920    MessageFormat *z = new MessageFormat("There are {0} files on {1} created", success);
921    MessageFormat *y = 0;
922    y = (MessageFormat*)x->clone();
923    if ( (*x == *y) &&
924         (*x != *z) &&
925         (*y != *z) )
926        logln("First test (operator ==): Passed!");
927    else {
928        errln("TestMessageFormat::testClone failed #1");
929        logln("First test (operator ==): Failed!");
930    }
931    if ( ((*x == *y) && (*y == *x)) &&
932         ((*x != *z) && (*z != *x)) &&
933         ((*y != *z) && (*z != *y)) )
934        logln("Second test (equals): Passed!");
935    else {
936        errln("TestMessageFormat::testClone failed #2");
937        logln("Second test (equals): Failed!");
938    }
939
940    delete x;
941    delete y;
942    delete z;
943}
944
945void TestMessageFormat::testEquals()
946{
947    UErrorCode success = U_ZERO_ERROR;
948    MessageFormat x("There are {0} files on {1}", success);
949    MessageFormat y("There are {0} files on {1}", success);
950    if (!(x == y)) {
951        errln( "TestMessageFormat::testEquals failed #1");
952        logln("First test (operator ==): Failed!");
953    }
954
955}
956
957void TestMessageFormat::testNotEquals()
958{
959    UErrorCode success = U_ZERO_ERROR;
960    MessageFormat x("There are {0} files on {1}", success);
961    MessageFormat y(x);
962    y.setLocale(Locale("fr"));
963    if (!(x != y)) {
964        errln( "TestMessageFormat::testEquals failed #1");
965        logln("First test (operator !=): Failed!");
966    }
967    y = x;
968    y.applyPattern("There are {0} files on {1} the disk", success);
969    if (!(x != y)) {
970        errln( "TestMessageFormat::testEquals failed #1");
971        logln("Second test (operator !=): Failed!");
972    }
973}
974
975
976void TestMessageFormat::testSetLocale()
977{
978    UErrorCode err = U_ZERO_ERROR;
979    GregorianCalendar cal(err);
980    Formattable arguments[] = {
981        456.83,
982        Formattable(UDate(8.71068e+011), Formattable::kIsDate),
983        "deposit"
984        };
985
986    UnicodeString result;
987
988    //UnicodeString formatStr = "At {1,time} on {1,date}, you made a {2} of {0,number,currency}.";
989    UnicodeString formatStr = "At <time> on {1,date}, you made a {2} of {0,number,currency}.";
990    // {sfb} to get $, would need Locale::US, not Locale::ENGLISH
991    // Just use unlocalized currency symbol.
992    //UnicodeString compareStrEng = "At <time> on Aug 8, 1997, you made a deposit of $456.83.";
993    UnicodeString compareStrEng = "At <time> on Aug 8, 1997, you made a deposit of ";
994    compareStrEng += (UChar) 0x00a4;
995    compareStrEng += "456.83.";
996    // {sfb} to get DM, would need Locale::GERMANY, not Locale::GERMAN
997    // Just use unlocalized currency symbol.
998    //UnicodeString compareStrGer = "At <time> on 08.08.1997, you made a deposit of 456,83 DM.";
999    UnicodeString compareStrGer = "At <time> on 08.08.1997, you made a deposit of ";
1000    compareStrGer += "456,83";
1001    compareStrGer += (UChar) 0x00a0;
1002    compareStrGer += (UChar) 0x00a4;
1003    compareStrGer += ".";
1004
1005    MessageFormat msg( formatStr, err);
1006    result = "";
1007    FieldPosition pos(FieldPosition::DONT_CARE);
1008    result = msg.format(
1009        arguments,
1010        3,
1011        result,
1012        pos,
1013        err);
1014
1015    logln(result);
1016    if (result != compareStrEng) {
1017        dataerrln("***  MSG format err. - %s", u_errorName(err));
1018    }
1019
1020    msg.setLocale(Locale::getEnglish());
1021    UBool getLocale_ok = TRUE;
1022    if (msg.getLocale() != Locale::getEnglish()) {
1023        errln("*** MSG getLocal err.");
1024        getLocale_ok = FALSE;
1025    }
1026
1027    msg.setLocale(Locale::getGerman());
1028
1029    if (msg.getLocale() != Locale::getGerman()) {
1030        errln("*** MSG getLocal err.");
1031        getLocale_ok = FALSE;
1032    }
1033
1034    msg.applyPattern( formatStr, err);
1035
1036    pos.setField(0);
1037    result = "";
1038    result = msg.format(
1039        arguments,
1040        3,
1041        result,
1042        pos,
1043        err);
1044
1045    logln(result);
1046    if (result == compareStrGer) {
1047        logln("MSG setLocale tested.");
1048    }else{
1049        dataerrln( "*** MSG setLocale err. - %s", u_errorName(err));
1050    }
1051
1052    if (getLocale_ok) {
1053        logln("MSG getLocale tested.");
1054    }
1055}
1056
1057void TestMessageFormat::testFormat()
1058{
1059    UErrorCode err = U_ZERO_ERROR;
1060    GregorianCalendar cal(err);
1061
1062    const Formattable ftarray[] =
1063    {
1064        Formattable( UDate(8.71068e+011), Formattable::kIsDate )
1065    };
1066    const int32_t ft_cnt = UPRV_LENGTHOF(ftarray);
1067    Formattable ft_arr( ftarray, ft_cnt );
1068
1069    Formattable* fmt = new Formattable(UDate(8.71068e+011), Formattable::kIsDate);
1070
1071    UnicodeString result;
1072
1073    //UnicodeString formatStr = "At {1,time} on {1,date}, you made a {2} of {0,number,currency}.";
1074    UnicodeString formatStr = "On {0,date}, it began.";
1075    UnicodeString compareStr = "On Aug 8, 1997, it began.";
1076
1077    err = U_ZERO_ERROR;
1078    MessageFormat msg( formatStr, err);
1079    FieldPosition fp(FieldPosition::DONT_CARE);
1080
1081    result = "";
1082    fp = 0;
1083    result = msg.format(
1084        *fmt,
1085        result,
1086        //FieldPosition(0),
1087        fp,
1088        err);
1089
1090    if (err != U_ILLEGAL_ARGUMENT_ERROR) {
1091        dataerrln("*** MSG format without expected error code. - %s", u_errorName(err));
1092    }
1093    err = U_ZERO_ERROR;
1094
1095    result = "";
1096    fp = 0;
1097    result = msg.format(
1098        ft_arr,
1099        result,
1100        //FieldPosition(0),
1101        fp,
1102        err);
1103
1104    logln("MSG format( Formattable&, ... ) expected:" + compareStr);
1105    logln("MSG format( Formattable&, ... )   result:" + result);
1106    if (result != compareStr) {
1107        dataerrln("***  MSG format( Formattable&, .... ) err. - %s", u_errorName(err));
1108    }else{
1109        logln("MSG format( Formattable&, ... ) tested.");
1110    }
1111
1112    delete fmt;
1113
1114}
1115
1116void TestMessageFormat::testParse()
1117{
1118    UErrorCode err = U_ZERO_ERROR;
1119    int32_t count;
1120    UnicodeString msgFormatString = "{0} =sep= {1}";
1121    MessageFormat msg( msgFormatString, err);
1122    UnicodeString source = "abc =sep= def";
1123    UnicodeString tmp1, tmp2;
1124
1125    Formattable* fmt_arr = msg.parse( source, count, err );
1126    if (U_FAILURE(err) || (!fmt_arr)) {
1127        errln("*** MSG parse (ustring, count, err) error.");
1128    }else{
1129        logln("MSG parse -- count: %d", count);
1130        if (count != 2) {
1131            errln("*** MSG parse (ustring, count, err) count err.");
1132        }else{
1133            if ((fmt_arr[0].getType() == Formattable::kString)
1134             && (fmt_arr[1].getType() == Formattable::kString)
1135             && (fmt_arr[0].getString(tmp1) == "abc")
1136             && (fmt_arr[1].getString(tmp2) == "def")) {
1137                logln("MSG parse (ustring, count, err) tested.");
1138            }else{
1139                errln("*** MSG parse (ustring, count, err) result err.");
1140            }
1141        }
1142    }
1143    delete[] fmt_arr;
1144
1145    ParsePosition pp(0);
1146
1147    fmt_arr = msg.parse( source, pp, count );
1148    if ((pp == 0) || (!fmt_arr)) {
1149        errln("*** MSG parse (ustring, parsepos., count) error.");
1150    }else{
1151        logln("MSG parse -- count: %d", count);
1152        if (count != 2) {
1153            errln("*** MSG parse (ustring, parsepos., count) count err.");
1154        }else{
1155            if ((fmt_arr[0].getType() == Formattable::kString)
1156             && (fmt_arr[1].getType() == Formattable::kString)
1157             && (fmt_arr[0].getString(tmp1) == "abc")
1158             && (fmt_arr[1].getString(tmp2) == "def")) {
1159                logln("MSG parse (ustring, parsepos., count) tested.");
1160            }else{
1161                errln("*** MSG parse (ustring, parsepos., count) result err.");
1162            }
1163        }
1164    }
1165    delete[] fmt_arr;
1166
1167    pp = 0;
1168    Formattable fmta;
1169
1170    msg.parseObject( source, fmta, pp );
1171    if (pp == 0) {
1172        errln("*** MSG parse (ustring, Formattable, parsepos ) error.");
1173    }else{
1174        logln("MSG parse -- count: %d", count);
1175        fmta.getArray(count);
1176        if (count != 2) {
1177            errln("*** MSG parse (ustring, Formattable, parsepos ) count err.");
1178        }else{
1179            if ((fmta[0].getType() == Formattable::kString)
1180             && (fmta[1].getType() == Formattable::kString)
1181             && (fmta[0].getString(tmp1) == "abc")
1182             && (fmta[1].getString(tmp2) == "def")) {
1183                logln("MSG parse (ustring, Formattable, parsepos ) tested.");
1184            }else{
1185                errln("*** MSG parse (ustring, Formattable, parsepos ) result err.");
1186            }
1187        }
1188    }
1189}
1190
1191
1192void TestMessageFormat::testAdopt()
1193{
1194    UErrorCode err = U_ZERO_ERROR;
1195
1196    UnicodeString formatStr("{0,date},{1},{2,number}", "");
1197    UnicodeString formatStrChange("{0,number},{1,number},{2,date}", "");
1198    err = U_ZERO_ERROR;
1199    MessageFormat msg( formatStr, err);
1200    MessageFormat msgCmp( formatStr, err);
1201    if (U_FAILURE(err)) {
1202        dataerrln("Unable to instantiate MessageFormat - %s", u_errorName(err));
1203        return;
1204    }
1205    int32_t count, countCmp;
1206    const Format** formats = msg.getFormats(count);
1207    const Format** formatsCmp = msgCmp.getFormats(countCmp);
1208    const Format** formatsChg = 0;
1209    const Format** formatsAct = 0;
1210    int32_t countAct;
1211    const Format* a;
1212    const Format* b;
1213    UnicodeString patCmp;
1214    UnicodeString patAct;
1215    Format** formatsToAdopt;
1216
1217    if (!formats || !formatsCmp || (count <= 0) || (count != countCmp)) {
1218        dataerrln("Error getting Formats");
1219        return;
1220    }
1221
1222    int32_t i;
1223
1224    for (i = 0; i < count; i++) {
1225        a = formats[i];
1226        b = formatsCmp[i];
1227        if ((a != NULL) && (b != NULL)) {
1228            if (*a != *b) {
1229                errln("a != b");
1230                return;
1231            }
1232        }else if ((a != NULL) || (b != NULL)) {
1233            errln("(a != NULL) || (b != NULL)");
1234            return;
1235        }
1236    }
1237
1238    msg.applyPattern( formatStrChange, err ); //set msg formats to something different
1239    int32_t countChg;
1240    formatsChg = msg.getFormats(countChg); // tested function
1241    if (!formatsChg || (countChg != count)) {
1242        errln("Error getting Formats");
1243        return;
1244    }
1245
1246    UBool diff;
1247    diff = TRUE;
1248    for (i = 0; i < count; i++) {
1249        a = formatsChg[i];
1250        b = formatsCmp[i];
1251        if ((a != NULL) && (b != NULL)) {
1252            if (*a == *b) {
1253                logln("formatsChg == formatsCmp at index %d", i);
1254                diff = FALSE;
1255            }
1256        }
1257    }
1258    if (!diff) {
1259        errln("*** MSG getFormats diff err.");
1260        return;
1261    }
1262
1263    logln("MSG getFormats tested.");
1264
1265    msg.setFormats( formatsCmp, countCmp ); //tested function
1266
1267    formatsAct = msg.getFormats(countAct);
1268    if (!formatsAct || (countAct <=0) || (countAct != countCmp)) {
1269        errln("Error getting Formats");
1270        return;
1271    }
1272
1273    assertEquals("msgCmp.toPattern()", formatStr, msgCmp.toPattern(patCmp.remove()));
1274    // ICU 4.8 does not support toPattern() when there are custom formats (from setFormat() etc.).
1275    // assertEquals("msg.toPattern()", formatStr, msg.toPattern(patAct.remove()));
1276    msg.toPattern(patCmp.remove());
1277    if (!patCmp.isBogus()) {
1278      errln("msg.setFormat().toPattern() succeeds.");
1279    }
1280
1281    for (i = 0; i < countAct; i++) {
1282        a = formatsAct[i];
1283        b = formatsCmp[i];
1284        if ((a != NULL) && (b != NULL)) {
1285            if (*a != *b) {
1286                logln("formatsAct != formatsCmp at index %d", i);
1287                errln("a != b");
1288                return;
1289            }
1290        }else if ((a != NULL) || (b != NULL)) {
1291            errln("(a != NULL) || (b != NULL)");
1292            return;
1293        }
1294    }
1295    logln("MSG setFormats tested.");
1296
1297    //----
1298
1299    msg.applyPattern( formatStrChange, err ); //set msg formats to something different
1300
1301    formatsToAdopt = new Format* [countCmp];
1302    if (!formatsToAdopt) {
1303        errln("memory allocation error");
1304        return;
1305    }
1306
1307    for (i = 0; i < countCmp; i++) {
1308        if (formatsCmp[i] == NULL) {
1309            formatsToAdopt[i] = NULL;
1310        }else{
1311            formatsToAdopt[i] = formatsCmp[i]->clone();
1312            if (!formatsToAdopt[i]) {
1313                errln("Can't clone format at index %d", i);
1314                return;
1315            }
1316        }
1317    }
1318    msg.adoptFormats( formatsToAdopt, countCmp ); // function to test
1319    delete[] formatsToAdopt;
1320
1321    assertEquals("msgCmp.toPattern()", formatStr, msgCmp.toPattern(patCmp.remove()));
1322    // ICU 4.8 does not support toPattern() when there are custom formats (from setFormat() etc.).
1323    // assertEquals("msg.toPattern()", formatStr, msg.toPattern(patAct.remove()));
1324
1325    formatsAct = msg.getFormats(countAct);
1326    if (!formatsAct || (countAct <=0) || (countAct != countCmp)) {
1327        errln("Error getting Formats");
1328        return;
1329    }
1330
1331    for (i = 0; i < countAct; i++) {
1332        a = formatsAct[i];
1333        b = formatsCmp[i];
1334        if ((a != NULL) && (b != NULL)) {
1335            if (*a != *b) {
1336                errln("a != b");
1337                return;
1338            }
1339        }else if ((a != NULL) || (b != NULL)) {
1340            errln("(a != NULL) || (b != NULL)");
1341            return;
1342        }
1343    }
1344    logln("MSG adoptFormats tested.");
1345
1346    //---- adoptFormat
1347
1348    msg.applyPattern( formatStrChange, err ); //set msg formats to something different
1349
1350    formatsToAdopt = new Format* [countCmp];
1351    if (!formatsToAdopt) {
1352        errln("memory allocation error");
1353        return;
1354    }
1355
1356    for (i = 0; i < countCmp; i++) {
1357        if (formatsCmp[i] == NULL) {
1358            formatsToAdopt[i] = NULL;
1359        }else{
1360            formatsToAdopt[i] = formatsCmp[i]->clone();
1361            if (!formatsToAdopt[i]) {
1362                errln("Can't clone format at index %d", i);
1363                return;
1364            }
1365        }
1366    }
1367
1368    for ( i = 0; i < countCmp; i++ ) {
1369        msg.adoptFormat( i, formatsToAdopt[i] ); // function to test
1370    }
1371    delete[] formatsToAdopt; // array itself not needed in this case;
1372
1373    assertEquals("msgCmp.toPattern()", formatStr, msgCmp.toPattern(patCmp.remove()));
1374    // ICU 4.8 does not support toPattern() when there are custom formats (from setFormat() etc.).
1375    // assertEquals("msg.toPattern()", formatStr, msg.toPattern(patAct.remove()));
1376
1377    formatsAct = msg.getFormats(countAct);
1378    if (!formatsAct || (countAct <=0) || (countAct != countCmp)) {
1379        errln("Error getting Formats");
1380        return;
1381    }
1382
1383    for (i = 0; i < countAct; i++) {
1384        a = formatsAct[i];
1385        b = formatsCmp[i];
1386        if ((a != NULL) && (b != NULL)) {
1387            if (*a != *b) {
1388                errln("a != b");
1389                return;
1390            }
1391        }else if ((a != NULL) || (b != NULL)) {
1392            errln("(a != NULL) || (b != NULL)");
1393            return;
1394        }
1395    }
1396    logln("MSG adoptFormat tested.");
1397}
1398
1399// This test is a regression test for a fixed bug in the copy constructor.
1400// It is kept as a global function rather than as a method since the test depends on memory values.
1401// (At least before the bug was fixed, whether it showed up or not depended on memory contents,
1402// which is probably why it didn't show up in the regular test for the copy constructor.)
1403// For this reason, the test isn't changed even though it contains function calls whose results are
1404// not tested and had no problems. Actually, the test failed by *crashing*.
1405static void _testCopyConstructor2()
1406{
1407    UErrorCode status = U_ZERO_ERROR;
1408    UnicodeString formatStr("Hello World on {0,date,full}", "");
1409    UnicodeString resultStr(" ", "");
1410    UnicodeString result;
1411    FieldPosition fp(FieldPosition::DONT_CARE);
1412    UDate d = Calendar::getNow();
1413    const Formattable fargs( d, Formattable::kIsDate );
1414
1415    MessageFormat* fmt1 = new MessageFormat( formatStr, status );
1416    MessageFormat* fmt2 = NULL;
1417    MessageFormat* fmt3 = NULL;
1418    MessageFormat* fmt4 = NULL;
1419
1420    if (fmt1 == NULL) {
1421        it_err("testCopyConstructor2: (fmt1 != NULL)");
1422        goto cleanup;
1423    }
1424
1425    fmt2 = new MessageFormat( *fmt1 );
1426    result = fmt1->format( &fargs, 1, resultStr, fp, status );
1427
1428    if (fmt2 == NULL) {
1429        it_err("testCopyConstructor2: (fmt2 != NULL)");
1430        goto cleanup;
1431    }
1432
1433    fmt3 = (MessageFormat*) fmt1->clone();
1434    fmt4 = (MessageFormat*) fmt2->clone();
1435
1436    if (fmt3 == NULL) {
1437        it_err("testCopyConstructor2: (fmt3 != NULL)");
1438        goto cleanup;
1439    }
1440    if (fmt4 == NULL) {
1441        it_err("testCopyConstructor2: (fmt4 != NULL)");
1442        goto cleanup;
1443    }
1444
1445    result = fmt1->format( &fargs, 1, resultStr, fp, status );
1446    result = fmt2->format( &fargs, 1, resultStr, fp, status );
1447    result = fmt3->format( &fargs, 1, resultStr, fp, status );
1448    result = fmt4->format( &fargs, 1, resultStr, fp, status );
1449
1450cleanup:
1451    delete fmt1;
1452    delete fmt2;
1453    delete fmt3;
1454    delete fmt4;
1455}
1456
1457void TestMessageFormat::testCopyConstructor2() {
1458    _testCopyConstructor2();
1459}
1460
1461/**
1462 * Verify that MessageFormat accomodates more than 10 arguments and
1463 * more than 10 subformats.
1464 */
1465void TestMessageFormat::TestUnlimitedArgsAndSubformats() {
1466    UErrorCode ec = U_ZERO_ERROR;
1467    const UnicodeString pattern =
1468        "On {0,date} (aka {0,date,short}, aka {0,date,long}) "
1469        "at {0,time} (aka {0,time,short}, aka {0,time,long}) "
1470        "there were {1,number} werjes "
1471        "(a {3,number,percent} increase over {2,number}) "
1472        "despite the {4}''s efforts "
1473        "and to delight of {5}, {6}, {7}, {8}, {9}, and {10} {11}.";
1474    MessageFormat msg(pattern, ec);
1475    if (U_FAILURE(ec)) {
1476        dataerrln("FAIL: constructor failed - %s", u_errorName(ec));
1477        return;
1478    }
1479
1480    const Formattable ARGS[] = {
1481        Formattable(UDate(1e13), Formattable::kIsDate),
1482        Formattable((int32_t)1303),
1483        Formattable((int32_t)1202),
1484        Formattable(1303.0/1202 - 1),
1485        Formattable("Glimmung"),
1486        Formattable("the printers"),
1487        Formattable("Nick"),
1488        Formattable("his father"),
1489        Formattable("his mother"),
1490        Formattable("the spiddles"),
1491        Formattable("of course"),
1492        Formattable("Horace"),
1493    };
1494    const int32_t ARGS_LENGTH = UPRV_LENGTHOF(ARGS);
1495    Formattable ARGS_OBJ(ARGS, ARGS_LENGTH);
1496
1497    UnicodeString expected =
1498        "On Nov 20, 2286 (aka 11/20/86, aka November 20, 2286) "
1499        "at 9:46:40 AM (aka 9:46 AM, aka 9:46:40 AM PST) "
1500        "there were 1,303 werjes "
1501        "(a 8% increase over 1,202) "
1502        "despite the Glimmung's efforts "
1503        "and to delight of the printers, Nick, his father, "
1504        "his mother, the spiddles, and of course Horace.";
1505    UnicodeString result;
1506    msg.format(ARGS_OBJ, result, ec);
1507    if (result == expected) {
1508        logln(result);
1509    } else {
1510        errln((UnicodeString)"FAIL: Got " + result +
1511              ", expected " + expected);
1512    }
1513}
1514
1515// test RBNF extensions to message format
1516void TestMessageFormat::TestRBNF(void) {
1517    // WARNING: this depends on the RBNF formats for en_US
1518    Locale locale("en", "US", "");
1519
1520    UErrorCode ec = U_ZERO_ERROR;
1521
1522    UnicodeString values[] = {
1523        // decimal values do not format completely for ordinal or duration, and
1524        // do not always parse, so do not include them
1525        "0", "1", "12", "100", "123", "1001", "123,456", "-17",
1526    };
1527    int32_t values_count = UPRV_LENGTHOF(values);
1528
1529    UnicodeString formats[] = {
1530        "There are {0,spellout} files to search.",
1531        "There are {0,spellout,%simplified} files to search.",
1532        "The bogus spellout {0,spellout,%BOGUS} files behaves like the default.",
1533        "This is the {0,ordinal} file to search.",
1534        "Searching this file will take {0,duration} to complete.",
1535        "Searching this file will take {0,duration,%with-words} to complete.",
1536    };
1537    int32_t formats_count = UPRV_LENGTHOF(formats);
1538
1539    Formattable args[1];
1540
1541    NumberFormat* numFmt = NumberFormat::createInstance(locale, ec);
1542    if (U_FAILURE(ec)) {
1543        dataerrln("Error calling NumberFormat::createInstance()");
1544        return;
1545    }
1546
1547    for (int i = 0; i < formats_count; ++i) {
1548        MessageFormat* fmt = new MessageFormat(formats[i], locale, ec);
1549        logln((UnicodeString)"Testing format pattern: '" + formats[i] + "'");
1550
1551        for (int j = 0; j < values_count; ++j) {
1552            ec = U_ZERO_ERROR;
1553            numFmt->parse(values[j], args[0], ec);
1554            if (U_FAILURE(ec)) {
1555                errln((UnicodeString)"Failed to parse test argument " + values[j]);
1556            } else {
1557                FieldPosition fp(FieldPosition::DONT_CARE);
1558                UnicodeString result;
1559                fmt->format(args, 1, result, fp, ec);
1560                logln((UnicodeString)"value: " + toString(args[0]) + " --> " + result + UnicodeString(" ec: ") + u_errorName(ec));
1561
1562                int32_t count = 0;
1563                Formattable* parseResult = fmt->parse(result, count, ec);
1564                if (count != 1) {
1565                    errln((UnicodeString)"parse returned " + count + " args");
1566                } else if (parseResult[0] != args[0]) {
1567                    errln((UnicodeString)"parsed argument " + toString(parseResult[0]) + " != " + toString(args[0]));
1568                }
1569                delete []parseResult;
1570            }
1571        }
1572        delete fmt;
1573    }
1574    delete numFmt;
1575}
1576
1577UnicodeString TestMessageFormat::GetPatternAndSkipSyntax(const MessagePattern& pattern) {
1578    UnicodeString us(pattern.getPatternString());
1579    int count = pattern.countParts();
1580    for (int i = count; i > 0;) {
1581        const MessagePattern::Part& part = pattern.getPart(--i);
1582        if (part.getType() == UMSGPAT_PART_TYPE_SKIP_SYNTAX) {
1583            us.remove(part.getIndex(), part.getLimit() - part.getIndex());
1584        }
1585    }
1586    return us;
1587}
1588
1589void TestMessageFormat::TestApostropheMode() {
1590    UErrorCode status = U_ZERO_ERROR;
1591    MessagePattern *ado_mp = new MessagePattern(UMSGPAT_APOS_DOUBLE_OPTIONAL, status);
1592    MessagePattern *adr_mp = new MessagePattern(UMSGPAT_APOS_DOUBLE_REQUIRED, status);
1593    if (ado_mp->getApostropheMode() != UMSGPAT_APOS_DOUBLE_OPTIONAL) {
1594      errln("wrong value from ado_mp->getApostropheMode().");
1595    }
1596    if (adr_mp->getApostropheMode() != UMSGPAT_APOS_DOUBLE_REQUIRED) {
1597      errln("wrong value from adr_mp->getApostropheMode().");
1598    }
1599
1600
1601    UnicodeString tuples[] = {
1602        // Desired output
1603        // DOUBLE_OPTIONAL pattern
1604        // DOUBLE_REQUIRED pattern (empty=same as DOUBLE_OPTIONAL)
1605        "I see {many}", "I see '{many}'", "",
1606        "I said {'Wow!'}", "I said '{''Wow!''}'", "",
1607        "I dont know", "I dont know", "I don't know",
1608        "I don't know", "I don't know", "I don''t know",
1609        "I don't know", "I don''t know", "I don''t know"
1610    };
1611    int32_t tuples_count = UPRV_LENGTHOF(tuples);
1612
1613    for (int i = 0; i < tuples_count; i += 3) {
1614      UnicodeString& desired = tuples[i];
1615      UnicodeString& ado_pattern = tuples[i + 1];
1616      UErrorCode status = U_ZERO_ERROR;
1617      assertEquals("DOUBLE_OPTIONAL failure",
1618                   desired,
1619                   GetPatternAndSkipSyntax(ado_mp->parse(ado_pattern, NULL, status)));
1620      UnicodeString& adr_pattern = tuples[i + 2].isEmpty() ? ado_pattern : tuples[i + 2];
1621      assertEquals("DOUBLE_REQUIRED failure", desired,
1622          GetPatternAndSkipSyntax(adr_mp->parse(adr_pattern, NULL, status)));
1623    }
1624    delete adr_mp;
1625    delete ado_mp;
1626}
1627
1628
1629// Compare behavior of DOUBLE_OPTIONAL (new default) and DOUBLE_REQUIRED JDK-compatibility mode.
1630void TestMessageFormat::TestCompatibleApostrophe() {
1631    // Message with choice argument which does not contain another argument.
1632    // The JDK performs only one apostrophe-quoting pass on this pattern.
1633    UnicodeString pattern = "ab{0,choice,0#1'2''3'''4''''.}yz";
1634
1635    UErrorCode ec = U_ZERO_ERROR;
1636    MessageFormat compMsg("", Locale::getUS(), ec);
1637    compMsg.applyPattern(pattern, UMSGPAT_APOS_DOUBLE_REQUIRED, NULL, ec);
1638    if (compMsg.getApostropheMode() != UMSGPAT_APOS_DOUBLE_REQUIRED) {
1639        errln("wrong value from  compMsg.getApostropheMode().");
1640    }
1641
1642    MessageFormat icuMsg("", Locale::getUS(), ec);
1643    icuMsg.applyPattern(pattern, UMSGPAT_APOS_DOUBLE_OPTIONAL, NULL, ec);
1644    if (icuMsg.getApostropheMode() != UMSGPAT_APOS_DOUBLE_OPTIONAL) {
1645        errln("wrong value from  icuMsg.getApostropheMode().");
1646    }
1647
1648    Formattable zero0[] = { (int32_t)0 };
1649    FieldPosition fieldpos(FieldPosition::DONT_CARE);
1650    UnicodeString buffer1, buffer2;
1651    assertEquals("incompatible ICU MessageFormat compatibility-apostrophe behavior",
1652            "ab12'3'4''.yz",
1653            compMsg.format(zero0, 1, buffer1, fieldpos, ec));
1654    assertEquals("unexpected ICU MessageFormat double-apostrophe-optional behavior",
1655            "ab1'2'3''4''.yz",
1656            icuMsg.format(zero0, 1, buffer2, fieldpos, ec));
1657
1658    // Message with choice argument which contains a nested simple argument.
1659    // The DOUBLE_REQUIRED version performs two apostrophe-quoting passes.
1660    buffer1.remove();
1661    buffer2.remove();
1662    pattern = "ab{0,choice,0#1'2''3'''4''''.{0,number,'#x'}}yz";
1663    compMsg.applyPattern(pattern, ec);
1664    icuMsg.applyPattern(pattern, ec);
1665    if (U_FAILURE(ec)) {
1666        dataerrln("Unable to applyPattern - %s", u_errorName(ec));
1667    } else {
1668        assertEquals("incompatible ICU MessageFormat compatibility-apostrophe behavior",
1669                "ab1234'.0xyz",
1670                compMsg.format(zero0, 1, buffer1, fieldpos, ec));
1671        assertEquals("unexpected ICU MessageFormat double-apostrophe-optional behavior",
1672                "ab1'2'3''4''.#x0yz",
1673                icuMsg.format(zero0, 1, buffer2, fieldpos, ec));
1674    }
1675
1676    // This part is copied over from Java tests but cannot be properly tested here
1677    // because we do not have a live reference implementation with JDK behavior.
1678    // The JDK ChoiceFormat itself always performs one apostrophe-quoting pass.
1679    /*
1680    ChoiceFormat choice = new ChoiceFormat("0#1'2''3'''4''''.");
1681    assertEquals("unexpected JDK ChoiceFormat apostrophe behavior",
1682            "12'3'4''.",
1683            choice.format(0));
1684    choice.applyPattern("0#1'2''3'''4''''.{0,number,'#x'}");
1685    assertEquals("unexpected JDK ChoiceFormat apostrophe behavior",
1686            "12'3'4''.{0,number,#x}",
1687            choice.format(0));
1688    */
1689}
1690
1691void TestMessageFormat::testAutoQuoteApostrophe(void) {
1692    const char* patterns[] = { // pattern, expected pattern
1693        "'", "''",
1694        "''", "''",
1695        "'{", "'{'",
1696        "' {", "'' {",
1697        "'a", "''a",
1698        "'{'a", "'{'a",
1699        "'{a'", "'{a'",
1700        "'{}", "'{}'",
1701        "{'", "{'",
1702        "{'a", "{'a",
1703        "{'a{}'a}'a", "{'a{}'a}''a",
1704        "'}'", "'}'",
1705        "'} '{'}'", "'} '{'}''",
1706        "'} {{{''", "'} {{{'''",
1707    };
1708    int32_t pattern_count = UPRV_LENGTHOF(patterns);
1709
1710    for (int i = 0; i < pattern_count; i += 2) {
1711        UErrorCode status = U_ZERO_ERROR;
1712        UnicodeString result = MessageFormat::autoQuoteApostrophe(patterns[i], status);
1713        UnicodeString target(patterns[i+1]);
1714        if (target != result) {
1715            const int BUF2_LEN = 64;
1716            char buf[256];
1717            char buf2[BUF2_LEN];
1718            int32_t len = result.extract(0, result.length(), buf2, BUF2_LEN);
1719            if (len >= BUF2_LEN) {
1720                buf2[BUF2_LEN-1] = 0;
1721            }
1722            sprintf(buf, "[%2d] test \"%s\": target (\"%s\") != result (\"%s\")\n", i/2, patterns[i], patterns[i+1], buf2);
1723            errln(buf);
1724        }
1725    }
1726}
1727
1728void TestMessageFormat::testCoverage(void) {
1729    UErrorCode status = U_ZERO_ERROR;
1730    UnicodeString testformat("{argument, plural, one{C''est # fichier} other {Ce sont # fichiers}} dans la liste.");
1731    MessageFormat *msgfmt = new MessageFormat(testformat, Locale("fr"), status);
1732    if (msgfmt == NULL || U_FAILURE(status)) {
1733        dataerrln("FAIL: Unable to create MessageFormat.: %s", u_errorName(status));
1734        return;
1735    }
1736    if (!msgfmt->usesNamedArguments()) {
1737        errln("FAIL: Unable to detect usage of named arguments.");
1738    }
1739    const double limit[] = {0.0, 1.0, 2.0};
1740    const UnicodeString formats[] = {"0.0<=Arg<1.0",
1741                                   "1.0<=Arg<2.0",
1742                                   "2.0<-Arg"};
1743    ChoiceFormat cf(limit, formats, 3);
1744
1745    msgfmt->setFormat("set", cf, status);
1746
1747    StringEnumeration *en = msgfmt->getFormatNames(status);
1748    if (en == NULL || U_FAILURE(status)) {
1749        errln("FAIL: Unable to get format names enumeration.");
1750    } else {
1751        int32_t count = 0;
1752        en->reset(status);
1753        count = en->count(status);
1754        if (U_FAILURE(status)) {
1755            errln("FAIL: Unable to get format name enumeration count.");
1756        } else {
1757            for (int32_t i = 0; i < count; i++) {
1758                en->snext(status);
1759                if (U_FAILURE(status)) {
1760                    errln("FAIL: Error enumerating through names.");
1761                    break;
1762                }
1763            }
1764        }
1765    }
1766
1767    // adoptFormat() takes ownership of the input Format object.
1768    // We need to clone the stack-allocated cf so that we do not attempt to delete cf.
1769    Format *cfClone = cf.clone();
1770    msgfmt->adoptFormat("adopt", cfClone, status);
1771
1772    delete en;
1773    delete msgfmt;
1774
1775    msgfmt = new MessageFormat("'", status);
1776    if (msgfmt == NULL || U_FAILURE(status)) {
1777        errln("FAIL: Unable to create MessageFormat.");
1778        return;
1779    }
1780    if (msgfmt->usesNamedArguments()) {
1781        errln("FAIL: Unable to detect usage of named arguments.");
1782    }
1783
1784    // Starting with ICU 4.8, we support setFormat(name, ...) and getFormatNames()
1785    // on a MessageFormat without named arguments.
1786    msgfmt->setFormat("formatName", cf, status);
1787    if (U_FAILURE(status)) {
1788        errln("FAIL: Should work to setFormat(name, ...) regardless of pattern.");
1789    }
1790    status = U_ZERO_ERROR;
1791    en = msgfmt->getFormatNames(status);
1792    if (U_FAILURE(status)) {
1793        errln("FAIL: Should work to get format names enumeration regardless of pattern.");
1794    }
1795
1796    delete en;
1797    delete msgfmt;
1798}
1799
1800void TestMessageFormat::testGetFormatNames() {
1801    IcuTestErrorCode errorCode(*this, "testGetFormatNames");
1802    MessageFormat msgfmt("Hello, {alice,number} {oops,date,full}  {zip,spellout} World.", Locale::getRoot(), errorCode);
1803    if(errorCode.logDataIfFailureAndReset("MessageFormat() failed")) {
1804        return;
1805    }
1806    LocalPointer<StringEnumeration> names(msgfmt.getFormatNames(errorCode));
1807    if(errorCode.logIfFailureAndReset("msgfmt.getFormatNames() failed")) {
1808        return;
1809    }
1810    const UnicodeString *name;
1811    name = names->snext(errorCode);
1812    if (name == NULL || errorCode.isFailure()) {
1813        errln("msgfmt.getFormatNames()[0] failed: %s", errorCode.errorName());
1814        errorCode.reset();
1815        return;
1816    }
1817    if (!assertEquals("msgfmt.getFormatNames()[0]", UNICODE_STRING_SIMPLE("alice"), *name)) {
1818        return;
1819    }
1820    name = names->snext(errorCode);
1821    if (name == NULL || errorCode.isFailure()) {
1822        errln("msgfmt.getFormatNames()[1] failed: %s", errorCode.errorName());
1823        errorCode.reset();
1824        return;
1825    }
1826    if (!assertEquals("msgfmt.getFormatNames()[1]", UNICODE_STRING_SIMPLE("oops"), *name)) {
1827        return;
1828    }
1829    name = names->snext(errorCode);
1830    if (name == NULL || errorCode.isFailure()) {
1831        errln("msgfmt.getFormatNames()[2] failed: %s", errorCode.errorName());
1832        errorCode.reset();
1833        return;
1834    }
1835    if (!assertEquals("msgfmt.getFormatNames()[2]", UNICODE_STRING_SIMPLE("zip"), *name)) {
1836        return;
1837    }
1838    name = names->snext(errorCode);
1839    if (name != NULL) {
1840        errln(UnicodeString("msgfmt.getFormatNames()[3] should be NULL but is: ") + *name);
1841        return;
1842    }
1843}
1844
1845void TestMessageFormat::TestTrimArgumentName() {
1846    // ICU 4.8 allows and ignores white space around argument names and numbers.
1847    IcuTestErrorCode errorCode(*this, "TestTrimArgumentName");
1848    MessageFormat m("a { 0 , number , '#,#'#.0 } z", Locale::getEnglish(), errorCode);
1849    if (errorCode.logDataIfFailureAndReset("Unable to instantiate MessageFormat")) {
1850        return;
1851    }
1852    Formattable args[1] = { (int32_t)2 };
1853    FieldPosition ignore(FieldPosition::DONT_CARE);
1854    UnicodeString result;
1855    assertEquals("trim-numbered-arg format() failed", "a  #,#2.0  z",
1856                 m.format(args, 1, result, ignore, errorCode));
1857
1858    m.applyPattern("x { _oOo_ , number , integer } y", errorCode);
1859    UnicodeString argName = UNICODE_STRING_SIMPLE("_oOo_");
1860    args[0].setLong(3);
1861    result.remove();
1862    assertEquals("trim-named-arg format() failed", "x 3 y",
1863                  m.format(&argName, args, 1, result, errorCode));
1864}
1865
1866void TestMessageFormat::TestSelectOrdinal() {
1867    IcuTestErrorCode errorCode(*this, "TestSelectOrdinal");
1868    // Test plural & ordinal together,
1869    // to make sure that we get the correct cached PluralSelector for each.
1870    MessageFormat m(
1871        "{0,plural,one{1 file}other{# files}}, "
1872        "{0,selectordinal,one{#st file}two{#nd file}few{#rd file}other{#th file}}",
1873        Locale::getEnglish(), errorCode);
1874    if (errorCode.logDataIfFailureAndReset("Unable to instantiate MessageFormat")) {
1875        return;
1876    }
1877    Formattable args[1] = { (int32_t)21 };
1878    FieldPosition ignore(FieldPosition::DONT_CARE);
1879    UnicodeString result;
1880    assertEquals("plural-and-ordinal format(21) failed", "21 files, 21st file",
1881                 m.format(args, 1, result, ignore, errorCode), TRUE);
1882
1883    args[0].setLong(2);
1884    assertEquals("plural-and-ordinal format(2) failed", "2 files, 2nd file",
1885                 m.format(args, 1, result.remove(), ignore, errorCode), TRUE);
1886
1887    args[0].setLong(1);
1888    assertEquals("plural-and-ordinal format(1) failed", "1 file, 1st file",
1889                 m.format(args, 1, result.remove(), ignore, errorCode), TRUE);
1890
1891    args[0].setLong(3);
1892    assertEquals("plural-and-ordinal format(3) failed", "3 files, 3rd file",
1893                 m.format(args, 1, result.remove(), ignore, errorCode), TRUE);
1894
1895    errorCode.logDataIfFailureAndReset("");
1896}
1897
1898void TestMessageFormat::TestDecimals() {
1899    IcuTestErrorCode errorCode(*this, "TestDecimals");
1900    // Simple number replacement.
1901    MessageFormat m(
1902            "{0,plural,one{one meter}other{# meters}}",
1903            Locale::getEnglish(), errorCode);
1904    Formattable args[1] = { (int32_t)1 };
1905    FieldPosition ignore;
1906    UnicodeString result;
1907    assertEquals("simple format(1)", "one meter",
1908            m.format(args, 1, result, ignore, errorCode), TRUE);
1909
1910    args[0] = (double)1.5;
1911    result.remove();
1912    assertEquals("simple format(1.5)", "1.5 meters",
1913            m.format(args, 1, result, ignore, errorCode), TRUE);
1914
1915    // Simple but explicit.
1916    MessageFormat m0(
1917            "{0,plural,one{one meter}other{{0} meters}}",
1918            Locale::getEnglish(), errorCode);
1919    args[0] = (int32_t)1;
1920    result.remove();
1921    assertEquals("explicit format(1)", "one meter",
1922            m0.format(args, 1, result, ignore, errorCode), TRUE);
1923
1924    args[0] = (double)1.5;
1925    result.remove();
1926    assertEquals("explicit format(1.5)", "1.5 meters",
1927            m0.format(args, 1, result, ignore, errorCode), TRUE);
1928
1929    // With offset and specific simple format with optional decimals.
1930    MessageFormat m1(
1931            "{0,plural,offset:1 one{another meter}other{{0,number,00.#} meters}}",
1932            Locale::getEnglish(), errorCode);
1933    args[0] = (int32_t)1;
1934    result.remove();
1935    assertEquals("offset format(1)", "01 meters",
1936            m1.format(args, 1, result, ignore, errorCode), TRUE);
1937
1938    args[0] = (int32_t)2;
1939    result.remove();
1940    assertEquals("offset format(1)", "another meter",
1941            m1.format(args, 1, result, ignore, errorCode), TRUE);
1942
1943    args[0] = (double)2.5;
1944    result.remove();
1945    assertEquals("offset format(1)", "02.5 meters",
1946            m1.format(args, 1, result, ignore, errorCode), TRUE);
1947
1948    // With offset and specific simple format with forced decimals.
1949    MessageFormat m2(
1950            "{0,plural,offset:1 one{another meter}other{{0,number,0.0} meters}}",
1951            Locale::getEnglish(), errorCode);
1952    args[0] = (int32_t)1;
1953    result.remove();
1954    assertEquals("offset-decimals format(1)", "1.0 meters",
1955            m2.format(args, 1, result, ignore, errorCode), TRUE);
1956
1957    args[0] = (int32_t)2;
1958    result.remove();
1959    assertEquals("offset-decimals format(1)", "2.0 meters",
1960            m2.format(args, 1, result, ignore, errorCode), TRUE);
1961
1962    args[0] = (double)2.5;
1963    result.remove();
1964    assertEquals("offset-decimals format(1)", "2.5 meters",
1965            m2.format(args, 1, result, ignore, errorCode), TRUE);
1966    errorCode.reset();
1967}
1968
1969void TestMessageFormat::TestArgIsPrefixOfAnother() {
1970    IcuTestErrorCode errorCode(*this, "TestArgIsPrefixOfAnother");
1971    // Ticket #11952
1972    MessageFormat mf1("{0,select,a{A}ab{AB}abc{ABC}other{?}}", Locale::getEnglish(), errorCode);
1973    Formattable args[3];
1974    FieldPosition ignore;
1975    UnicodeString result;
1976    args[0].setString("a");
1977    assertEquals("a", "A", mf1.format(args, 1, result, ignore, errorCode));
1978    args[0].setString("ab");
1979    assertEquals("ab", "AB", mf1.format(args, 1, result.remove(), ignore, errorCode));
1980    args[0].setString("abc");
1981    assertEquals("abc", "ABC", mf1.format(args, 1, result.remove(), ignore, errorCode));
1982
1983    // Ticket #12172
1984    MessageFormat mf2("{a} {aa} {aaa}", Locale::getEnglish(), errorCode);
1985    UnicodeString argNames[3] = { "a", "aa", "aaa" };
1986    args[0].setString("A");
1987    args[1].setString("AB");
1988    args[2].setString("ABC");
1989    assertEquals("a aa aaa", "A AB ABC", mf2.format(argNames, args, 3, result.remove(), errorCode));
1990
1991    // Ticket #12172
1992    MessageFormat mf3("{aa} {aaa}", Locale::getEnglish(), errorCode);
1993    assertEquals("aa aaa", "AB ABC", mf3.format(argNames + 1, args + 1, 2, result.remove(), errorCode));
1994}
1995
1996#endif /* #if !UCONFIG_NO_FORMATTING */
1997