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