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