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