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