1// © 2016 and later: Unicode, Inc. and others.
2// License & terms of use: http://www.unicode.org/copyright.html
3/***********************************************************************
4 * Copyright (c) 1997-2016, International Business Machines Corporation
5 * and others. All Rights Reserved.
6 ***********************************************************************/
7
8#include "unicode/utypes.h"
9
10#if !UCONFIG_NO_FORMATTING
11
12#include "numrgts.h"
13
14#include <float.h> // DBL_MIN, DBL_MAX
15#include <stdio.h>
16
17#include "unicode/dcfmtsym.h"
18#include "unicode/decimfmt.h"
19#include "unicode/locid.h"
20#include "unicode/resbund.h"
21#include "unicode/calendar.h"
22#include "unicode/datefmt.h"
23#include "unicode/ucurr.h"
24#include "cmemory.h"
25#include "putilimp.h"
26#include "uassert.h"
27
28class MyNumberFormatTest : public NumberFormat
29{
30public:
31
32    virtual UClassID getDynamicClassID(void) const;
33
34    virtual UnicodeString& format(    double            number,
35                    UnicodeString&        toAppendTo,
36                    FieldPositionIterator* posIter,
37                    UErrorCode& status) const
38    {
39        return NumberFormat::format(number, toAppendTo, posIter, status);
40    }
41
42    /* Just keep this here to make some of the compilers happy */
43    virtual UnicodeString& format(const Formattable& obj,
44                                  UnicodeString& toAppendTo,
45                                  FieldPosition& pos,
46                                  UErrorCode& status) const
47    {
48        return NumberFormat::format(obj, toAppendTo, pos, status);
49    }
50
51    /* Just use one of the format functions */
52    virtual UnicodeString& format(    double            /* number */,
53                    UnicodeString&        toAppendTo,
54                    FieldPosition&        /* pos */) const
55    {
56        toAppendTo = "";
57        return toAppendTo;
58    }
59
60    /*
61    public Number parse(String text, ParsePosition parsePosition)
62    { return new Integer(0); }
63    */
64
65    /* Just use one of the parse functions */
66    virtual void parse(    const UnicodeString&    /* text */,
67            Formattable&            result,
68            ParsePosition&          /* parsePosition */) const
69    {
70        result.setLong((int32_t)0);
71    }
72
73    virtual void parse(    const UnicodeString&    text,
74            Formattable&            result,
75            UErrorCode&            status) const
76    {
77        NumberFormat::parse(text, result, status);
78    }
79    virtual Format* clone() const
80    { return NULL; }
81
82    virtual UnicodeString& format(int32_t,
83                UnicodeString& foo,
84                FieldPosition&) const
85    { return foo.remove(); }
86
87    virtual UnicodeString& format(int64_t,
88                UnicodeString& foo,
89                FieldPosition&) const
90    { return foo.remove(); }
91
92    virtual void applyPattern(const UnicodeString&, UParseError&, UErrorCode&){
93    }
94};
95
96int32_t gMyNumberFormatTestClassID;
97UClassID MyNumberFormatTest::getDynamicClassID()  const
98{
99    return (UClassID)&gMyNumberFormatTestClassID;
100}
101
102
103// *****************************************************************************
104// class NumberFormatRegressionTest
105// *****************************************************************************
106
107#define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break
108
109void
110NumberFormatRegressionTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
111{
112    // if (exec) logln((UnicodeString)"TestSuite NumberFormatRegressionTest");
113    switch (index) {
114        CASE(0,Test4075713);
115        CASE(1,Test4074620);
116        CASE(2,Test4088161);
117        CASE(3,Test4087245);
118        CASE(4,Test4087535);
119        CASE(5,Test4088503);
120        CASE(6,Test4066646);
121        CASE(7,Test4059870);
122        CASE(8,Test4083018);
123        CASE(9,Test4071492);
124        CASE(10,Test4086575);
125        CASE(11,Test4068693);
126        CASE(12,Test4069754);
127        CASE(13,Test4087251);
128        CASE(14,Test4090489);
129        CASE(15,Test4090504);
130        CASE(16,Test4095713);
131        CASE(17,Test4092561);
132        CASE(18,Test4092480);
133        CASE(19,Test4087244);
134        CASE(20,Test4070798);
135        CASE(21,Test4071005);
136        CASE(22,Test4071014);
137        CASE(23,Test4071859);
138        CASE(24,Test4093610);
139        CASE(25,Test4098741);
140        CASE(26,Test4074454);
141        CASE(27,Test4099404);
142        CASE(28,Test4101481);
143        CASE(29,Test4052223);
144        CASE(30,Test4061302);
145        CASE(31,Test4062486);
146        CASE(32,Test4108738);
147        CASE(33,Test4106658);
148        CASE(34,Test4106662);
149        CASE(35,Test4114639);
150        CASE(36,Test4106664);
151        CASE(37,Test4106667);
152        CASE(38,Test4110936);
153        CASE(39,Test4122840);
154        CASE(40,Test4125885);
155        CASE(41,Test4134034);
156        CASE(42,Test4134300);
157        CASE(43,Test4140009);
158        CASE(44,Test4141750);
159        CASE(45,Test4145457);
160        CASE(46,Test4147295);
161        CASE(47,Test4147706);
162        CASE(48,Test4162198);
163        CASE(49,Test4162852);
164        CASE(50,Test4167494);
165        CASE(51,Test4170798);
166        CASE(52,Test4176114);
167        CASE(53,Test4179818);
168        CASE(54,Test4212072);
169        CASE(55,Test4216742);
170        CASE(56,Test4217661);
171        CASE(57,Test4161100);
172        CASE(58,Test4243011);
173        CASE(59,Test4243108);
174        CASE(60,TestJ691);
175        CASE(61,Test8199);
176        CASE(62,Test9109);
177        CASE(63,Test9780);
178        CASE(64,Test9677);
179        CASE(65,Test10361);
180
181        default: name = ""; break;
182    }
183}
184
185UBool
186NumberFormatRegressionTest::failure(UErrorCode status, const UnicodeString& msg, const Locale& l, UBool possibleDataError)
187{
188    if(U_FAILURE(status)) {
189        if (possibleDataError) {
190            dataerrln(UnicodeString("FAIL: ", "") + msg
191                  + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status), "") + UnicodeString(l.getName(),""));
192        } else {
193            errcheckln(status, UnicodeString("FAIL: ", "") + msg
194                  + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status), "") + UnicodeString(l.getName(),""));
195        }
196        return TRUE;
197    }
198
199    return FALSE;
200}
201
202UBool
203NumberFormatRegressionTest::failure(UErrorCode status, const UnicodeString& msg, const char *l, UBool possibleDataError)
204{
205    if(U_FAILURE(status)) {
206        if (possibleDataError) {
207            dataerrln(UnicodeString("FAIL: ", "") + msg
208                  + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status), "") + UnicodeString(l, ""));
209        } else {
210            errcheckln(status, UnicodeString("FAIL: ", "") + msg
211                  + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status), "") + UnicodeString(l, ""));
212        }
213        return TRUE;
214    }
215
216    return FALSE;
217}
218
219UBool
220NumberFormatRegressionTest::failure(UErrorCode status, const UnicodeString& msg, UBool possibleDataError)
221{
222    if(U_FAILURE(status)) {
223        if (possibleDataError) {
224            dataerrln(UnicodeString("FAIL: ", "") + msg
225                  + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status), ""));
226        } else {
227            errcheckln(status, UnicodeString("FAIL: ", "") + msg
228                  + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status), ""));
229        }
230        return TRUE;
231    }
232
233    return FALSE;
234}
235
236/**
237 * Convert Java-style strings with \u Unicode escapes into UnicodeString objects
238 */
239inline UnicodeString str(const char *input)
240{
241  return CharsToUnicodeString(input);
242}
243
244/* @bug 4075713
245 * NumberFormat.equals comparing with null should always return false.
246 */
247// {sfb} kind of silly in C++, just checking for new success
248void NumberFormatRegressionTest::Test4075713(void)
249{
250    //try {
251        MyNumberFormatTest *tmp = new MyNumberFormatTest();
252        if(tmp != NULL)
253            logln("NumberFormat.equals passed");
254    /*} catch (NullPointerException e) {
255        errln("(new MyNumberFormatTest()).equals(null) throws unexpected exception");
256    }*/
257
258    delete tmp;
259}
260
261/* @bug 4074620
262 * NumberFormat.equals comparing two obj equal even the setGroupingUsed
263 * flag is different.
264 */
265void NumberFormatRegressionTest::Test4074620(void)
266{
267
268    MyNumberFormatTest *nf1 = new MyNumberFormatTest();
269    MyNumberFormatTest *nf2 = new MyNumberFormatTest();
270
271    nf1->setGroupingUsed(FALSE);
272    nf2->setGroupingUsed(TRUE);
273
274    if(nf1 == nf2)
275        errln("Test for bug 4074620 failed");
276    else
277        logln("Test for bug 4074620 passed.");
278
279    delete nf1;
280    delete nf2;
281}
282
283
284/* @bug 4088161
285 * DecimalFormat.format() incorrectly uses maxFractionDigits setting.
286 */
287
288void NumberFormatRegressionTest::Test4088161 (void)
289{
290    UErrorCode status = U_ZERO_ERROR;
291    DecimalFormat *df = new DecimalFormat(status);
292    if (!failure(status, "new DecimalFormat", "")) {
293        double d = 100;
294        df->setMinimumFractionDigits(0);
295        df->setMaximumFractionDigits(16);
296        UnicodeString sBuf1;
297        FieldPosition fp1(FieldPosition::DONT_CARE);
298        logln(UnicodeString("d = ") + d);
299        logln(UnicodeString("maxFractionDigits = ") + df->getMaximumFractionDigits());
300
301        logln(" format(d) = '" + df->format(d, sBuf1, fp1) + "'");
302        df->setMaximumFractionDigits(17);
303        UnicodeString sBuf2;
304        FieldPosition fp2(FieldPosition::DONT_CARE);
305        logln(UnicodeString("maxFractionDigits = ") + df->getMaximumFractionDigits());
306        sBuf2 = df->format(d, sBuf2, fp2);
307        if(sBuf2 != "100")
308            errln(" format(d) = '" + sBuf2 + "'");
309    }
310
311    delete df;
312}
313
314/* @bug 4087245
315 * DecimalFormatSymbols should be cloned in the ctor DecimalFormat.
316 * DecimalFormat(String, DecimalFormatSymbols).
317 */
318void NumberFormatRegressionTest::Test4087245 (void)
319{
320    UErrorCode status = U_ZERO_ERROR;
321    DecimalFormatSymbols *symbols = new DecimalFormatSymbols(status);
322    failure(status, "new DecimalFormatSymbols", "");
323    // {sfb} One note about this test: if you pass in a pointer
324    // to the symbols, they are adopted and this test will fail,
325    // even though that is the correct behavior.  To test the cloning
326    // of the symbols, it is necessary to pass in a reference to the symbols
327    DecimalFormat *df = new DecimalFormat("#,##0.0", *symbols, status);
328    failure(status, "new DecimalFormat with symbols", "");
329    int32_t n = 123;
330    UnicodeString buf1;
331    UnicodeString buf2;
332    FieldPosition pos(FieldPosition::DONT_CARE);
333    logln(UnicodeString("format(") + n + ") = " +
334        df->format(n, buf1, pos));
335    symbols->setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, UnicodeString((UChar)0x70)); // change value of field
336    logln(UnicodeString("format(") + n + ") = " +
337        df->format(n, buf2, pos));
338    if(buf1 != buf2)
339        errln("Test for bug 4087245 failed");
340
341    delete df;
342    delete symbols;
343}
344
345/* @bug 4087535
346 * DecimalFormat.format() incorrectly formats 0.0
347 */
348void NumberFormatRegressionTest::Test4087535 (void)
349{
350    UErrorCode status = U_ZERO_ERROR;
351    DecimalFormat *df = new DecimalFormat(status);
352    if (U_FAILURE(status)) {
353        dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
354        return;
355    }
356    df->setMinimumIntegerDigits(0);
357
358    double n = 0;
359    UnicodeString buffer;
360    FieldPosition pos(FieldPosition::DONT_CARE);
361    buffer = df->format(n, buffer, pos);
362    if (buffer.length() == 0)
363        errln(/*n + */": '" + buffer + "'");
364    n = 0.1;
365    buffer = df->format(n, buffer, pos);
366    if (buffer.length() == 0)
367        errln(/*n + */": '" + buffer + "'");
368
369    delete df;
370}
371
372/* @bug 4088503
373 * DecimalFormat.format fails when groupingSize is set to 0.
374 */
375// {sfb} how do I tell if this worked? --> FieldPosition doesn't change ??
376void NumberFormatRegressionTest::Test4088503 (void)
377{
378    UErrorCode status = U_ZERO_ERROR;
379    DecimalFormat *df = new DecimalFormat(status);
380    if (U_FAILURE(status)) {
381        dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
382        return;
383    }
384    df->setGroupingSize(0);
385    UnicodeString sBuf;
386    FieldPosition fp(FieldPosition::DONT_CARE);
387    //try {
388        logln(df->format((int32_t)123, sBuf, fp));
389        //if(fp == FieldPosition(FieldPosition::DONT_CARE))
390        //    errln("Test for bug 4088503 failed.");
391    /*} catch (Exception foo) {
392        errln("Test for bug 4088503 failed.");
393    }*/
394    delete df;
395
396}
397/* @bug 4066646
398 * NumberFormat.getCurrencyInstance is wrong.
399 */
400void NumberFormatRegressionTest::Test4066646 (void)
401{
402    assignFloatValue(2.04f);
403    assignFloatValue(2.03f);
404    assignFloatValue(2.02f);
405    assignFloatValue(0.0f);
406}
407
408float
409NumberFormatRegressionTest::assignFloatValue(float returnfloat)
410{
411    logln(UnicodeString(" VALUE ") + returnfloat);
412    UErrorCode status = U_ZERO_ERROR;
413    NumberFormat *nfcommon =  NumberFormat::createCurrencyInstance(Locale::getUS(), status);
414    if (failure(status, "NumberFormat::createCurrencyInstance", Locale::getUS(), TRUE)){
415        delete nfcommon;
416        return returnfloat;
417    }
418    nfcommon->setGroupingUsed(FALSE);
419
420    UnicodeString stringValue;
421    stringValue = nfcommon->format(returnfloat, stringValue);
422    logln(" DISPLAYVALUE " + stringValue);
423    Formattable result;
424    nfcommon->parse(stringValue, result, status);
425    failure(status, "nfcommon->parse", Locale::getUS());
426    float floatResult = (float) (result.getType() == Formattable::kDouble
427                                        ? result.getDouble() : result.getLong());
428    if( uprv_fabs(floatResult - returnfloat) > 0.0001)
429    //String stringValue = nfcommon.format(returnfloat).substring(1);
430    //if (Float.valueOf(stringValue).floatValue() != returnfloat)
431        errln(UnicodeString("FAIL: expected ") + returnfloat + ", got " + floatResult + " (" + stringValue+")");
432
433    delete nfcommon;
434    return returnfloat;
435} // End Of assignFloatValue()
436
437/* @bug 4059870
438 * DecimalFormat throws exception when parsing "0"
439 */
440void NumberFormatRegressionTest::Test4059870(void)
441{
442    UErrorCode status = U_ZERO_ERROR;
443    DecimalFormat *format = new DecimalFormat("00", status);
444    failure(status, "new Decimalformat", Locale::getUS());
445    //try {
446        Formattable result;
447        UnicodeString str;
448        format->parse(UnicodeString("0"), result, status);
449        failure(status, "format->parse", Locale::getUS());
450
451    /*}
452    catch (Exception e) {
453        errln("Test for bug 4059870 failed : " + e);
454    }*/
455
456    delete format;
457}
458/* @bug 4083018
459 * DecimalFormatSymbol.equals should always return false when
460 * comparing with null.
461 */
462// {sfb} this is silly in C++
463void NumberFormatRegressionTest::Test4083018 (void)
464{
465    UErrorCode status = U_ZERO_ERROR;
466    DecimalFormatSymbols *dfs = new DecimalFormatSymbols(status);
467    failure(status, "new DecimalFormatSymbols", Locale::getUS());
468    //try {
469        if (dfs != NULL)
470            logln("Test Passed!");
471        else
472            errln("Test for bug 4083018 failed");
473    /*} catch (Exception foo) {
474        errln("Test for bug 4083018 failed => Message : " + foo.getMessage());
475    }*/
476
477    delete dfs;
478}
479
480/* @bug 4071492
481 * DecimalFormat does not round up correctly.
482 */
483void NumberFormatRegressionTest::Test4071492 (void)
484{
485    double x = 0.00159999;
486    UErrorCode status = U_ZERO_ERROR;
487    NumberFormat *nf = NumberFormat::createInstance(status);
488    if (failure(status, "NumberFormat::createInstance", Locale::getUS(), TRUE)) {
489        delete nf;
490        return;
491    }
492    nf->setMaximumFractionDigits(4);
493    UnicodeString out;
494    FieldPosition pos(FieldPosition::DONT_CARE);
495    out = nf->format(x, out, pos);
496    logln("0.00159999 formats with 4 fractional digits to " + out);
497    UnicodeString expected("0.0016");
498    if (out != expected)
499        errln("FAIL: Expected " + expected);
500
501    delete nf;
502}
503
504/* @bug 4086575
505 * A space as a group separator for localized pattern causes
506 * wrong format.  WorkAround : use non-breaking space.
507 */
508void NumberFormatRegressionTest::Test4086575(void)
509{
510    UErrorCode status = U_ZERO_ERROR;
511    NumberFormat *nf1 = NumberFormat::createInstance(Locale::getFrance(), status);
512
513    // TODO: There is not a good way to find out that the creation of this number format has
514    // failed. Major rewiring of format construction proposed.
515    if(U_FAILURE(status)) {
516      dataerrln("Something is wrong with French number format - it should not fallback. Exitting - %s", u_errorName(status));
517      delete nf1;
518      return;
519    }
520    failure(status, "NumberFormat::createInstance", Locale::getFrance());
521
522    // C++ workaround to make sure cast works
523    DecimalFormat *nf = dynamic_cast<DecimalFormat *>(nf1);
524    if(nf == NULL) {
525        errln("NumberFormat::createInstance returned incorrect type.");
526        return;
527    }
528
529    UnicodeString temp;
530    logln("nf toPattern1: " + nf->toPattern(temp));
531    logln("nf toLocPattern1: " + nf->toLocalizedPattern(temp));
532
533    // No group separator
534    logln("...applyLocalizedPattern ###,00;(###,00) ");
535    nf->applyLocalizedPattern(UnicodeString("###,00;(###,00)"), status);
536    failure(status, "nf->applyLocalizedPattern", Locale::getFrance());
537    logln("nf toPattern2: " + nf->toPattern(temp));
538    logln("nf toLocPattern2: " + nf->toLocalizedPattern(temp));
539
540    FieldPosition pos(FieldPosition::DONT_CARE);
541    logln("nf: " + nf->format((int32_t)1234, temp, pos)); // 1234,00
542    logln("nf: " + nf->format((int32_t)-1234, temp, pos)); // (1234,00)
543
544    // Space as group separator
545
546    logln("...applyLocalizedPattern # ###,00;(# ###,00) ");
547    // nbsp = \u00a0
548    //nf->applyLocalizedPattern("#\u00a0###,00;(#\u00a0###,00)");
549    UChar patChars[] = {
550             0x23, 0x00a0, 0x23, 0x23, 0x23, 0x2c, 0x30, 0x30, 0x3b,
551        0x28, 0x23, 0x00a0, 0x23, 0x23, 0x23, 0x2c, 0x30, 0x30, 0x29
552    };
553    UnicodeString pat(patChars, 19, 19);
554    nf->applyLocalizedPattern(pat, status);
555    failure(status, "nf->applyLocalizedPattern", Locale::getFrance());
556    logln("nf toPattern2: " + nf->toPattern(temp));
557    logln("nf toLocPattern2: " + nf->toLocalizedPattern(temp));
558    UnicodeString buffer;
559    buffer = nf->format((int32_t)1234, buffer, pos);
560    //if (buffer != UnicodeString("1\u00a0234,00"))
561    UChar c[] = {
562        0x31, 0x00a0, 0x32, 0x33, 0x34, 0x2c, 0x30, 0x30
563    };
564    UnicodeString cc(c, 8, 8);
565    if (buffer != cc)
566        errln("nf : " + buffer); // Expect 1 234,00
567
568    buffer.remove();
569    buffer = nf->format((int32_t)-1234, buffer, pos);
570    UChar c1[] = {
571        0x28, 0x31, 0x00a0, 0x32, 0x33, 0x34, 0x2c, 0x30, 0x30, 0x29
572    };
573    UnicodeString cc1(c1, 10, 10);
574    if (buffer != cc1)
575        errln("nf : " + buffer); // Expect (1 234,00)
576
577    // Erroneously prints:
578    // 1234,00 ,
579    // (1234,00 ,)
580
581    delete nf1;
582}
583/* @bug 4068693
584 * DecimalFormat.parse returns wrong value
585 */
586// {sfb} slightly converted into a round-trip test, since in C++
587// there is no Double.toString()
588void NumberFormatRegressionTest::Test4068693(void)
589{
590    logln("----- Test Application -----");
591    ParsePosition pos(0);
592    UErrorCode status = U_ZERO_ERROR;
593    DecimalFormat *df = new DecimalFormat(status);
594    if(U_FAILURE(status)) {
595      errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
596      delete df;
597      return;
598    }
599    failure(status, "new DecimalFormat");
600    Formattable d;
601    //Double d = (Double)df.parse("123.55456", pos=new ParsePosition(0));
602    df->parse(UnicodeString("123.55456"), d, pos);
603    //if (!d.toString().equals("123.55456")) {
604    UnicodeString dstr;
605    df->setMaximumFractionDigits(999);
606    df->setMaximumIntegerDigits(999);
607    FieldPosition fp(FieldPosition::DONT_CARE);
608    dstr = df->format(d.getDouble(), dstr, fp);
609    if (dstr != UnicodeString("123.55456")) {
610        errln(UnicodeString("Result -> ") + d.getDouble());
611    }
612
613    delete df;
614}
615
616/* @bug 4069754, 4067878
617 * null pointer thrown when accessing a deserialized DecimalFormat
618 * object.
619 */
620// {sfb} doesn't apply in C++
621void NumberFormatRegressionTest::Test4069754(void)
622{
623/*    try {
624        myformat it = new myformat();
625        logln(it.Now());
626        FileOutputStream ostream = new FileOutputStream("t.tmp");
627        ObjectOutputStream p = new ObjectOutputStream(ostream);
628        p.writeObject(it);
629        ostream.close();
630        logln("Saved ok.");
631
632        FileInputStream istream = new FileInputStream("t.tmp");
633        ObjectInputStream p2 = new ObjectInputStream(istream);
634        myformat it2 = (myformat)p2.readObject();
635        logln(it2.Now());
636        istream.close();
637        logln("Loaded ok.");
638    } catch (Exception foo) {
639        errln("Test for bug 4069754 or 4057878 failed => Exception: " + foo.getMessage());
640    }
641*/}
642
643/* @bug 4087251
644 * DecimalFormat.applyPattern(String) allows illegal patterns
645 */
646void NumberFormatRegressionTest::Test4087251 (void)
647{
648    UErrorCode status = U_ZERO_ERROR;
649    DecimalFormat *df = new DecimalFormat(status);
650    if(U_FAILURE(status)) {
651      errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
652      delete df;
653      return;
654    }
655    failure(status, "new DecimalFormat");
656    //try {
657        df->applyPattern(UnicodeString("#.#.#"), status);
658        if( ! U_FAILURE(status))
659            errln("df->applyPattern with illegal pattern didn't fail");
660        UnicodeString temp;
661        logln("toPattern() returns \"" + df->toPattern(temp) + "\"");
662        //errln("applyPattern(\"#.#.#\") doesn't throw IllegalArgumentException");
663    /*} catch (IllegalArgumentException e) {
664        logln("Caught Illegal Argument Error !");
665    }*/
666    // Second test; added 5/11/98 when reported to fail on 1.2b3
667    //try {
668        df->applyPattern("#0.0#0#0", status);
669        if( ! U_FAILURE(status))
670            errln("df->applyPattern with illegal pattern didn't fail");
671        logln("toPattern() returns \"" + df->toPattern(temp) + "\"");
672        //errln("applyPattern(\"#0.0#0#0\") doesn't throw IllegalArgumentException");
673    /*} catch (IllegalArgumentException e) {
674        logln("Ok - IllegalArgumentException for #0.0#0#0");
675    }*/
676
677    delete df;
678}
679
680/* @bug 4090489
681 * DecimalFormat.format() loses precision
682 */
683void NumberFormatRegressionTest::Test4090489 (void)
684{
685// {sfb} sprintf doesn't correctly handle the double, so there is nothing
686// that NumberFormat can do.  For some reason, it does not format the last 1.
687
688/*    UErrorCode status = U_ZERO_ERROR;
689    DecimalFormat *df = new DecimalFormat(status);
690    failure(status, "new DecimalFormat");
691    df->setMinimumFractionDigits(10);
692    df->setMaximumFractionDigits(999);
693    df->setGroupingUsed(FALSE);
694    double d = 1.000000000000001E7;
695    //BigDecimal bd = new BigDecimal(d);
696    UnicodeString sb;
697    FieldPosition fp(FieldPosition::DONT_CARE);
698    logln(UnicodeString("d = ") + d);
699    //logln("BigDecimal.toString():  " + bd.toString());
700    df->format(d, sb, fp);
701    if (sb != "10000000.0000000100") {
702        errln("DecimalFormat.format(): " + sb);
703    }
704*/
705}
706
707/* @bug 4090504
708 * DecimalFormat.format() loses precision
709 */
710void NumberFormatRegressionTest::Test4090504 (void)
711{
712    double d = 1;
713    logln(UnicodeString("d = ") + d);
714    UErrorCode status = U_ZERO_ERROR;
715    DecimalFormat *df = new DecimalFormat(status);
716    if(U_FAILURE(status)) {
717      errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
718      delete df;
719      return;
720    }
721    failure(status, "new DecimalFormat");
722    UnicodeString sb;
723    FieldPosition fp(FieldPosition::DONT_CARE);
724    //try {
725        for (int i = 17; i <= 20; i++) {
726            df->setMaximumFractionDigits(i);
727            //sb = new StringBuffer("");
728            fp.setField(0);
729            logln(UnicodeString("  getMaximumFractionDigits() = ") + i);
730            logln(UnicodeString("  formated: ") + df->format(d, sb, fp));
731        }
732    /*} catch (Exception foo) {
733        errln("Bug 4090504 regression test failed. Message : " + foo.getMessage());
734    }*/
735
736    delete df;
737}
738/* @bug 4095713
739 * DecimalFormat.parse(String str, ParsePosition pp) loses precision
740 */
741void NumberFormatRegressionTest::Test4095713 (void)
742{
743    UErrorCode status = U_ZERO_ERROR;
744    DecimalFormat *df = new DecimalFormat(status);
745    if(U_FAILURE(status)) {
746      errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
747      delete df;
748      return;
749    }
750    failure(status, "new DecimalFormat");
751    UnicodeString str("0.1234");
752    double d1 = 0.1234;
753    //Double d1 = new Double(str);
754    //Double d2 = (Double) df.parse(str, new ParsePosition(0));
755    Formattable d2;
756    ParsePosition pp(0);
757    df->parse(str, d2, pp);
758    logln(UnicodeString("") + d1);
759    if (d2.getDouble() != d1)
760        errln(UnicodeString("Bug 4095713 test failed, new double value : ") + d2.getDouble());
761    delete df;
762}
763
764/* @bug 4092561
765 * DecimalFormat.parse() fails when multiplier is not set to 1
766 */
767// {sfb} not sure what to do with this one
768void NumberFormatRegressionTest::Test4092561 (void)
769{
770    UErrorCode status = U_ZERO_ERROR;
771    DecimalFormat *df = new DecimalFormat(status);
772    if(U_FAILURE(status)) {
773      errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
774      delete df;
775      return;
776    }
777    failure(status, "new DecimalFormat");
778
779    // {sfb} going to cheat here and use sprintf ??
780
781    /*UnicodeString str = Long.toString(Long.MIN_VALUE);
782    logln("Long.MIN_VALUE : " + df.parse(str, new ParsePosition(0)).toString());
783    df.setMultiplier(100);
784    Number num = df.parse(str, new ParsePosition(0));
785    if (num.doubleValue() != -9.223372036854776E16)
786        errln("Bug 4092561 test failed when multiplier is set to not 1.");
787*/
788    delete df;
789}
790
791/* @bug 4092480
792 * DecimalFormat: Negative format ignored.
793 */
794void NumberFormatRegressionTest::Test4092480 (void)
795{
796    UErrorCode status = U_ZERO_ERROR;
797    DecimalFormat *dfFoo = new DecimalFormat(UnicodeString("000"), status);
798    if(U_FAILURE(status)) {
799      errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
800      delete dfFoo;
801      return;
802    }
803    failure(status, "new DecimalFormat");
804
805    //try {
806        dfFoo->applyPattern("0000;-000", status);
807        failure(status, "dfFoo->applyPattern");
808        UnicodeString temp;
809        if (dfFoo->toPattern(temp) != UnicodeString("#0000"))
810            errln("dfFoo.toPattern : " + dfFoo->toPattern(temp));
811        FieldPosition pos(FieldPosition::DONT_CARE);
812        logln(dfFoo->format((int32_t)42, temp, pos));
813        logln(dfFoo->format((int32_t)-42, temp, pos));
814        dfFoo->applyPattern("000;-000", status);
815        failure(status, "dfFoo->applyPattern");
816        if (dfFoo->toPattern(temp) != UnicodeString("#000"))
817            errln("dfFoo.toPattern : " + dfFoo->toPattern(temp));
818        logln(dfFoo->format((int32_t)42,temp, pos));
819        logln(dfFoo->format((int32_t)-42, temp, pos));
820
821        dfFoo->applyPattern("000;-0000", status);
822        failure(status, "dfFoo->applyPattern");
823        if (dfFoo->toPattern(temp) != UnicodeString("#000"))
824            errln("dfFoo.toPattern : " + dfFoo->toPattern(temp));
825        logln(dfFoo->format((int32_t)42, temp, pos));
826        logln(dfFoo->format((int32_t)-42, temp, pos));
827
828        dfFoo->applyPattern("0000;-000", status);
829        failure(status, "dfFoo->applyPattern");
830        if (dfFoo->toPattern(temp) != UnicodeString("#0000"))
831            errln("dfFoo.toPattern : " + dfFoo->toPattern(temp));
832        logln(dfFoo->format((int32_t)42, temp, pos));
833        logln(dfFoo->format((int32_t)-42, temp, pos));
834    /*} catch (Exception foo) {
835        errln("Message " + foo.getMessage());
836    }*/
837
838    delete dfFoo;
839}
840/* @bug 4087244
841 * NumberFormat.getCurrencyInstance() produces format that uses
842 * decimal separator instead of monetary decimal separator.
843 *
844 * Rewrote this test not to depend on the actual pattern.  Pattern should
845 * never contain the monetary separator!  Decimal separator in pattern is
846 * interpreted as monetary separator if currency symbol is seen!
847 */
848void NumberFormatRegressionTest::Test4087244 (void) {
849    UErrorCode status = U_ZERO_ERROR;
850    char loc[256] = {0};
851    uloc_canonicalize("pt_PT_PREEURO", loc, 256, &status);
852    Locale *de = new Locale(loc);
853    NumberFormat *nf = NumberFormat::createCurrencyInstance(*de, status);
854    if(U_FAILURE(status)) {
855      dataerrln("Error creating DecimalFormat: %s", u_errorName(status));
856      delete nf;
857      return;
858    }
859    DecimalFormat *df = dynamic_cast<DecimalFormat *>(nf);
860    if(df == NULL) {
861        errln("expected DecimalFormat!");
862        return;
863    }
864    const DecimalFormatSymbols *sym = df->getDecimalFormatSymbols();
865    UnicodeString decSep = sym->getSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol);
866    UnicodeString monSep = sym->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol);
867    if (decSep == monSep) {
868        errln("ERROR in test: want decimal sep != monetary sep");
869        return;
870    }
871    df->setMinimumIntegerDigits(1);
872    df->setMinimumFractionDigits(2);
873    UnicodeString str;
874    FieldPosition pos;
875    df->format(1.23, str, pos);
876    UnicodeString monStr("1x23");
877    monStr.replace((int32_t)1, 1, monSep);
878    UnicodeString decStr("1x23");
879    decStr.replace((int32_t)1, 1, decSep);
880    if (str.indexOf(monStr) >= 0 && str.indexOf(decStr) < 0) {
881        logln(UnicodeString("OK: 1.23 -> \"") + str + "\" contains \"" +
882              monStr + "\" and not \"" + decStr + '"');
883    } else {
884        errln(UnicodeString("FAIL: 1.23 -> \"") + str + "\", should contain \"" +
885              monStr +
886              "\" and not \"" + decStr + '"');
887    }
888    delete de;
889    delete nf;
890}
891/* @bug 4070798
892 * Number format data rounding errors for locale FR
893 */
894void NumberFormatRegressionTest::Test4070798 (void)
895{
896    NumberFormat *formatter;
897    UnicodeString tempString;
898
899    /* User error :
900    String expectedDefault = "-5\u00a0789,987";
901    String expectedCurrency = "5\u00a0789,98\u00a0F";
902    String expectedPercent = "-578\u00a0998%";
903    */
904    UChar chars1 [] = {
905        0x2d, 0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x38, 0x38
906    };
907    UChar chars2 [] = {
908        0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x39, 0x00a0, 0x46
909    };
910    UChar chars3 [] = {
911        0x2d, 0x35, 0x37, 0x38, 0x00a0, 0x39, 0x39, 0x39, 0x00a0, 0x25
912    };
913    UnicodeString expectedDefault(chars1, 10, 10);
914    UnicodeString expectedCurrency(chars2, 10, 10);
915    UnicodeString expectedPercent(chars3, 10, 10);
916
917    UErrorCode status = U_ZERO_ERROR;
918    char loc[256]={0};
919    int len = uloc_canonicalize("fr_FR_PREEURO", loc, 256, &status);
920    (void)len;  // Suppress set but not used warning.
921    formatter = NumberFormat::createInstance(Locale(loc), status);
922    if(U_FAILURE(status)) {
923      dataerrln("Error creating DecimalFormat: %s", u_errorName(status));
924      delete formatter;
925      return;
926    }
927    failure(status, "NumberFormat::createInstance", loc);
928    tempString = formatter->format (-5789.9876, tempString);
929
930    if (tempString == expectedDefault) {
931        logln ("Bug 4070798 default test passed.");
932    } else {
933        errln(UnicodeString("Failed:") +
934        " Expected " + expectedDefault +
935        " Received " + tempString );
936    }
937    delete formatter;
938    len = uloc_canonicalize("fr_FR_PREEURO", loc, 256, &status);
939    formatter = NumberFormat::createCurrencyInstance(loc, status);
940    failure(status, "NumberFormat::createCurrencyInstance", loc);
941    tempString.remove();
942    tempString = formatter->format( 5789.9876, tempString );
943
944    if (tempString == expectedCurrency) {
945        logln ("Bug 4070798 currency test passed.");
946    } else {
947        errln(UnicodeString("Failed:") +
948        " Expected " + expectedCurrency +
949        " Received " + tempString );
950    }
951    delete formatter;
952
953    uloc_canonicalize("fr_FR_PREEURO", loc, 256, &status);
954    formatter = NumberFormat::createPercentInstance(Locale(loc), status);
955    failure(status, "NumberFormat::createPercentInstance", loc);
956    tempString.remove();
957    tempString = formatter->format (-5789.9876, tempString);
958
959    if (tempString == expectedPercent) {
960        logln ("Bug 4070798 percentage test passed.");
961    } else {
962        errln(UnicodeString("Failed:") +
963        " Expected " + expectedPercent +
964        " Received " + tempString );
965    }
966
967    delete formatter;
968}
969/* @bug 4071005
970 * Data rounding errors for French (Canada) locale
971 */
972void NumberFormatRegressionTest::Test4071005 (void)
973{
974    NumberFormat *formatter;
975    UnicodeString tempString;
976    /* User error :
977    String expectedDefault = "-5\u00a0789,987";
978    String expectedCurrency = "5\u00a0789,98\u00a0$";
979    String expectedPercent = "-578\u00a0998%";
980    */
981    UChar chars1 [] = {
982        0x2d, 0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x38, 0x38
983    };
984    UChar chars2 [] = {
985        0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x39, 0x00a0, 0x24
986    };
987    UChar chars3 [] = {
988        0x2d, 0x35, 0x37, 0x38, 0x00a0, 0x39, 0x39, 0x39, 0x00a0, 0x25
989    };
990    UnicodeString expectedDefault(chars1, 10, 10);
991    UnicodeString expectedCurrency(chars2, 10, 10);
992    UnicodeString expectedPercent(chars3, 10, 10);
993
994    UErrorCode status = U_ZERO_ERROR;
995    formatter = NumberFormat::createInstance(Locale::getCanadaFrench(), status);
996    if (failure(status, "NumberFormat::createInstance", Locale::getCanadaFrench(), TRUE)){
997        delete formatter;
998        return;
999    };
1000    tempString = formatter->format (-5789.9876, tempString);
1001
1002    if (tempString == expectedDefault) {
1003        logln ("Bug 4071005 default test passed.");
1004    } else {
1005        errln(UnicodeString("Failed:") +
1006        " Expected " + expectedDefault +
1007        " Received " + tempString );
1008    }
1009    delete formatter;
1010
1011    formatter = NumberFormat::createCurrencyInstance(Locale::getCanadaFrench(), status);
1012    failure(status, "NumberFormat::createCurrencyInstance", Locale::getCanadaFrench());
1013    tempString.remove();
1014    tempString = formatter->format( 5789.9876, tempString );
1015
1016    if (tempString == expectedCurrency) {
1017        logln ("Bug 4071005 currency test assed.");
1018    } else {
1019        errln(UnicodeString("Failed:") +
1020        " Expected " + expectedCurrency +
1021        " Received " + tempString );
1022    }
1023    delete formatter;
1024
1025    formatter = NumberFormat::createPercentInstance(Locale::getCanadaFrench(), status);
1026    failure(status, "NumberFormat::createPercentInstance", Locale::getCanadaFrench());
1027    tempString.remove();
1028    tempString = formatter->format (-5789.9876, tempString);
1029
1030    if (tempString == expectedPercent) {
1031        logln ("Bug 4071005 percentage test passed.");
1032    } else {
1033        errln(UnicodeString("Failed:") +
1034        " Expected " + expectedPercent +
1035        " Received " + tempString );
1036    }
1037
1038    delete formatter;
1039}
1040
1041/* @bug 4071014
1042 * Data rounding errors for German (Germany) locale
1043 */
1044void NumberFormatRegressionTest::Test4071014 (void)
1045{
1046    NumberFormat *formatter;
1047    UnicodeString tempString;
1048    /* user error :
1049    String expectedDefault = "-5.789,987";
1050    String expectedCurrency = "5.789,98 DM";
1051    String expectedPercent = "-578.998%";
1052    */
1053    UnicodeString expectedDefault("-5.789,988");
1054    UnicodeString expectedCurrency("5.789,99\\u00A0DM");
1055    UnicodeString expectedPercent("-578.999\\u00A0%");
1056
1057    expectedCurrency = expectedCurrency.unescape();
1058    expectedPercent = expectedPercent.unescape();
1059
1060    UErrorCode status = U_ZERO_ERROR;
1061    char loc[256]={0};
1062    uloc_canonicalize("de_DE_PREEURO", loc, 256, &status);
1063    formatter = NumberFormat::createInstance(Locale(loc), status);
1064    if (failure(status, "NumberFormat::createInstance", loc, TRUE)){
1065        delete formatter;
1066        return;
1067    }
1068    tempString.remove();
1069    tempString = formatter->format (-5789.9876, tempString);
1070
1071    if (tempString == expectedDefault) {
1072        logln ("Bug 4071014 default test passed.");
1073    } else {
1074        errln(UnicodeString("Failed:") +
1075        " Expected " + expectedDefault +
1076        " Received " + tempString );
1077    }
1078    delete formatter;
1079    uloc_canonicalize("de_DE_PREEURO", loc, 256, &status);
1080    formatter = NumberFormat::createCurrencyInstance(Locale(loc), status);
1081    failure(status, "NumberFormat::createCurrencyInstance", loc);
1082    tempString.remove();
1083    tempString = formatter->format( 5789.9876, tempString );
1084
1085    if (tempString == expectedCurrency) {
1086        logln ("Bug 4071014 currency test assed.");
1087    } else {
1088        errln(UnicodeString("Failed:") +
1089        " Expected " + expectedCurrency +
1090        " Received " + tempString );
1091    }
1092    delete formatter;
1093
1094    formatter = NumberFormat::createPercentInstance(Locale::getGermany(), status);
1095    failure(status, "NumberFormat::createPercentInstance", Locale::getGermany());
1096    tempString.remove();
1097    tempString = formatter->format (-5789.9876, tempString);
1098
1099    if (tempString == expectedPercent) {
1100        logln ("Bug 4071014 percentage test passed.");
1101    } else {
1102        errln(UnicodeString("Failed:") +
1103        " Expected " + expectedPercent +
1104        " Received " + tempString );
1105    }
1106
1107    delete formatter;
1108}
1109/* @bug 4071859
1110 * Data rounding errors for Italian locale number formats
1111 */
1112void NumberFormatRegressionTest::Test4071859 (void)
1113{
1114    NumberFormat *formatter;
1115    UnicodeString tempString;
1116    /* user error :
1117    String expectedDefault = "-5.789,987";
1118    String expectedCurrency = "-L.\\u00A05.789,98";
1119    String expectedPercent = "-578.998%";
1120    */
1121    UnicodeString expectedDefault("-5.789,988");
1122    UnicodeString expectedCurrency("-ITL\\u00A05.790", -1, US_INV);
1123    UnicodeString expectedPercent("-578.999%");
1124    expectedCurrency = expectedCurrency.unescape();
1125
1126    UErrorCode status = U_ZERO_ERROR;
1127    char loc[256]={0};
1128    uloc_canonicalize("it_IT_PREEURO", loc, 256, &status);
1129    formatter = NumberFormat::createInstance(Locale(loc), status);
1130    if (failure(status, "NumberFormat::createNumberInstance", TRUE)){
1131        delete formatter;
1132        return;
1133    };
1134    tempString = formatter->format (-5789.9876, tempString);
1135
1136    if (tempString == expectedDefault) {
1137        logln ("Bug 4071859 default test passed.");
1138    } else {
1139        errln(UnicodeString("Failed:") +
1140        " Expected " + expectedDefault +
1141        " Received " + tempString );
1142    }
1143    delete formatter;
1144    uloc_canonicalize("it_IT_PREEURO", loc, 256, &status);
1145    formatter = NumberFormat::createCurrencyInstance(Locale(loc), status);
1146    failure(status, "NumberFormat::createCurrencyInstance");
1147    tempString.remove();
1148    tempString = formatter->format( -5789.9876, tempString );
1149
1150    if (tempString == expectedCurrency) {
1151        logln ("Bug 4071859 currency test assed.");
1152    } else {
1153        errln(UnicodeString("Failed:") +
1154        " Expected " + expectedCurrency +
1155        " Received " + tempString );
1156    }
1157    delete formatter;
1158    uloc_canonicalize("it_IT_PREEURO", loc, 256, &status);
1159    formatter = NumberFormat::createPercentInstance(Locale(loc), status);
1160    failure(status, "NumberFormat::createPercentInstance");
1161    tempString.remove();
1162    tempString = formatter->format (-5789.9876, tempString);
1163
1164    if (tempString == expectedPercent) {
1165        logln ("Bug 4071859 percentage test passed.");
1166    } else {
1167        errln(UnicodeString("Failed:") +
1168        " Expected " + expectedPercent +
1169        " Received " + tempString );
1170    }
1171
1172    delete formatter;
1173}
1174/* @bug 4071859
1175 * Test rounding for nearest even.
1176 */
1177void NumberFormatRegressionTest::Test4093610(void)
1178{
1179    UErrorCode status = U_ZERO_ERROR;
1180    DecimalFormat *df = new DecimalFormat("#0.#", status);
1181    if (!failure(status, "new DecimalFormat")) {
1182        UnicodeString s("12.4");
1183        roundingTest(df, 12.35, s);
1184        roundingTest(df, 12.45, s);
1185        s = "12.5";
1186        roundingTest(df, 12.452,s);
1187        s = "12.6";
1188        roundingTest(df, 12.55, s);
1189        roundingTest(df, 12.65, s);
1190        s = "12.7";
1191        roundingTest(df, 12.652,s);
1192        s = "12.8";
1193        roundingTest(df, 12.75, s);
1194        roundingTest(df, 12.752,s);
1195        roundingTest(df, 12.85, s);
1196        s = "12.9";
1197        roundingTest(df, 12.852,s);
1198        s = "13";
1199        roundingTest(df, 12.95, s);
1200        roundingTest(df, 12.952,s);
1201    }
1202
1203    delete df;
1204}
1205
1206void NumberFormatRegressionTest::roundingTest(DecimalFormat *df, double x, UnicodeString& expected)
1207{
1208    UnicodeString out;
1209    FieldPosition pos(FieldPosition::DONT_CARE);
1210    out = df->format(x, out, pos);
1211    logln(UnicodeString("") + x + " formats with 1 fractional digits to " + out);
1212    if (out != expected)
1213        errln("FAIL: Expected " + expected);
1214}
1215/* @bug 4098741
1216 * Tests the setMaximumFractionDigits limit.
1217 */
1218void NumberFormatRegressionTest::Test4098741(void)
1219{
1220    //try {
1221    UErrorCode status = U_ZERO_ERROR;
1222    NumberFormat *fmt = NumberFormat::createPercentInstance(status);
1223    if (U_FAILURE(status)) {
1224        dataerrln("Error calling NumberFormat::createPercentInstance");
1225        delete fmt;
1226        return;
1227    }
1228
1229        fmt->setMaximumFractionDigits(20);
1230        UnicodeString temp;
1231        logln(fmt->format(.001, temp));
1232    /*} catch (Exception foo) {
1233        errln("Bug 4098471 failed with exception thrown : " + foo.getMessage());
1234    }*/
1235    delete fmt;
1236}
1237/* @bug 4074454
1238 * Tests illegal pattern exception.
1239 * Fix comment : HShih A31 Part1 will not be fixed and javadoc needs to be updated.
1240 * Part2 has been fixed.
1241 */
1242void NumberFormatRegressionTest::Test4074454(void)
1243{
1244    //try {
1245    UErrorCode status = U_ZERO_ERROR;
1246    DecimalFormat *fmt = new DecimalFormat("#,#00.00;-#.#", status);
1247    if(U_FAILURE(status)) {
1248      errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
1249      delete fmt;
1250      return;
1251    }
1252    failure(status, "new DecimalFormat");
1253      logln("Inconsistent negative pattern is fine.");
1254        DecimalFormat *newFmt = new DecimalFormat("#,#00.00 p''ieces;-#,#00.00 p''ieces", status);
1255        failure(status, "new DecimalFormat");
1256        UnicodeString tempString;
1257        FieldPosition pos(FieldPosition::DONT_CARE);
1258        tempString = newFmt->format(3456.78, tempString, pos);
1259        if (tempString != UnicodeString("3,456.78 p'ieces"))
1260            dataerrln("Failed!  3456.78 p'ieces expected, but got : " + tempString);
1261    /*} catch (Exception foo) {
1262        errln("An exception was thrown for any inconsistent negative pattern.");
1263    }*/
1264
1265    delete fmt;
1266    delete newFmt;
1267}
1268/* @bug 4099404
1269 * Tests all different comments.
1270 * Response to some comments :
1271 * [1] DecimalFormat.parse API documentation is more than just one line.
1272 * This is not a reproducable doc error in 116 source code.
1273 * [2] See updated javadoc.
1274 * [3] Fixed.
1275 * [4] NumberFormat.parse(String, ParsePosition) : If parsing fails,
1276 * a null object will be returned.  The unchanged parse position also
1277 * reflects an error.
1278 * NumberFormat.parse(String) : If parsing fails, an ParseException
1279 * will be thrown.
1280 * See updated javadoc for more details.
1281 * [5] See updated javadoc.
1282 * [6] See updated javadoc.
1283 * [7] This is a correct behavior if the DateFormat object is linient.
1284 * Otherwise, an IllegalArgumentException will be thrown when formatting
1285 * "January 35".  See GregorianCalendar class javadoc for more details.
1286 */
1287void NumberFormatRegressionTest::Test4099404(void)
1288{
1289    //try {
1290        UErrorCode status = U_ZERO_ERROR;
1291        DecimalFormat *fmt = new DecimalFormat(UnicodeString("000.0#0"), status);
1292        if(! U_FAILURE(status))
1293            errln(UnicodeString("Bug 4099404 failed applying illegal pattern \"000.0#0\""));
1294    /*} catch (Exception foo) {
1295        logln("Bug 4099404 pattern \"000.0#0\" passed");
1296    }*/
1297    delete fmt;
1298    fmt = 0;
1299        //try {
1300        fmt = new DecimalFormat(UnicodeString("0#0.000"), status);
1301        if( !U_FAILURE(status))
1302           errln("Bug 4099404 failed applying illegal pattern \"0#0.000\"");
1303    /*} catch (Exception foo) {
1304        logln("Bug 4099404 pattern \"0#0.000\" passed");
1305    }*/
1306
1307    delete fmt;
1308}
1309/* @bug 4101481
1310 * DecimalFormat.applyPattern doesn't set minimum integer digits
1311 */
1312void NumberFormatRegressionTest::Test4101481(void)
1313{
1314    UErrorCode status = U_ZERO_ERROR;
1315    DecimalFormat *sdf = new DecimalFormat(UnicodeString("#,##0"), status);
1316    if(U_FAILURE(status)) {
1317      errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
1318      delete sdf;
1319      return;
1320    }
1321    failure(status, "new DecimalFormat");
1322    if (sdf->getMinimumIntegerDigits() != 1)
1323        errln(UnicodeString("Minimum integer digits : ") + sdf->getMinimumIntegerDigits());
1324    delete sdf;
1325}
1326/* @bug 4052223 (API addition request A27)
1327 * Tests ParsePosition.setErrorPosition() and ParsePosition.getErrorPosition().
1328 */
1329void NumberFormatRegressionTest::Test4052223(void)
1330{
1331    //try {
1332    UErrorCode status = U_ZERO_ERROR;
1333        DecimalFormat *fmt = new DecimalFormat(UnicodeString("#,#00.00"), status);
1334        if(U_FAILURE(status)) {
1335          errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
1336          delete fmt;
1337          return;
1338        }
1339        failure(status, "new DecimalFormat");
1340        Formattable num;
1341        fmt->parse(UnicodeString("abc3"), num, status);
1342        if(! U_FAILURE(status))
1343            errln(UnicodeString("Bug 4052223 failed : can't parse string \"a\".  Got ") /*+ num*/);
1344    /*} catch (ParseException foo) {
1345        logln("Caught expected ParseException : " + foo.getMessage() + " at index : " + foo.getErrorOffset());
1346    }*/
1347    delete fmt;
1348}
1349/* @bug 4061302
1350 * API tests for API addition request A9.
1351 */
1352void NumberFormatRegressionTest::Test4061302(void)
1353{
1354    UErrorCode status = U_ZERO_ERROR;
1355    DecimalFormatSymbols *fmt = new DecimalFormatSymbols(status);
1356    if (U_FAILURE(status)) {
1357        dataerrln("Error creating DecimalFormatSymbols - %s", u_errorName(status));
1358        return;
1359    }
1360    UnicodeString currency(fmt->getSymbol(DecimalFormatSymbols::kCurrencySymbol));
1361    UnicodeString intlCurrency(fmt->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol));
1362    UnicodeString monDecSeparator(fmt->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol));
1363    if (currency == UnicodeString("") ||
1364        intlCurrency == UnicodeString("") ||
1365        monDecSeparator == UnicodeString(""))
1366    {
1367        errln("getCurrencySymbols failed, got empty string.");
1368    }
1369    UnicodeString monDecSeparatorStr;
1370    monDecSeparatorStr.append(monDecSeparator);
1371    logln((UnicodeString)"Before set ==> Currency : " + currency +(UnicodeString)" Intl Currency : " + intlCurrency + (UnicodeString)" Monetary Decimal Separator : " + monDecSeparatorStr);
1372    fmt->setSymbol(DecimalFormatSymbols::kCurrencySymbol, UnicodeString("XYZ"));
1373    fmt->setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol, UnicodeString("ABC"));
1374    fmt->setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol, UnicodeString((UChar)0x002A/*'*'*/));
1375    currency = fmt->getSymbol(DecimalFormatSymbols::kCurrencySymbol);
1376    intlCurrency = fmt->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol);
1377    monDecSeparator = fmt->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol);
1378    if (currency != UnicodeString("XYZ") ||
1379        intlCurrency != UnicodeString("ABC") ||
1380        monDecSeparator != UnicodeString((UChar)0x002A/*'*'*/)) {
1381        errln("setCurrencySymbols failed.");
1382    }
1383    monDecSeparatorStr.remove();
1384    monDecSeparatorStr.append(monDecSeparator);
1385    logln("After set ==> Currency : " + currency + " Intl Currency : " + intlCurrency + " Monetary Decimal Separator : " + monDecSeparatorStr);
1386
1387    delete fmt;
1388}
1389/* @bug 4062486
1390 * API tests for API addition request A23. FieldPosition.getBeginIndex and
1391 * FieldPosition.getEndIndex.
1392 */
1393void NumberFormatRegressionTest::Test4062486(void)
1394{
1395    UErrorCode status = U_ZERO_ERROR;
1396    DecimalFormat *fmt = new DecimalFormat(UnicodeString("#,##0.00"), status);
1397    if (U_FAILURE(status)) {
1398        dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
1399        return;
1400    }
1401    UnicodeString formatted;
1402    FieldPosition field(FieldPosition::DONT_CARE);
1403    double num = 1234.5;
1404    fmt->format(num, formatted, field);
1405    if (field.getBeginIndex() != 0 && field.getEndIndex() != 5)
1406        errln(UnicodeString("Format 1234.5 failed. Begin index: ") /*+ field.getBeginIndex() + " End index: " + field.getEndIndex()*/);
1407    field.setBeginIndex(7);
1408    field.setEndIndex(4);
1409    if (field.getBeginIndex() != 7 && field.getEndIndex() != 4)
1410        errln("Set begin/end field indexes failed. Begin index: " /*+ field.getBeginIndex() + " End index: " + field.getEndIndex()*/);
1411
1412    delete fmt;
1413}
1414
1415/* @bug 4108738
1416 * DecimalFormat.parse incorrectly works with a group separator.
1417 */
1418void NumberFormatRegressionTest::Test4108738(void)
1419{
1420    UErrorCode status = U_ZERO_ERROR;
1421    DecimalFormatSymbols *syms = new DecimalFormatSymbols(Locale::getUS(), status);
1422    failure(status, "new DecimalFormatSymbols");
1423    DecimalFormat *df = new DecimalFormat("#,##0.###", syms, status);
1424    if(U_FAILURE(status)) {
1425      errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
1426      delete df;
1427      return;
1428    }
1429    failure(status, "new DecimalFormat");
1430    UnicodeString text("1.222,111");
1431    Formattable num;
1432    ParsePosition pp(0);
1433    df->parse(text, num, pp);
1434
1435    // {sfb} how to do this (again) ?
1436    // shouldn't just be another round-trip test, should it?
1437    UnicodeString temp;
1438    FieldPosition pos(FieldPosition::DONT_CARE);
1439    temp = df->format(num.getDouble(), temp, pos);
1440    //if (!num.toString().equals("1.222"))
1441    if (temp != UnicodeString("1.222"))
1442        //errln("\"" + text + "\"  is parsed as " + num);
1443        errln("\"" + text + "\"  is parsed as " + temp);
1444    text = UnicodeString("1.222x111");
1445    pp = ParsePosition(0);
1446    df->parse(text, num, pp);
1447    temp.remove();
1448    temp = df->format(num.getDouble(), temp, pos);
1449    //if (!num.toString().equals("1.222"))
1450    if (temp != UnicodeString("1.222"))
1451        errln("\"" + text + "\"  is parsed as " + temp);
1452
1453    delete df;
1454}
1455
1456/* @bug 4106658
1457 * DecimalFormat.format() incorrectly formats negative doubles.
1458 */
1459void NumberFormatRegressionTest::Test4106658(void)
1460{
1461    UErrorCode status = U_ZERO_ERROR;
1462    DecimalFormat *df = new DecimalFormat(status); // Corrected; see 4147706
1463    if(U_FAILURE(status)) {
1464      errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
1465      delete df;
1466      return;
1467    }
1468    failure(status, "new DecimalFormat");
1469    volatile double d1 = 0.0;   // volatile to prevent code optimization
1470    double d2 = -0.0001;
1471    UnicodeString buffer;
1472    UnicodeString temp;
1473    FieldPosition pos(FieldPosition::DONT_CARE);
1474
1475#if U_PLATFORM == U_PF_HPUX
1476    d1 = 0.0 * -1.0;    // old HPUX compiler ignores volatile keyword
1477#else
1478    d1 *= -1.0; // Some compilers have a problem with defining -0.0
1479#endif
1480    logln("pattern: \"" + df->toPattern(temp) + "\"");
1481    df->format(d1, buffer, pos);
1482    if (buffer != UnicodeString("-0")) // Corrected; see 4147706
1483        errln(UnicodeString("") + d1 + "      is formatted as " + buffer);
1484    buffer.remove();
1485    df->format(d2, buffer, pos);
1486    if (buffer != UnicodeString("-0")) // Corrected; see 4147706
1487        errln(UnicodeString("") + d2 + "      is formatted as " + buffer);
1488
1489    delete df;
1490}
1491
1492/* @bug 4106662
1493 * DecimalFormat.parse returns 0 if string parameter is incorrect.
1494 */
1495void NumberFormatRegressionTest::Test4106662(void)
1496{
1497    UErrorCode status = U_ZERO_ERROR;
1498    DecimalFormat *df = new DecimalFormat(status);
1499    if(U_FAILURE(status)) {
1500      errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
1501      delete df;
1502      return;
1503    }
1504    failure(status, "new DecimalFormat");
1505    UnicodeString text("x");
1506    ParsePosition pos1(0), pos2(0);
1507
1508    UnicodeString temp;
1509    logln("pattern: \"" + df->toPattern(temp) + "\"");
1510    Formattable num;
1511    df->parse(text, num, pos1);
1512    if (pos1 == ParsePosition(0)/*num != null*/) {
1513        errln(UnicodeString("Test Failed: \"") + text + "\" is parsed as " /*+ num*/);
1514    }
1515    delete df;
1516    df = new DecimalFormat(UnicodeString("$###.00"), status);
1517    failure(status, "new DecimalFormat");
1518    df->parse(UnicodeString("$"), num, pos2);
1519    if (pos2 == ParsePosition(0) /*num != null*/){
1520        errln(UnicodeString("Test Failed: \"$\" is parsed as ") /*+ num*/);
1521    }
1522
1523    delete df;
1524}
1525
1526/* @bug 4114639 (duplicate of 4106662)
1527 * NumberFormat.parse doesn't return null
1528 */
1529void NumberFormatRegressionTest::Test4114639(void)
1530{
1531    UErrorCode status = U_ZERO_ERROR;
1532    NumberFormat *format = NumberFormat::createInstance(status);
1533    if(U_FAILURE(status)) {
1534      dataerrln("Error creating DecimalFormat: %s", u_errorName(status));
1535      delete format;
1536      return;
1537    }
1538    failure(status, "NumberFormat::createInstance");
1539    UnicodeString text("time 10:x");
1540    ParsePosition pos(8);
1541    Formattable result;
1542    format->parse(text, result, pos);
1543    if (/*result != null*/pos.getErrorIndex() != 8)
1544        errln(UnicodeString("Should return null but got : ") /*+ result*/); // Should be null; it isn't
1545
1546    delete format;
1547}
1548
1549/* @bug 4106664
1550 * TODO: this test does not work because we need to use a 64 bit number and a
1551 * a double only MAY only have 52 bits of precision.
1552 * DecimalFormat.format(long n) fails if n * multiplier > MAX_LONG.
1553 */
1554void NumberFormatRegressionTest::Test4106664(void)
1555{
1556    UErrorCode status = U_ZERO_ERROR;
1557    DecimalFormat *df = new DecimalFormat(status);
1558    if(U_FAILURE(status)) {
1559      errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
1560      delete df;
1561      return;
1562    }
1563    failure(status, "new DecimalFormat");
1564    // {sfb} long in java is 64 bits
1565    /*long*/double n = 1234567890123456.0;
1566    /*int*/int32_t m = 12345678;
1567    // {sfb} will this work?
1568    //BigInteger bigN = BigInteger.valueOf(n);
1569    //bigN = bigN.multiply(BigInteger.valueOf(m));
1570    double bigN = n * m;
1571    df->setMultiplier(m);
1572    df->setGroupingUsed(FALSE);
1573    UnicodeString temp;
1574    FieldPosition pos(FieldPosition::DONT_CARE);
1575    logln("formated: " +
1576        df->format(n, temp, pos));
1577
1578    char buf [128];
1579    sprintf(buf, "%g", bigN);
1580    //logln("expected: " + bigN.toString());
1581    logln(UnicodeString("expected: ") + buf);
1582
1583    delete df;
1584}
1585/* @bug 4106667 (duplicate of 4106658)
1586 * DecimalFormat.format incorrectly formats -0.0.
1587 */
1588void NumberFormatRegressionTest::Test4106667(void)
1589{
1590    UErrorCode status = U_ZERO_ERROR;
1591    DecimalFormat *df = new DecimalFormat(status);
1592    if(U_FAILURE(status)) {
1593      errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
1594      delete df;
1595      return;
1596    }
1597    failure(status, "new DecimalFormat");
1598    UChar foo [] = { 0x002B };
1599    UnicodeString bar(foo, 1, 1);
1600    volatile double d = 0.0;   // volatile to prevent code optimization
1601    UnicodeString temp;
1602    UnicodeString buffer;
1603    FieldPosition pos(FieldPosition::DONT_CARE);
1604
1605    logln("pattern: \"" + df->toPattern(temp) + "\"");
1606#if U_PLATFORM == U_PF_HPUX
1607    d = 0.0 * -1.0;    // old HPUX compiler ignores volatile keyword
1608#else
1609    d *= -1.0; // Some compilers have a problem with defining -0.0
1610#endif
1611    df->setPositivePrefix(/*"+"*/bar);
1612    df->format(d, buffer, pos);
1613    if (buffer != UnicodeString("-0")) // Corrected; see 4147706
1614        errln(/*d + */UnicodeString("  is formatted as ") + buffer);
1615
1616    delete df;
1617}
1618
1619/* @bug 4110936
1620 * DecimalFormat.setMaximumIntegerDigits() works incorrectly.
1621 */
1622#if U_PLATFORM == U_PF_OS390
1623#   define MAX_INT_DIGITS 70
1624#else
1625#   define MAX_INT_DIGITS 128
1626#endif
1627
1628void NumberFormatRegressionTest::Test4110936(void)
1629{
1630    UErrorCode status = U_ZERO_ERROR;
1631    NumberFormat *nf = NumberFormat::createInstance(status);
1632    if(U_FAILURE(status)) {
1633      dataerrln("Error creating DecimalFormat: %s", u_errorName(status));
1634      delete nf;
1635      return;
1636    }
1637    failure(status, "NumberFormat::createInstance");
1638    nf->setMaximumIntegerDigits(MAX_INT_DIGITS);
1639    logln("setMaximumIntegerDigits(MAX_INT_DIGITS)");
1640    if (nf->getMaximumIntegerDigits() != MAX_INT_DIGITS)
1641        errln(UnicodeString("getMaximumIntegerDigits() returns ") +
1642            nf->getMaximumIntegerDigits());
1643
1644    delete nf;
1645}
1646
1647/* @bug 4122840
1648 * Locale data should use generic currency symbol
1649 *
1650 * 1) Make sure that all currency formats use the generic currency symbol.
1651 * 2) Make sure we get the same results using the generic symbol or a
1652 *    hard-coded one.
1653 */
1654void NumberFormatRegressionTest::Test4122840(void)
1655{
1656    int32_t count = 0;
1657    const Locale *locales = Locale::getAvailableLocales(count);
1658
1659    for (int i = 0; i < count; i++) {
1660        UErrorCode status = U_ZERO_ERROR;
1661        ResourceBundle *rb = new ResourceBundle(
1662            NULL/*"java.text.resources.LocaleElements"*/,
1663            locales[i], status);
1664        failure(status, "new ResourceBundle");
1665        ResourceBundle numPat = rb->getWithFallback("NumberElements", status);
1666        failure(status, "rb.get(NumberElements)");
1667        numPat = numPat.getWithFallback("latn",status);
1668        failure(status, "rb.get(latn)");
1669        numPat = numPat.getWithFallback("patterns",status);
1670        failure(status, "rb.get(patterns)");
1671        numPat = numPat.getWithFallback("currencyFormat",status);
1672        failure(status, "rb.get(currencyFormat)");
1673       //
1674        // Get the currency pattern for this locale.  We have to fish it
1675        // out of the ResourceBundle directly, since DecimalFormat.toPattern
1676        // will return the localized symbol, not \00a4
1677        //
1678        UnicodeString pattern = numPat.getString(status);
1679        failure(status, "rb->getString()");
1680
1681        UChar fo[] = { 0x00A4 };
1682        UnicodeString foo(fo, 1, 1);
1683
1684        //if (pattern.indexOf("\u00A4") == -1 ) {
1685        if (pattern.indexOf(foo) == -1 ) {
1686            errln(UnicodeString("Currency format for ") + UnicodeString(locales[i].getName()) +
1687                    " does not contain generic currency symbol:" +
1688                    pattern );
1689        }
1690
1691        // Create a DecimalFormat using the pattern we got and format a number
1692        DecimalFormatSymbols *symbols = new DecimalFormatSymbols(locales[i], status);
1693        failure(status, "new DecimalFormatSymbols");
1694        DecimalFormat *fmt1 = new DecimalFormat(pattern, *symbols, status);
1695        failure(status, "new DecimalFormat");
1696
1697        UnicodeString result1;
1698        FieldPosition pos(FieldPosition::DONT_CARE);
1699        result1 = fmt1->format(1.111, result1, pos);
1700
1701        //
1702        // Now substitute in the locale's currency symbol and create another
1703        // pattern.  We have to skip locales where the currency symbol
1704        // contains decimal separators, because that confuses things
1705        //
1706        UChar ba[] = { 0x002E/*'.'*/ };
1707        UnicodeString bar(ba, 1, 1);
1708
1709        if (symbols->getSymbol(DecimalFormatSymbols::kCurrencySymbol).indexOf(bar) == -1) {
1710            // {sfb} Also, switch the decimal separator to the monetary decimal
1711            // separator to mimic the behavior of a currency format
1712            symbols->setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol,
1713                symbols->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol));
1714
1715            UnicodeString buf(pattern);
1716            for (int j = 0; j < buf.length(); j++) {
1717                if (buf[j] == 0x00a4 ) {
1718                    if(buf[j + 1] == 0x00a4) {
1719                        // {sfb} added to support double currency marker (intl currency sign)
1720                        buf.replace(j, /*j+*/2, symbols->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol));
1721                        j += symbols->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol).length();
1722                    }
1723                    else {
1724                        buf.replace(j, /*j+*/1, symbols->getSymbol(DecimalFormatSymbols::kCurrencySymbol));
1725                        j += symbols->getSymbol(DecimalFormatSymbols::kCurrencySymbol).length() - 1;
1726                    }
1727                }
1728            }
1729
1730            DecimalFormat *fmt2 = new DecimalFormat(buf, *symbols, status);
1731            failure(status, "new DecimalFormat");
1732
1733            // Get the currency (if there is one) so we can set the rounding and fraction
1734            const UChar *currency = fmt1->getCurrency();
1735            if (*currency != 0) {
1736                double rounding = ucurr_getRoundingIncrement(currency, &status);
1737                int32_t frac = ucurr_getDefaultFractionDigits(currency, &status);
1738                if (U_SUCCESS(status)) {
1739                    fmt2->setRoundingIncrement(rounding);
1740                    fmt2->setMinimumFractionDigits(frac);
1741                    fmt2->setMaximumFractionDigits(frac);
1742                }
1743                else {
1744                    failure(status, "Fetching currency rounding/fractions");
1745                }
1746            }
1747
1748            UnicodeString result2;
1749            fmt2->format(1.111, result2, pos);
1750
1751            if (result1 != result2) {
1752                errln("Results for " + (UnicodeString)(locales[i].getName()) + " differ: " +
1753                        result1 + " vs " + result2);
1754            }
1755
1756            delete fmt2;
1757        }
1758
1759        delete rb;
1760        delete fmt1;
1761        delete symbols;
1762    }
1763}
1764
1765/* @bug 4125885
1766 * DecimalFormat.format() delivers wrong string.
1767 */
1768void NumberFormatRegressionTest::Test4125885(void)
1769{
1770    UErrorCode status = U_ZERO_ERROR;
1771    double rate = 12.34;
1772    DecimalFormat *formatDec = new DecimalFormat ("000.00", status);
1773    if(U_FAILURE(status)) {
1774      errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
1775      delete formatDec;
1776      return;
1777    }
1778    failure(status, "new DecimalFormat");
1779    UnicodeString temp;
1780    logln("toPattern: " + formatDec->toPattern(temp));
1781    UnicodeString rateString;
1782    FieldPosition pos(FieldPosition::DONT_CARE);
1783    rateString = formatDec->format(rate, rateString, pos);
1784    if (rateString != UnicodeString("012.34"))
1785        errln("result : " + rateString + " expected : 012.34");
1786    rate = 0.1234;
1787    delete formatDec;// = null;
1788    formatDec = new DecimalFormat ("+000.00%;-000.00%", status);
1789    failure(status, "new DecimalFormat");
1790    logln("toPattern: " + formatDec->toPattern(temp));
1791    rateString.remove();
1792    rateString = formatDec->format(rate, rateString, pos);
1793    if (rateString != UnicodeString("+012.34%"))
1794        errln("result : " + rateString + " expected : +012.34%");
1795
1796    delete formatDec;
1797}
1798
1799/**
1800 * @bug 4134034
1801 * DecimalFormat produces extra zeros when formatting numbers.
1802 */
1803void NumberFormatRegressionTest::Test4134034(void)
1804{
1805    UErrorCode status = U_ZERO_ERROR;
1806    DecimalFormat *nf = new DecimalFormat("##,###,###.00", status);
1807    if (!failure(status, "new DecimalFormat")) {
1808        UnicodeString f;
1809        FieldPosition pos(FieldPosition::DONT_CARE);
1810        f = nf->format(9.02, f, pos);
1811        if (f == UnicodeString("9.02"))
1812            logln(f + " ok");
1813        else
1814            errln("9.02 -> " + f + "; want 9.02");
1815
1816        f.remove();
1817        f = nf->format((int32_t)0, f, pos);
1818        if (f == UnicodeString(".00"))
1819            logln(f + " ok");
1820        else
1821            errln("0 -> " + f + "; want .00");
1822    }
1823
1824    delete nf;
1825}
1826
1827/**
1828 * @bug 4134300
1829 * CANNOT REPRODUCE - This bug could not be reproduced.  It may be
1830 * a duplicate of 4134034.
1831 *
1832 * JDK 1.1.6 Bug, did NOT occur in 1.1.5
1833 * Possibly related to bug 4125885.
1834 *
1835 * This class demonstrates a regression in version 1.1.6
1836 * of DecimalFormat class.
1837 *
1838 * 1.1.6 Results
1839 * Value 1.2 Format #.00 Result '01.20' !!!wrong
1840 * Value 1.2 Format 0.00 Result '001.20' !!!wrong
1841 * Value 1.2 Format 00.00 Result '0001.20' !!!wrong
1842 * Value 1.2 Format #0.0# Result '1.2'
1843 * Value 1.2 Format #0.00 Result '001.20' !!!wrong
1844 *
1845 * 1.1.5 Results
1846 * Value 1.2 Format #.00 Result '1.20'
1847 * Value 1.2 Format 0.00 Result '1.20'
1848 * Value 1.2 Format 00.00 Result '01.20'
1849 * Value 1.2 Format #0.0# Result '1.2'
1850 * Value 1.2 Format #0.00 Result '1.20'
1851 */
1852void NumberFormatRegressionTest::Test4134300(void) {
1853    UnicodeString DATA [] = {
1854     // Pattern      Expected string
1855        UnicodeString("#.00"),      UnicodeString("1.20"),
1856        UnicodeString("0.00"),      UnicodeString("1.20"),
1857        UnicodeString("00.00"),     UnicodeString("01.20"),
1858        UnicodeString("#0.0#"),     UnicodeString("1.2"),
1859        UnicodeString("#0.00"),     UnicodeString("1.20")
1860    };
1861
1862    for (int i=0; i< 10; i+=2) {
1863        UnicodeString result;
1864        UErrorCode status = U_ZERO_ERROR;
1865        DecimalFormat *df = new DecimalFormat(DATA[i], status);
1866        if (!failure(status, "new DecimalFormat")) {
1867            FieldPosition pos(FieldPosition::DONT_CARE);
1868            result = df->format(1.2, result, pos);
1869            if (result != DATA[i+1]) {
1870                errln("Fail: 1.2 x " + DATA[i] + " = " + result +
1871                      "; want " + DATA[i+1]);
1872            }
1873            else {
1874                logln("Ok: 1.2 x " + DATA[i] + " = " + result);
1875            }
1876        }
1877
1878        delete df;
1879    }
1880}
1881
1882/**
1883 * @bug 4140009
1884 * Empty pattern produces double negative prefix.
1885 */
1886void NumberFormatRegressionTest::Test4140009(void)
1887{
1888    UErrorCode status = U_ZERO_ERROR;
1889    DecimalFormatSymbols *syms = new DecimalFormatSymbols(Locale::getEnglish(), status);
1890    failure(status, "new DecimalFormatSymbols");
1891    DecimalFormat *f = new DecimalFormat(UnicodeString(""), syms, status);
1892    if (!failure(status, "new DecimalFormat")) {
1893        UnicodeString s;
1894        FieldPosition pos(FieldPosition::DONT_CARE);
1895        s = f->format(123.456, s, pos);
1896        if (s != UnicodeString("123.456"))
1897            errln("Fail: Format empty pattern x 123.456 => " + s);
1898        s.remove();
1899        s = f->format(-123.456, s, pos);
1900        if (s != UnicodeString("-123.456"))
1901            errln("Fail: Format empty pattern x -123.456 => " + s);
1902    }
1903    delete f;
1904}
1905
1906/**
1907 * @bug 4141750
1908 * BigDecimal numbers get their fractions truncated by NumberFormat.
1909 */
1910// {sfb} not pertinent in C++ ??
1911void NumberFormatRegressionTest::Test4141750(void) {
1912    /*try {
1913        UnicodeString str("12345.67");
1914        BigDecimal bd = new BigDecimal(str);
1915        String sd = NumberFormat.getInstance(Locale.US).format(bd);
1916        if (!sd.endsWith("67")) errln("Fail: " + str + " x format -> " + sd);
1917    }
1918    catch (Exception e) {
1919        errln(e.toString());
1920        e.printStackTrace();
1921    }*/
1922}
1923
1924/**
1925 * @bug 4145457
1926 * DecimalFormat toPattern() doesn't quote special characters or handle
1927 * single quotes.
1928 */
1929void NumberFormatRegressionTest::Test4145457() {
1930    //try {
1931    UErrorCode status = U_ZERO_ERROR;
1932    NumberFormat *nff = NumberFormat::createInstance(status);
1933    if (failure(status, "NumberFormat::createInstance", TRUE)){
1934        delete nff;
1935        return;
1936    };
1937    DecimalFormat *nf = dynamic_cast<DecimalFormat *>(nff);
1938    if(nf == NULL) {
1939        errln("DecimalFormat needed to continue");
1940        return;
1941    }
1942
1943    DecimalFormatSymbols *sym = (DecimalFormatSymbols*) nf->getDecimalFormatSymbols();
1944    sym->setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, (UChar)/*'\''*/0x0027);
1945    nf->setDecimalFormatSymbols(*sym);
1946    double pi = 3.14159;
1947
1948    UnicodeString PATS [] = {
1949        UnicodeString("#.00 'num''ber'"), UnicodeString("''#.00''")
1950    };
1951
1952    for (int32_t i=0; i<2; ++i) {
1953        nf->applyPattern(PATS[i], status);
1954        failure(status, "nf->applyPattern");
1955        UnicodeString out;
1956        FieldPosition pos(FieldPosition::DONT_CARE);
1957        out = nf->format(pi, out, pos);
1958        UnicodeString pat;
1959        pat = nf->toPattern(pat);
1960        Formattable num;
1961        ParsePosition pp(0);
1962        nf->parse(out, num, pp);
1963        double val = num.getDouble();
1964
1965        nf->applyPattern(pat, status);
1966        failure(status, "nf->applyPattern");
1967        UnicodeString out2;
1968        out2 = nf->format(pi, out2, pos);
1969        UnicodeString pat2;
1970        pat2 = nf->toPattern(pat2);
1971        pp.setIndex(0);
1972        nf->parse(out2, num, pp);
1973        double val2 = num.getDouble();
1974
1975        if (pat != pat2)
1976            errln("Fail with \"" + PATS[i] + "\": Patterns should concur, \"" +
1977                pat + "\" vs. \"" + pat2 + "\"");
1978        else
1979            logln("Ok \"" + PATS[i] + "\" toPattern() -> \"" + pat + '"');
1980
1981        if (val == val2 && out == out2) {
1982            logln(UnicodeString("Ok ") + pi + " x \"" + PATS[i] + "\" -> \"" +
1983                out + "\" -> " + val + " -> \"" +
1984                out2 + "\" -> " + val2);
1985        }
1986        else {
1987            errln(UnicodeString("Fail ") + pi + " x \"" + PATS[i] + "\" -> \"" +
1988                out + "\" -> " + val + " -> \"" +
1989                out2 + "\" -> " + val2);
1990        }
1991    }
1992    /*}
1993    catch (ParseException e) {
1994        errln("Fail: " + e);
1995        e.printStackTrace();
1996    }*/
1997
1998    delete nff;
1999}
2000
2001/**
2002 * @bug 4147295
2003 * DecimalFormat.applyPattern() sets minimum integer digits incorrectly.
2004 * CANNOT REPRODUCE
2005 * This bug is a duplicate of 4139344, which is a duplicate of 4134300
2006 */
2007void NumberFormatRegressionTest::Test4147295(void)
2008{
2009    UErrorCode status = U_ZERO_ERROR;
2010    DecimalFormat *sdf = new DecimalFormat(status);
2011    UnicodeString pattern("#,###");
2012    logln("Applying pattern \"" + pattern + "\"");
2013    sdf->applyPattern(pattern, status);
2014    if (!failure(status, "sdf->applyPattern")) {
2015        int minIntDig = sdf->getMinimumIntegerDigits();
2016        if (minIntDig != 0) {
2017            errln("Test failed");
2018            errln(UnicodeString(" Minimum integer digits : ") + minIntDig);
2019            UnicodeString temp;
2020            errln(UnicodeString(" new pattern: ") + sdf->toPattern(temp));
2021        } else {
2022            logln("Test passed");
2023            logln(UnicodeString(" Minimum integer digits : ") + minIntDig);
2024        }
2025    }
2026    delete sdf;
2027}
2028
2029/**
2030 * @bug 4147706
2031 * DecimalFormat formats -0.0 as +0.0
2032 * See also older related bug 4106658, 4106667
2033 */
2034void NumberFormatRegressionTest::Test4147706(void)
2035{
2036    UErrorCode status = U_ZERO_ERROR;
2037    DecimalFormat *df = new DecimalFormat("#,##0.0##", status);
2038    failure(status, "new DecimalFormat");
2039    DecimalFormatSymbols *syms = new DecimalFormatSymbols(Locale::getEnglish(), status);
2040    if (!failure(status, "new DecimalFormatSymbols")) {
2041        UnicodeString f1;
2042        UnicodeString f2, temp;
2043        FieldPosition pos(FieldPosition::DONT_CARE);
2044        volatile double d1 = 0.0;   // volatile to prevent code optimization
2045        double d2 = -0.0001;
2046
2047#if U_PLATFORM == U_PF_HPUX
2048        d1 = 0.0 * -1.0;    // old HPUX compiler ignores volatile keyword
2049#else
2050        d1 *= -1.0; // Some compilers have a problem with defining -0.0
2051#endif
2052        df->adoptDecimalFormatSymbols(syms);
2053        f1 = df->format(d1, f1, pos);
2054        f2 = df->format(d2, f2, pos);
2055        if (f1 != UnicodeString("-0.0")) {
2056            errln(UnicodeString("") + d1 + UnicodeString(" x \"") + df->toPattern(temp) + "\" is formatted as \"" + f1 + '"');
2057        }
2058        if (f2 != UnicodeString("-0.0")) {
2059            errln(UnicodeString("") + d2 + UnicodeString(" x \"") + df->toPattern(temp) + "\" is formatted as \"" + f2 + '"');
2060        }
2061    }
2062
2063    delete df;
2064}
2065
2066
2067// Not applicable, since no serialization in C++
2068/*class myformat implements Serializable
2069{
2070DateFormat _dateFormat = DateFormat.getDateInstance();
2071
2072public String Now()
2073{
2074    GregorianCalendar calendar = new GregorianCalendar();
2075    Date t = calendar.getTime();
2076    String nowStr = _dateFormat.format(t);
2077    return nowStr;
2078}
2079}*/
2080
2081/**
2082 * @bug 4162198
2083 * NumberFormat cannot format Double.MAX_VALUE
2084 */
2085// TODO: make this test actually test something
2086void
2087NumberFormatRegressionTest::Test4162198(void)
2088{
2089    // for some reason, DBL_MAX will not round trip. (bug in sprintf/atof)
2090    double dbl = INT32_MAX * 1000.0;
2091    UErrorCode status = U_ZERO_ERROR;
2092    NumberFormat *f = NumberFormat::createInstance(status);
2093    if(U_FAILURE(status)) {
2094        dataerrln("Couldn't create number format - %s", u_errorName(status));
2095        return;
2096    }
2097    f->setMaximumFractionDigits(INT32_MAX);
2098    f->setMaximumIntegerDigits(INT32_MAX);
2099    UnicodeString s;
2100    f->format(dbl,s);
2101    logln(UnicodeString("The number ") + dbl + " formatted to " + s);
2102    Formattable n;
2103    //try {
2104    f->parse(s, n, status);
2105    if(U_FAILURE(status))
2106        errln("Couldn't parse!");
2107    //} catch (java.text.ParseException e) {
2108    //    errln("Caught a ParseException:");
2109    //    e.printStackTrace();
2110    //}
2111
2112    //logln("The string " + s + " parsed as " + n);
2113
2114    // {dlf} The old code assumes n is a double, but it isn't any more...
2115    // Formattable apparently does not and never did interconvert... too bad.
2116    //if(n.getDouble() != dbl) {
2117    //    errln("Round trip failure");
2118    //}
2119    if (n.getInt64() != dbl) {
2120        errln("Round trip failure");
2121    }
2122
2123    delete f;
2124}
2125
2126/**
2127 * @bug 4162852
2128 * NumberFormat does not parse negative zero.
2129 */
2130void
2131NumberFormatRegressionTest::Test4162852(void)
2132{
2133    UErrorCode status = U_ZERO_ERROR;
2134    for(int32_t i=0; i < 2; ++i) {
2135        NumberFormat *f = (i == 0) ? NumberFormat::createInstance(status)
2136            : NumberFormat::createPercentInstance(status);
2137        if(U_FAILURE(status)) {
2138            dataerrln("Couldn't create number format - %s", u_errorName(status));
2139            return;
2140        }
2141        double d = 0.0;
2142        d *= -1.0;
2143        UnicodeString s;
2144        f->format(d, s);
2145        Formattable n;
2146        f->parse(s, n, status);
2147        if(U_FAILURE(status))
2148            errln("Couldn't parse!");
2149        double e = n.getDouble();
2150        logln(UnicodeString("") +
2151              d + " -> " +
2152              '"' + s + '"' + " -> " + e);
2153#if (U_PLATFORM == U_PF_OS390 && !defined(IEEE_754)) || U_PLATFORM == U_PF_OS400
2154        if (e != 0.0) {
2155#else
2156        if (e != 0.0 || 1.0/e > 0.0) {
2157#endif
2158            logln("Failed to parse negative zero");
2159        }
2160        delete f;
2161    }
2162}
2163
2164static double _u_abs(double a) { return a<0?-a:a; }
2165
2166/**
2167 * May 17 1999 sync up - liu
2168 * @bug 4167494
2169 * NumberFormat truncates data
2170 */
2171void NumberFormatRegressionTest::Test4167494(void) {
2172    UErrorCode status = U_ZERO_ERROR;
2173    NumberFormat *fmt = NumberFormat::createInstance(Locale::getUS(), status);
2174    if (failure(status, "NumberFormat::createInstance", TRUE)){
2175        delete fmt;
2176        return;
2177    };
2178
2179    double a = DBL_MAX * 0.99; // DBL_MAX itself overflows to +Inf
2180    UnicodeString s;
2181    fmt->format(a, s);
2182    Formattable num;
2183    fmt->parse(s, num, status);
2184    failure(status, "Parse");
2185    if (num.getType() == Formattable::kDouble &&
2186        _u_abs(num.getDouble() - a) / a < 0.01) { // RT within 1%
2187        logln(UnicodeString("") + a + " -> \"" + s + "\" -> " +
2188              toString(num) + " ok");
2189    } else {
2190        errln(UnicodeString("") + a + " -> \"" + s + "\" -> " +
2191              toString(num) + " FAIL");
2192    }
2193
2194    // We don't test Double.MIN_VALUE because the locale data for the US
2195    // currently doesn't specify enough digits to display Double.MIN_VALUE.
2196    // This is correct for now; however, we leave this here as a reminder
2197    // in case we want to address this later.
2198
2199    delete fmt;
2200}
2201
2202/**
2203 * May 17 1999 sync up - liu
2204 * @bug 4170798
2205 * DecimalFormat.parse() fails when ParseIntegerOnly set to true
2206 */
2207void NumberFormatRegressionTest::Test4170798(void) {
2208    UErrorCode status = U_ZERO_ERROR;
2209    NumberFormat *nf = NumberFormat::createInstance(Locale::getUS(), status);
2210    if (failure(status, "NumberFormat::createInstance", TRUE)){
2211        delete nf;
2212        return;
2213    };
2214    DecimalFormat *df = dynamic_cast<DecimalFormat *>(nf);
2215    if(df == NULL) {
2216        errln("DecimalFormat needed to continue");
2217        return;
2218    }
2219    df->setParseIntegerOnly(TRUE);
2220    Formattable n;
2221    ParsePosition pos(0);
2222    df->parse("-0.0", n, pos);
2223    if (n.getType() != Formattable::kLong
2224        || n.getLong() != 0) {
2225        errln(UnicodeString("FAIL: parse(\"-0.0\") returns ") + toString(n));
2226    }
2227    delete nf;
2228}
2229
2230/**
2231 * May 17 1999 sync up - liu
2232 * toPattern only puts the first grouping separator in.
2233 */
2234void NumberFormatRegressionTest::Test4176114(void) {
2235    const char* DATA[] = {
2236        "00", "#00",
2237        "000", "#000", // No grouping
2238        "#000", "#000", // No grouping
2239        "#,##0", "#,##0",
2240        "#,000", "#,000",
2241        "0,000", "#0,000",
2242        "00,000", "#00,000",
2243        "000,000", "#,000,000",
2244        "0,000,000,000,000.0000", "#0,000,000,000,000.0000", // Reported
2245    };
2246    int DATA_length = UPRV_LENGTHOF(DATA);
2247    UErrorCode status = U_ZERO_ERROR;
2248    UnicodeString s;
2249    for (int i=0; i<DATA_length; i+=2) {
2250        DecimalFormat df(DATA[i], status);
2251        if (!failure(status, "DecimalFormat constructor")) {
2252            df.toPattern(s);
2253            UnicodeString exp(DATA[i+1]);
2254            if (s != exp) {
2255                errln(UnicodeString("FAIL: ") + DATA[i] + " -> " +
2256                      s + ", want " + exp);
2257            }
2258        }
2259    }
2260}
2261
2262/**
2263 * May 17 1999 sync up - liu
2264 * @bug 4179818
2265 * DecimalFormat is incorrectly rounding numbers like 1.2501 to 1.2
2266 */
2267void NumberFormatRegressionTest::Test4179818(void) {
2268    const char* DATA[] = {
2269        // Input  Pattern  Expected output
2270        "1.2511", "#.#",   "1.3",
2271        "1.2501", "#.#",   "1.3",
2272        "0.9999", "#",     "1",
2273    };
2274    int DATA_length = UPRV_LENGTHOF(DATA);
2275    double DOUBLE[] = {
2276        1.2511,
2277        1.2501,
2278        0.9999,
2279    };
2280    UErrorCode status = U_ZERO_ERROR;
2281    DecimalFormatSymbols sym(Locale::getUS(), status);
2282    failure(status, "Construct DecimalFormatSymbols");
2283    DecimalFormat fmt("#", sym, status);
2284    if (!failure(status, "Construct DecimalFormat")) {
2285        for (int i=0; i<DATA_length; i+=3) {
2286            double in = DOUBLE[i/3];
2287            UnicodeString pat(DATA[i+1]);
2288            UnicodeString exp(DATA[i+2]);
2289            fmt.applyPattern(pat, status);
2290            failure(status, "applyPattern");
2291            UnicodeString out;
2292            FieldPosition pos;
2293            fmt.format(in, out, pos);
2294            if (out == exp) {
2295                logln(UnicodeString("Ok: ") + in + " x " + pat + " = " + out);
2296            } else {
2297                errln(UnicodeString("FAIL: ") + in + " x  " + pat + " = " + out +
2298                      ", expected " + exp);
2299            }
2300        }
2301    }
2302}
2303
2304/**
2305 * May 17 1999 sync up - liu
2306 * Some DecimalFormatSymbols changes are not picked up by DecimalFormat.
2307 * This includes the minus sign, currency symbol, international currency
2308 * symbol, percent, and permille.  This is filed as bugs 4212072 and
2309 * 4212073.
2310 */
2311void NumberFormatRegressionTest::Test4212072(void) {
2312    UErrorCode status = U_ZERO_ERROR;
2313    DecimalFormatSymbols sym(Locale::getUS(), status);
2314
2315    failure(status, "DecimalFormatSymbols ct", Locale::getUS());
2316    DecimalFormat fmt(UnicodeString("#"), sym, status);
2317    if(failure(status, "DecimalFormat ct", Locale::getUS())) {
2318        return;
2319    }
2320
2321    UnicodeString s;
2322    FieldPosition pos;
2323
2324    sym.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, (UChar)0x5e);
2325    fmt.setDecimalFormatSymbols(sym);
2326    s.remove();
2327    if (fmt.format((int32_t)-1, s, pos) != UNICODE_STRING("^1", 2)) {
2328        errln(UnicodeString("FAIL: -1 x (minus=^) -> ") + s +
2329              ", exp ^1");
2330    }
2331    s.remove();
2332    if (fmt.getNegativePrefix(s) != UnicodeString((UChar)0x5e)) {
2333        errln(UnicodeString("FAIL: (minus=^).getNegativePrefix -> ") +
2334              s + ", exp ^");
2335    }
2336    sym.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, (UChar)0x2d);
2337
2338    fmt.applyPattern(UnicodeString("#%"), status);
2339    failure(status, "applyPattern percent");
2340    sym.setSymbol(DecimalFormatSymbols::kPercentSymbol, (UChar)0x5e);
2341    fmt.setDecimalFormatSymbols(sym);
2342    s.remove();
2343    if (fmt.format(0.25, s, pos) != UNICODE_STRING("25^", 3)) {
2344        errln(UnicodeString("FAIL: 0.25 x (percent=^) -> ") + s +
2345              ", exp 25^");
2346    }
2347    s.remove();
2348    if (fmt.getPositiveSuffix(s) != UnicodeString((UChar)0x5e)) {
2349        errln(UnicodeString("FAIL: (percent=^).getPositiveSuffix -> ") +
2350              s + ", exp ^");
2351    }
2352    sym.setSymbol(DecimalFormatSymbols::kPercentSymbol, (UChar)0x25);
2353
2354    fmt.applyPattern(str("#\\u2030"), status);
2355    failure(status, "applyPattern permill");
2356    sym.setSymbol(DecimalFormatSymbols::kPerMillSymbol, (UChar)0x5e);
2357    fmt.setDecimalFormatSymbols(sym);
2358    s.remove();
2359    if (fmt.format(0.25, s, pos) != UNICODE_STRING("250^", 4)) {
2360        errln(UnicodeString("FAIL: 0.25 x (permill=^) -> ") + s +
2361              ", exp 250^");
2362    }
2363    s.remove();
2364    if (fmt.getPositiveSuffix(s) != UnicodeString((UChar)0x5e)) {
2365        errln(UnicodeString("FAIL: (permill=^).getPositiveSuffix -> ") +
2366              s + ", exp ^");
2367    }
2368    sym.setSymbol(DecimalFormatSymbols::kPerMillSymbol, (UChar)0x2030);
2369
2370    fmt.applyPattern(str("\\u00A4#.00"), status);
2371    failure(status, "applyPattern currency");
2372    sym.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "usd");
2373    fmt.setDecimalFormatSymbols(sym);
2374    s.remove();
2375    if (fmt.format(12.5, s, pos) != UnicodeString("usd12.50")) {
2376        errln(UnicodeString("FAIL: 12.5 x (currency=usd) -> ") + s +
2377              ", exp usd12.50");
2378    }
2379    s.remove();
2380    if (fmt.getPositivePrefix(s) != UnicodeString("usd")) {
2381        errln(UnicodeString("FAIL: (currency=usd).getPositivePrefix -> ") +
2382              s + ", exp usd");
2383    }
2384    sym.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "$");
2385
2386    fmt.applyPattern(str("\\u00A4\\u00A4#.00"), status);
2387    failure(status, "applyPattern intl currency");
2388    sym.setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol, "DOL");
2389    fmt.setDecimalFormatSymbols(sym);
2390    s.remove();
2391    if (fmt.format(12.5, s, pos) != UnicodeString("DOL12.50")) {
2392        errln(UnicodeString("FAIL: 12.5 x (intlcurrency=DOL) -> ") + s +
2393              ", exp DOL12.50");
2394    }
2395    s.remove();
2396    if (fmt.getPositivePrefix(s) != UnicodeString("DOL")) {
2397        errln(UnicodeString("FAIL: (intlcurrency=DOL).getPositivePrefix -> ") +
2398              s + ", exp DOL");
2399    }
2400    sym.setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol, "USD");
2401
2402    // Since the pattern logic has changed, make sure that patterns round
2403    // trip properly.  Test stream in/out integrity too.
2404    int32_t n;
2405    const Locale* avail = NumberFormat::getAvailableLocales(n);
2406    static const char* type[] = {
2407        "",
2408        "$ ",
2409        "% ",
2410    };
2411    for (int i=0; i<n; ++i) {
2412        for (int j=0; j<3; ++j) {
2413            status = U_ZERO_ERROR;
2414            NumberFormat *nf;
2415            switch (j) {
2416            case 0:
2417                nf = NumberFormat::createInstance(avail[i], status);
2418                failure(status, "createInstance", avail[i]);
2419                break;
2420            case 1:
2421                nf = NumberFormat::createCurrencyInstance(avail[i], status);
2422                failure(status, "createCurrencyInstance", avail[i]);
2423                break;
2424            default:
2425                nf = NumberFormat::createPercentInstance(avail[i], status);
2426                failure(status, "createPercentInstance", avail[i]);
2427                break;
2428            }
2429            if (U_FAILURE(status)) {
2430                continue;
2431            }
2432            DecimalFormat *df = (DecimalFormat*) nf;
2433
2434            // Test toPattern/applyPattern round trip
2435            UnicodeString pat;
2436            df->toPattern(pat);
2437            DecimalFormatSymbols symb(avail[i], status);
2438            failure(status, "Construct DecimalFormatSymbols", avail[i]);
2439            DecimalFormat f2(pat, symb, status);
2440            if (failure(status,
2441                        UnicodeString("Construct DecimalFormat(") + pat + ")")) {
2442                continue;
2443            }
2444            if (*df != f2) {
2445                UnicodeString l, p;
2446                errln(UnicodeString("FAIL: ") + type[j] + avail[i].getDisplayName(l) +
2447                      " -> \"" + pat +
2448                      "\" -> \"" + f2.toPattern(p) + "\"");
2449            } else {
2450                UnicodeString l, p;
2451                logln(UnicodeString("PASS: ") + type[j] + avail[i].getDisplayName(l) +
2452                      " -> \"" + pat +
2453                      "\"");
2454            }
2455
2456            // Test toLocalizedPattern/applyLocalizedPattern round trip
2457// TODO(refactor): don't worry about localized patterns for now.
2458//            df->toLocalizedPattern(pat);
2459//           f2.applyLocalizedPattern(pat, status);
2460            failure(status,
2461                    UnicodeString("applyLocalizedPattern(") + pat + ")", avail[i]);
2462            if (U_FAILURE(status)) {
2463                continue;
2464            }
2465
2466// TODO(refactor): don't worry about localized patterns for now.
2467            // Make sure we set the currency attributes appropriately
2468//            if (j == 1) {   // Currency format
2469//                f2.setCurrency(f2.getCurrency(), status);
2470//            }
2471            failure(status,
2472                    UnicodeString("setCurrency() for (") + pat + ")", avail[i]);
2473            if (U_FAILURE(status)) {
2474                continue;
2475            }
2476
2477            if (*df != f2) {
2478                UnicodeString l, p;
2479                errln(UnicodeString("FAIL: ") + type[j] + avail[i].getDisplayName(l) +
2480                      " -> localized \"" + pat +
2481                      "\" -> \"" + f2.toPattern(p) + "\"");
2482            }
2483
2484            delete nf;
2485
2486            // Test writeObject/readObject round trip
2487            // NOT ON ICU -- Java only
2488        }
2489    }
2490}
2491
2492/**
2493 * May 17 1999 sync up - liu
2494 * DecimalFormat.parse() fails for mulipliers 2^n.
2495 */
2496void NumberFormatRegressionTest::Test4216742(void) {
2497    UErrorCode status = U_ZERO_ERROR;
2498    DecimalFormat *fmt = (DecimalFormat*) NumberFormat::createInstance(Locale::getUS(), status);
2499    if (failure(status, "createInstance", Locale::getUS(), TRUE)){
2500        delete fmt;
2501        return;
2502    };
2503    int32_t DATA[] = { INT32_MIN, INT32_MAX, -100000000, 100000000 };
2504    int DATA_length = UPRV_LENGTHOF(DATA);
2505    for (int i=0; i<DATA_length; ++i) {
2506        UnicodeString str((UnicodeString)"" + DATA[i]);
2507        for (int m = 1; m <= 100; m++) {
2508            fmt->setMultiplier(m);
2509            Formattable num;
2510            fmt->parse(str, num, status);
2511            failure(status, "parse", Locale::getUS());
2512            if (num.getType() != Formattable::kLong &&
2513                num.getType() != Formattable::kDouble) {
2514                errln(UnicodeString("FAIL: Wanted number, got ") +
2515                      toString(num));
2516            } else {
2517                double d = num.getType() == Formattable::kDouble ?
2518                    num.getDouble() : (double) num.getLong();
2519                if ((d > 0) != (DATA[i] > 0)) {
2520                    errln(UnicodeString("\"") + str + "\" parse(x " +
2521                          fmt->getMultiplier() +
2522                          ") => " + toString(num));
2523                }
2524            }
2525        }
2526    }
2527    delete fmt;
2528}
2529
2530/**
2531 * May 17 1999 sync up - liu
2532 * DecimalFormat formats 1.001 to "1.00" instead of "1" with 2 fraction
2533 * digits.
2534 */
2535void NumberFormatRegressionTest::Test4217661(void) {
2536    const double D[] = {  0.001, 1.001, 0.006,  1.006 };
2537    const char*  S[] = { "0",   "1",   "0.01", "1.01" };
2538    int D_length = UPRV_LENGTHOF(D);
2539    UErrorCode status = U_ZERO_ERROR;
2540    NumberFormat *fmt = NumberFormat::createInstance(Locale::getUS(), status);
2541    if (failure(status, "createInstance", Locale::getUS(), TRUE)){
2542        delete fmt;
2543        return;
2544    };
2545    fmt->setMaximumFractionDigits(2);
2546    for (int i=0; i<D_length; i++) {
2547        UnicodeString s;
2548        fmt->format(D[i], s);
2549        if (s != UnicodeString(S[i])) {
2550            errln(UnicodeString("FAIL: Got ") + s + ", exp " + S[i]);
2551        }
2552    }
2553    delete fmt;
2554}
2555
2556/**
2557 * alphaWorks upgrade
2558 */
2559void NumberFormatRegressionTest::Test4161100(void) {
2560    UErrorCode status = U_ZERO_ERROR;
2561    NumberFormat *nf = NumberFormat::createInstance(Locale::getUS(), status);
2562    if (failure(status, "createInstance", Locale::getUS(), TRUE)){
2563        delete nf;
2564        return;
2565    };
2566    nf->setMinimumFractionDigits(1);
2567    nf->setMaximumFractionDigits(1);
2568    double a = -0.09;
2569    UnicodeString s;
2570    nf->format(a, s);
2571    UnicodeString pat;
2572    logln(UnicodeString() + a + " x " +
2573          ((DecimalFormat*) nf)->toPattern(pat) + " = " + s);
2574    if (s != UnicodeString("-0.1")) {
2575        errln("FAIL");
2576    }
2577    delete nf;
2578}
2579
2580/**
2581 * June 16 1999 sync up - liu
2582 * Formatting .5 rounds to "1" instead of "0". (Regression in 1.2.2 RC1)
2583 */
2584void NumberFormatRegressionTest::Test4243011(void) {
2585    UErrorCode status = U_ZERO_ERROR;
2586    DecimalFormatSymbols sym(Locale::getUS(), status);
2587    failure(status, "DecimalFormatSymbols ct", Locale::getUS());
2588    DecimalFormat fmt(UnicodeString("0."), sym, status);
2589
2590    if (!failure(status, "DecimalFormat ct", Locale::getUS())) {
2591        const double NUM[] = {  -2.5,  -1.5,  -0.5,  0.5,  1.5,  2.5,  3.5,  4.5 };
2592        const char*  STR[] = { "-2.", "-2.", "-0.", "0.", "2.", "2.", "4.", "4." };
2593        int32_t N = UPRV_LENGTHOF(NUM);
2594
2595        for (int32_t i=0; i<N; ++i) {
2596            UnicodeString str;
2597            UnicodeString exp(STR[i]);
2598            FieldPosition pos;
2599            fmt.format(NUM[i], str, pos);
2600            if (str == exp) {
2601                logln(UnicodeString("Ok   ") + NUM[i] + " x 0. = " + str);
2602            } else {
2603                errln(UnicodeString("FAIL ") + NUM[i] + " x 0. = " + str +
2604                      ", want " + exp);
2605            }
2606        }
2607    }
2608}
2609
2610/**
2611 * June 16 1999 sync up - liu
2612 * format(0.0) gives "0.1" if preceded by parse("99.99").
2613 * (Regression in 1.2.2 RC1)
2614 */
2615void NumberFormatRegressionTest::Test4243108(void) {
2616    UErrorCode status = U_ZERO_ERROR;
2617    DecimalFormatSymbols sym(Locale::getUS(), status);
2618    failure(status, "DecimalFormatSymbols ct", Locale::getUS());
2619    DecimalFormat fmt(UnicodeString("#.#"), sym, status);
2620    if (failure(status, "DecimalFormat ct", Locale::getUS())) {
2621        return;
2622    }
2623
2624    UnicodeString str;
2625    FieldPosition pos;
2626
2627    fmt.format(0.0, str, pos);
2628    UnicodeString exp("0");
2629    if (str == exp) {
2630        logln(UnicodeString("Ok   0.0 x #.# = ") + str);
2631    } else {
2632        errln(UnicodeString("FAIL 0.0 x #.# = ") + str +
2633              ", want " + exp);
2634    }
2635
2636    str = "99.99";
2637    Formattable val;
2638    fmt.parse(str, val, status);
2639    failure(status, "DecimalFormat.parse(99.99)", Locale::getUS());
2640    if (val.getType() == Formattable::kDouble &&
2641        val.getDouble() == 99.99) {
2642        logln(UnicodeString("Ok   99.99 / #.# = ") + toString(val));
2643    } else {
2644        errln(UnicodeString("FAIL 99.99 / #.# = ") + toString(val) +
2645              ", want " + 99.99);
2646    }
2647
2648    str.remove();
2649    fmt.format(0.0, str, pos);
2650    if (str == exp) {
2651        logln(UnicodeString("Ok   0.0 x #.# = ") + str);
2652    } else {
2653        errln(UnicodeString("FAIL 0.0 x #.# = ") + str +
2654              ", want " + exp);
2655    }
2656}
2657
2658
2659/**
2660 * DateFormat should call setIntegerParseOnly(TRUE) on adopted
2661 * NumberFormat objects.
2662 */
2663void NumberFormatRegressionTest::TestJ691(void) {
2664    UErrorCode status = U_ZERO_ERROR;
2665    Locale loc("fr", "CH");
2666
2667    // set up the input date string & expected output
2668    UnicodeString udt("11.10.2000", "");
2669    UnicodeString exp("11.10.00", "");
2670
2671    // create a Calendar for this locale
2672    Calendar *cal = Calendar::createInstance(loc, status);
2673    if (U_FAILURE(status)) {
2674        dataerrln("FAIL: Calendar::createInstance() returned " + (UnicodeString)u_errorName(status));
2675        return;
2676    }
2677
2678    // create a NumberFormat for this locale
2679    NumberFormat *nf = NumberFormat::createInstance(loc, status);
2680    if (U_FAILURE(status)) {
2681        dataerrln("FAIL: NumberFormat::createInstance() returned " + (UnicodeString)u_errorName(status));
2682        return;
2683    }
2684
2685    // *** Here's the key: We don't want to have to do THIS:
2686    // nf->setParseIntegerOnly(TRUE);
2687    // or this (with changes to fr_CH per cldrbug:9370):
2688    // nf->setGroupingUsed(FALSE);
2689    // so they are done in DateFormat::adoptNumberFormat
2690
2691    // create the DateFormat
2692    DateFormat *df = DateFormat::createDateInstance(DateFormat::kShort, loc);
2693    if (U_FAILURE(status)) {
2694        errln("FAIL: DateFormat::createInstance() returned " + (UnicodeString)u_errorName(status));
2695        return;
2696    }
2697
2698    df->adoptCalendar(cal);
2699    df->adoptNumberFormat(nf);
2700
2701    // set parsing to lenient & parse
2702    df->setLenient(TRUE);
2703    UDate ulocdat = df->parse(udt, status);
2704
2705    // format back to a string
2706    UnicodeString outString;
2707    df->format(ulocdat, outString);
2708
2709    if (outString != exp) {
2710        errln("FAIL: " + udt + " => " + outString);
2711    }
2712
2713    delete df;
2714}
2715
2716//---------------------------------------------------------------------------
2717//
2718//   Error Checking / Reporting macros
2719//
2720//---------------------------------------------------------------------------
2721#define TEST_CHECK_STATUS(status) { \
2722    if (U_FAILURE(status)) { \
2723        if (status == U_MISSING_RESOURCE_ERROR) { \
2724            dataerrln("File %s, Line %d: status=%s", __FILE__, __LINE__, u_errorName(status)); \
2725        } else { \
2726            errln("File %s, Line %d: status=%s", __FILE__, __LINE__, u_errorName(status)); \
2727        } return; \
2728    }}
2729
2730#define TEST_ASSERT(expr) \
2731    if ((expr)==FALSE) {\
2732        errln("File %s, line %d: Assertion Failed: " #expr "\n", __FILE__, __LINE__);\
2733    }
2734#define TEST_ASSERT_EQUALS(x,y)                  \
2735    {                                                                     \
2736      char _msg[1000]; \
2737      int32_t len = sprintf (_msg,"File %s, line %d: Assertion Failed: " #x "==" #y "\n", __FILE__, __LINE__); \
2738      (void)len;                                                         \
2739      U_ASSERT(len < (int32_t) sizeof(_msg));                            \
2740      assertEquals((const char*) _msg, x,y);                             \
2741    }
2742
2743
2744// Ticket 8199:  Parse failure for numbers in the range of 1E10 - 1E18
2745
2746void NumberFormatRegressionTest::Test8199(void) {
2747    UErrorCode status = U_ZERO_ERROR;
2748    NumberFormat *nf = NumberFormat::createInstance(Locale::getEnglish(), status);
2749    if (nf == NULL) {
2750        dataerrln("Fail: NumberFormat::createInstance(Locale::getEnglish(), status)");
2751        return;
2752    }
2753    TEST_CHECK_STATUS(status);
2754
2755    // Note:  Retrieving parsed values from a Formattable as a reduced-precision type
2756    //        should always truncate, no other rounding scheme.
2757
2758    UnicodeString numStr = "1000000000.6";   // 9 zeroes
2759    Formattable val;
2760    nf->parse(numStr, val, status);
2761    TEST_CHECK_STATUS(status);
2762    TEST_ASSERT(Formattable::kDouble == val.getType());
2763    TEST_ASSERT(1000000000 == val.getInt64(status));
2764    TEST_CHECK_STATUS(status);
2765    TEST_ASSERT(1000000000.6 == val.getDouble(status));
2766    TEST_CHECK_STATUS(status);
2767
2768    numStr = "100000000000000001.1";   // approx 1E17, parses as a double rather
2769                                       //   than int64 because of the fraction
2770                                       //   even though int64 is more precise.
2771    nf->parse(numStr, val, status);
2772    TEST_CHECK_STATUS(status);
2773    TEST_ASSERT(Formattable::kDouble == val.getType());
2774    TEST_ASSERT(100000000000000001LL == val.getInt64(status));
2775    TEST_CHECK_STATUS(status);
2776    TEST_ASSERT(100000000000000000.0 == val.getDouble(status));
2777    TEST_CHECK_STATUS(status);
2778
2779    numStr = "1E17";  // Parses with the internal decimal number having non-zero exponent
2780    nf->parse(numStr, val, status);
2781    TEST_CHECK_STATUS(status);
2782    TEST_ASSERT(Formattable::kInt64 == val.getType());
2783    TEST_ASSERT(100000000000000000LL == val.getInt64());
2784    TEST_ASSERT(1.0E17 == val.getDouble(status));
2785    TEST_CHECK_STATUS(status);
2786
2787    numStr = "9223372036854775807";  // largest int64_t
2788    nf->parse(numStr, val, status);
2789    TEST_CHECK_STATUS(status);
2790    TEST_ASSERT(Formattable::kInt64 == val.getType());
2791    TEST_ASSERT(9223372036854775807LL == val.getInt64());
2792    // In the following check, note that a substantial range of integers will
2793    //    convert to the same double value.  There are also platform variations
2794    //    in the rounding at compile time of double constants.
2795    TEST_ASSERT(9223372036854775808.0 >= val.getDouble(status));
2796    TEST_ASSERT(9223372036854774700.0 <= val.getDouble(status));
2797    TEST_CHECK_STATUS(status);
2798
2799    numStr = "-9223372036854775808";  // smallest int64_t
2800    nf->parse(numStr, val, status);
2801    TEST_CHECK_STATUS(status);
2802    TEST_ASSERT(Formattable::kInt64 == val.getType());
2803    // TEST_ASSERT(-9223372036854775808LL == val.getInt64()); // Compiler chokes on constant.
2804    TEST_ASSERT((int64_t)0x8000000000000000LL == val.getInt64());
2805    TEST_ASSERT(-9223372036854775808.0 == val.getDouble(status));
2806    TEST_CHECK_STATUS(status);
2807
2808    numStr = "9223372036854775808";  // largest int64_t + 1
2809    nf->parse(numStr, val, status);
2810    TEST_CHECK_STATUS(status);
2811    TEST_ASSERT(Formattable::kDouble == val.getType());
2812    TEST_ASSERT(9223372036854775807LL == val.getInt64(status));
2813    TEST_ASSERT(status == U_INVALID_FORMAT_ERROR);
2814    status = U_ZERO_ERROR;
2815    TEST_ASSERT(9223372036854775810.0 == val.getDouble(status));
2816    TEST_CHECK_STATUS(status);
2817
2818    numStr = "-9223372036854775809";  // smallest int64_t - 1
2819    nf->parse(numStr, val, status);
2820    TEST_CHECK_STATUS(status);
2821    TEST_ASSERT(Formattable::kDouble == val.getType());
2822    // TEST_ASSERT(-9223372036854775808LL == val.getInt64(status));  // spurious compiler warnings
2823    TEST_ASSERT((int64_t)0x8000000000000000LL == val.getInt64(status));
2824    TEST_ASSERT(status == U_INVALID_FORMAT_ERROR);
2825    status = U_ZERO_ERROR;
2826    TEST_ASSERT(-9223372036854775810.0 == val.getDouble(status));
2827    TEST_CHECK_STATUS(status);
2828
2829    // Test values near the limit of where doubles can represent all integers.
2830    // The implementation strategy of getInt64() changes at this boundary.
2831    // Strings to be parsed include a decimal fraction to force them to be
2832    //   parsed as doubles rather than ints.  The fraction is discarded
2833    //   from the parsed double value because it is beyond what can be represented.
2834
2835    status = U_ZERO_ERROR;
2836    numStr = "9007199254740991.1";  // largest 53 bit int
2837    nf->parse(numStr, val, status);
2838    TEST_CHECK_STATUS(status);
2839    // printf("getInt64() returns %lld\n", val.getInt64(status));
2840    TEST_ASSERT(Formattable::kDouble == val.getType());
2841    TEST_ASSERT(9007199254740991LL == val.getInt64(status));
2842    TEST_ASSERT(9007199254740991.0 == val.getDouble(status));
2843    TEST_CHECK_STATUS(status);
2844
2845    status = U_ZERO_ERROR;
2846    numStr = "9007199254740992.1";  // 54 bits for the int part.
2847    nf->parse(numStr, val, status);
2848    TEST_CHECK_STATUS(status);
2849    TEST_ASSERT(Formattable::kDouble == val.getType());
2850    TEST_ASSERT(9007199254740992LL == val.getInt64(status));
2851    TEST_ASSERT(9007199254740992.0 == val.getDouble(status));
2852    TEST_CHECK_STATUS(status);
2853
2854    status = U_ZERO_ERROR;
2855    numStr = "9007199254740993.1";  // 54 bits for the int part.  Double will round
2856    nf->parse(numStr, val, status); //    the ones digit, putting it up to ...994
2857    TEST_CHECK_STATUS(status);
2858    TEST_ASSERT(Formattable::kDouble == val.getType());
2859    TEST_ASSERT_EQUALS((int64_t)9007199254740993LL,val.getInt64(status));
2860    TEST_ASSERT_EQUALS((double)9007199254740994.0,(double)val.getDouble(status));
2861    TEST_CHECK_STATUS(status);
2862
2863    delete nf;
2864}
2865
2866void NumberFormatRegressionTest::Test9109(void) {
2867    UErrorCode status = U_ZERO_ERROR;
2868    Formattable val;
2869    ParsePosition pos;
2870    DecimalFormat fmt("+##", status);
2871    if (U_FAILURE(status)) {
2872        dataerrln("Failed to create DecimalFormat with pattern '+##' - %s", u_errorName(status));
2873        return;
2874    }
2875
2876    fmt.setLenient(TRUE);
2877    UnicodeString text("123");
2878    int32_t expected = 123;
2879    int32_t expos = 3;
2880
2881    fmt.parse(text, val, pos);
2882    if (pos.getErrorIndex() >= 0) {
2883        errln(UnicodeString("Parse failure at ") + pos.getErrorIndex());
2884    } else if (val.getLong() != 123) {
2885        errln(UnicodeString("Incorrect parse result: ") + val.getLong() + " expected: " + expected);
2886    } else if (pos.getIndex() != 3) {
2887        errln(UnicodeString("Incorrect parse position: ") + pos.getIndex() + " expected: " + expos);
2888    }
2889}
2890
2891
2892void NumberFormatRegressionTest::Test9780(void) {
2893    UErrorCode status = U_ZERO_ERROR;
2894    NumberFormat *nf = NumberFormat::createInstance(Locale::getUS(), status);
2895    if (failure(status, "NumberFormat::createInstance", TRUE)){
2896        delete nf;
2897        return;
2898    };
2899    DecimalFormat *df = dynamic_cast<DecimalFormat *>(nf);
2900    if(df == NULL) {
2901        errln("DecimalFormat needed to continue");
2902        return;
2903    }
2904    df->setParseIntegerOnly(TRUE);
2905
2906    {
2907      Formattable n;
2908      ParsePosition pos(0);
2909      UnicodeString toParse("1,234","");
2910      df->parse(toParse, n, pos);
2911      if (n.getType() != Formattable::kLong
2912          || n.getLong() != 1234) {
2913        errln(UnicodeString("FAIL: parse(\"") + toParse + UnicodeString("\") returns ") + toString(n));
2914      }
2915    }
2916    // should still work in lenient mode, just won't get fastpath
2917    df->setLenient(TRUE);
2918    {
2919      Formattable n;
2920      ParsePosition pos(0);
2921      UnicodeString toParse("1,234","");
2922      df->parse(toParse, n, pos);
2923      if (n.getType() != Formattable::kLong
2924          || n.getLong() != 1234) {
2925        errln(UnicodeString("FAIL: parse(\"") + toParse + UnicodeString("\") returns ") + toString(n));
2926      }
2927    }
2928    delete nf;
2929}
2930
2931
2932void NumberFormatRegressionTest::Test9677(void) {
2933  static const UChar pattern[] = { 0x23,0x23,0x23,0x23,0x2E,0x23,0x23,0x23,0x23,0 }; // "####.####"
2934  static const UChar positivePrefix[] = { 0x40,0 }; // "@"
2935  static const UChar negativePrefix[] = { 0x6E,0 }; // "n"
2936  static const UChar text[] = { 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0 }; // 123456789
2937  static const UChar text2[] = { 0x6E, 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0 }; // n123456789
2938
2939  UErrorCode status = U_ZERO_ERROR;
2940  LocalUNumberFormatPointer f(unum_open(UNUM_DEFAULT, NULL, 0, "en_US", NULL, &status));
2941  if (U_FAILURE(status)) {
2942      dataerrln("Failure opening unum_open");
2943      return;
2944  }
2945
2946  if (U_SUCCESS(status)) {
2947    unum_applyPattern(f.getAlias(), FALSE, pattern, -1, NULL, &status);
2948    unum_setTextAttribute(f.getAlias(), UNUM_POSITIVE_PREFIX, positivePrefix, -1, &status);
2949    assertSuccess("setting attributes", status);
2950  }
2951
2952  if(U_SUCCESS(status)) {
2953    int32_t n = unum_parse(f.getAlias(), text, -1, NULL, &status);
2954    logln("unum_parse status %s, result %d\n", u_errorName(status), n);
2955
2956    if(U_FAILURE(status)) {
2957        logln("Got expected parse error %s\n", u_errorName(status));
2958        status = U_ZERO_ERROR;
2959    } else {
2960        errln("FAIL: unum_parse status %s, result %d - expected failure\n", u_errorName(status), n);
2961    }
2962  }
2963
2964  if (U_SUCCESS(status)) {
2965    unum_setTextAttribute(f.getAlias(), UNUM_POSITIVE_PREFIX, NULL, 0, &status);
2966    assertSuccess("setting attributes", status);
2967    logln("removed positive prefix");
2968  }
2969
2970  if(U_SUCCESS(status)) {
2971    int32_t n = unum_parse(f.getAlias(), text, -1, NULL, &status);
2972    logln("unum_parse status %s, result %d\n", u_errorName(status), n);
2973
2974    if(U_FAILURE(status)) {
2975        errln("FAIL: with pos prefix removed, parse error %s\n", u_errorName(status));
2976        status = U_ZERO_ERROR;
2977    } else {
2978        if(n!=123456789) {
2979          errln("FAIL: with pos prefix removed , unum_parse status %s, result %d expected 123456789\n", u_errorName(status), n);
2980        } else {
2981          logln("PASS: with pos prefix removed , unum_parse status %s, result %d expected 123456789\n", u_errorName(status),n);
2982        }
2983    }
2984  }
2985
2986  if(U_SUCCESS(status)) {
2987    int32_t n = unum_parse(f.getAlias(), text2, -1, NULL, &status);
2988    logln("unum_parse status %s, result %d\n", u_errorName(status), n);
2989
2990    if(U_FAILURE(status)) {
2991        logln("text2: Got expected parse error %s\n", u_errorName(status));
2992        status = U_ZERO_ERROR;
2993    } else {
2994        errln("FAIL: text2: unum_parse status %s, result %d - expected failure\n", u_errorName(status), n);
2995    }
2996  }
2997
2998  if (U_SUCCESS(status)) {
2999    unum_setTextAttribute(f.getAlias(), UNUM_NEGATIVE_PREFIX, negativePrefix, -1, &status);
3000    assertSuccess("setting attributes", status);
3001    logln("Set a different neg prefix prefix");
3002  }
3003
3004  if(U_SUCCESS(status)) {
3005    int32_t n = unum_parse(f.getAlias(), text2, -1, NULL, &status);
3006    logln("unum_parse status %s, result %d\n", u_errorName(status), n);
3007
3008    if(U_FAILURE(status)) {
3009        errln("FAIL: with different neg prefix , parse error %s\n", u_errorName(status));
3010        status = U_ZERO_ERROR;
3011    } else {
3012;
3013        if(n!=-123456789) {
3014          errln("FAIL: with different neg prefix , unum_parse status %s, result %d expected -123456789\n", u_errorName(status), n);
3015        } else {
3016          logln("PASS: with different neg prefix , unum_parse status %s, result %d expected -123456789\n", u_errorName(status), n);
3017        }
3018    }
3019  }
3020}
3021
3022void NumberFormatRegressionTest::Test10361(void) {
3023    // DecimalFormat/NumberFormat were artificially limiting the number of digits,
3024    //    preventing formatting of big decimals.
3025    UErrorCode status = U_ZERO_ERROR;
3026    DecimalFormatSymbols symbols(Locale::getEnglish(), status);
3027    LocalPointer<DecimalFormat> df(new DecimalFormat("###.##", symbols, status), status);
3028    TEST_CHECK_STATUS(status);
3029
3030    // Create a decimal number with a million digits.
3031    const int32_t NUMSIZE=1000000;
3032    char *num = new char[NUMSIZE];
3033    for (int32_t i=0; i<NUMSIZE; i++) {
3034        num[i] = '0' + (i+1) % 10;
3035    }
3036    num[NUMSIZE-3] = '.';
3037    num[NUMSIZE-1] = 0;
3038
3039    UnicodeString    s;
3040    Formattable      fmtable;
3041    fmtable.setDecimalNumber(num, status);
3042    TEST_CHECK_STATUS(status);
3043
3044    FieldPosition pos(UNUM_DECIMAL_SEPARATOR_FIELD);
3045    df->format(fmtable, s, pos, status);
3046    TEST_CHECK_STATUS(status);
3047    TEST_ASSERT(999999 == s.length());
3048    TEST_ASSERT(999997 == pos.getBeginIndex());
3049    TEST_ASSERT(999998 == pos.getEndIndex());
3050
3051    UnicodeString expected(num, -1, US_INV);
3052    TEST_ASSERT(expected == s);
3053    delete [] num;
3054}
3055
3056#endif /* #if !UCONFIG_NO_FORMATTING */
3057