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