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