• 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 MyNumberFormatTest* 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 
854     uloc_canonicalize("pt_PT@currency=PTE", loc, 256, &status);
855     Locale de(loc);
856     LocalPointer<NumberFormat> nf(NumberFormat::createCurrencyInstance(de, status));
857     if(U_FAILURE(status)) {
858         dataerrln("Error creating DecimalFormat: %s", u_errorName(status));
859         return;
860     }
861     DecimalFormat *df = dynamic_cast<DecimalFormat *>(nf.getAlias());
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 }
891 /* @bug 4070798
892  * Number format data rounding errors for locale FR
893  */
Test4070798(void)894 void NumberFormatRegressionTest::Test4070798 (void)
895 {
896     NumberFormat *formatter;
897     UnicodeString tempString;
898 
899     /* User error :
900     String expectedDefault = "-5\u202f789,987";
901     String expectedCurrency = "5\u202f789,98\u00a0F";
902     String expectedPercent = "-578\u202f998%";
903     */
904     UChar chars1 [] = {
905         0x2d, 0x35, 0x202f, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x38, 0x38
906     };
907     UChar chars2 [] = {
908         0x35, 0x202f, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x39, 0x00a0, 0x46
909     };
910     UChar chars3 [] = {
911         0x2d, 0x35, 0x37, 0x38, 0x202f, 0x39, 0x39, 0x39, 0x00a0, 0x25
912     };
913     UnicodeString expectedDefault(chars1, 10, 10);
914     UnicodeString expectedCurrency(chars2, 10, 10);
915     UnicodeString expectedPercent(chars3, 10, 10);
916 
917     UErrorCode status = U_ZERO_ERROR;
918     char loc[256]={0};
919     int len = uloc_canonicalize("fr_FR@currency=FRF", loc, 256, &status);
920     (void)len;  // Suppress set but not used warning.
921     formatter = NumberFormat::createInstance(Locale(loc), status);
922     if(U_FAILURE(status)) {
923       dataerrln("Error creating DecimalFormat: %s", u_errorName(status));
924       delete formatter;
925       return;
926     }
927     failure(status, "NumberFormat::createInstance", loc);
928     tempString = formatter->format (-5789.9876, tempString);
929 
930     if (tempString == expectedDefault) {
931         logln ("Bug 4070798 default test passed.");
932     } else {
933         errln(UnicodeString("Failed:") +
934         " Expected " + expectedDefault +
935         " Received " + tempString );
936     }
937     delete formatter;
938     len = uloc_canonicalize("fr_FR@currency=FRF", loc, 256, &status);
939     formatter = NumberFormat::createCurrencyInstance(loc, status);
940     failure(status, "NumberFormat::createCurrencyInstance", loc);
941     tempString.remove();
942     tempString = formatter->format( 5789.9876, tempString );
943 
944     if (tempString == expectedCurrency) {
945         logln ("Bug 4070798 currency test passed.");
946     } else {
947         errln(UnicodeString("Failed:") +
948         " Expected " + expectedCurrency +
949         " Received " + tempString );
950     }
951     delete formatter;
952 
953     uloc_canonicalize("fr_FR@currency=FRF", loc, 256, &status);
954     formatter = NumberFormat::createPercentInstance(Locale(loc), status);
955     failure(status, "NumberFormat::createPercentInstance", loc);
956     tempString.remove();
957     tempString = formatter->format (-5789.9876, tempString);
958 
959     if (tempString == expectedPercent) {
960         logln ("Bug 4070798 percentage test passed.");
961     } else {
962         errln(UnicodeString("Failed:") +
963         " Expected " + expectedPercent +
964         " Received " + tempString );
965     }
966 
967     delete formatter;
968 }
969 /* @bug 4071005
970  * Data rounding errors for French (Canada) locale
971  */
Test4071005(void)972 void NumberFormatRegressionTest::Test4071005 (void)
973 {
974     NumberFormat *formatter;
975     UnicodeString tempString;
976     /* User error :
977     String expectedDefault = "-5\u00a0789,987";
978     String expectedCurrency = "5\u00a0789,98\u00a0$\u00a0CA";
979     String expectedPercent = "-578\u00a0998%";
980     */
981     UChar chars1 [] = {
982         0x2d, 0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x38, 0x38
983     };
984     UChar chars2 [] = {
985         0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x39, 0x00a0, 0x24, 0x00a0, 0x43, 0x41
986     };
987     UChar chars3 [] = {
988         0x2d, 0x35, 0x37, 0x38, 0x00a0, 0x39, 0x39, 0x39, 0x00a0, 0x25
989     };
990     UnicodeString expectedDefault(chars1, 10, 10);
991     UnicodeString expectedCurrency(chars2, 13, 13);
992     UnicodeString expectedPercent(chars3, 10, 10);
993 
994     UErrorCode status = U_ZERO_ERROR;
995     formatter = NumberFormat::createInstance(Locale::getCanadaFrench(), status);
996     if (failure(status, "NumberFormat::createInstance", Locale::getCanadaFrench(), TRUE)){
997         delete formatter;
998         return;
999     }
1000     tempString = formatter->format (-5789.9876, tempString);
1001 
1002     if (tempString == expectedDefault) {
1003         logln ("Bug 4071005 default test passed.");
1004     } else {
1005         errln(UnicodeString("Failed:") +
1006         " Expected " + expectedDefault +
1007         " Received " + tempString );
1008     }
1009     delete formatter;
1010 
1011     formatter = NumberFormat::createCurrencyInstance(Locale::getCanadaFrench(), status);
1012     failure(status, "NumberFormat::createCurrencyInstance", Locale::getCanadaFrench());
1013     tempString.remove();
1014     tempString = formatter->format( 5789.9876, tempString );
1015 
1016     if (tempString == expectedCurrency) {
1017         logln ("Bug 4071005 currency test assed.");
1018     } else {
1019         errln(UnicodeString("Failed:") +
1020         " Expected " + expectedCurrency +
1021         " Received " + tempString );
1022     }
1023     delete formatter;
1024 
1025     formatter = NumberFormat::createPercentInstance(Locale::getCanadaFrench(), status);
1026     failure(status, "NumberFormat::createPercentInstance", Locale::getCanadaFrench());
1027     tempString.remove();
1028     tempString = formatter->format (-5789.9876, tempString);
1029 
1030     if (tempString == expectedPercent) {
1031         logln ("Bug 4071005 percentage test passed.");
1032     } else {
1033         errln(UnicodeString("Failed:") +
1034         " Expected " + expectedPercent +
1035         " Received " + tempString );
1036     }
1037 
1038     delete formatter;
1039 }
1040 
1041 /* @bug 4071014
1042  * Data rounding errors for German (Germany) locale
1043  */
Test4071014(void)1044 void NumberFormatRegressionTest::Test4071014 (void)
1045 {
1046     NumberFormat *formatter;
1047     UnicodeString tempString;
1048     /* user error :
1049     String expectedDefault = "-5.789,987";
1050     String expectedCurrency = "5.789,98 DM";
1051     String expectedPercent = "-578.998%";
1052     */
1053     UnicodeString expectedDefault("-5.789,988");
1054     UnicodeString expectedCurrency("5.789,99\\u00A0DM");
1055     UnicodeString expectedPercent("-578.999\\u00A0%");
1056 
1057     expectedCurrency = expectedCurrency.unescape();
1058     expectedPercent = expectedPercent.unescape();
1059 
1060     UErrorCode status = U_ZERO_ERROR;
1061     char loc[256]={0};
1062     uloc_canonicalize("de_DE@currency=DEM", loc, 256, &status);
1063     formatter = NumberFormat::createInstance(Locale(loc), status);
1064     if (failure(status, "NumberFormat::createInstance", loc, TRUE)){
1065         delete formatter;
1066         return;
1067     }
1068     tempString.remove();
1069     tempString = formatter->format (-5789.9876, tempString);
1070 
1071     if (tempString == expectedDefault) {
1072         logln ("Bug 4071014 default test passed.");
1073     } else {
1074         errln(UnicodeString("Failed:") +
1075         " Expected " + expectedDefault +
1076         " Received " + tempString );
1077     }
1078     delete formatter;
1079     uloc_canonicalize("de_DE@currency=DEM", loc, 256, &status);
1080     formatter = NumberFormat::createCurrencyInstance(Locale(loc), status);
1081     failure(status, "NumberFormat::createCurrencyInstance", loc);
1082     tempString.remove();
1083     tempString = formatter->format( 5789.9876, tempString );
1084 
1085     if (tempString == expectedCurrency) {
1086         logln ("Bug 4071014 currency test assed.");
1087     } else {
1088         errln(UnicodeString("Failed:") +
1089         " Expected " + expectedCurrency +
1090         " Received " + tempString );
1091     }
1092     delete formatter;
1093 
1094     formatter = NumberFormat::createPercentInstance(Locale::getGermany(), status);
1095     failure(status, "NumberFormat::createPercentInstance", Locale::getGermany());
1096     tempString.remove();
1097     tempString = formatter->format (-5789.9876, tempString);
1098 
1099     if (tempString == expectedPercent) {
1100         logln ("Bug 4071014 percentage test passed.");
1101     } else {
1102         errln(UnicodeString("Failed:") +
1103         " Expected " + expectedPercent +
1104         " Received " + tempString );
1105     }
1106 
1107     delete formatter;
1108 }
1109 /* @bug 4071859
1110  * Data rounding errors for Italian locale number formats
1111  */
Test4071859(void)1112 void NumberFormatRegressionTest::Test4071859 (void)
1113 {
1114     NumberFormat *formatter;
1115     UnicodeString tempString;
1116     /* user error :
1117     String expectedDefault = "-5.789,987";
1118     String expectedCurrency = "-L.\\u00A05.789,98";
1119     String expectedPercent = "-578.998%";
1120     */
1121     UnicodeString expectedDefault("-5.789,988");
1122     UnicodeString expectedCurrency("-ITL\\u00A05.790", -1, US_INV);
1123     UnicodeString expectedPercent("-578.999%");
1124     expectedCurrency = expectedCurrency.unescape();
1125 
1126     UErrorCode status = U_ZERO_ERROR;
1127     char loc[256]={0};
1128     uloc_canonicalize("it_IT@currency=ITL", loc, 256, &status);
1129     formatter = NumberFormat::createInstance(Locale(loc), status);
1130     if (failure(status, "NumberFormat::createNumberInstance", TRUE)){
1131         delete formatter;
1132         return;
1133     }
1134     tempString = formatter->format (-5789.9876, tempString);
1135 
1136     if (tempString == expectedDefault) {
1137         logln ("Bug 4071859 default test passed.");
1138     } else {
1139         errln(UnicodeString("Failed:") +
1140         " Expected " + expectedDefault +
1141         " Received " + tempString );
1142     }
1143     delete formatter;
1144     uloc_canonicalize("it_IT@currency=ITL", loc, 256, &status);
1145     formatter = NumberFormat::createCurrencyInstance(Locale(loc), status);
1146     failure(status, "NumberFormat::createCurrencyInstance");
1147     tempString.remove();
1148     tempString = formatter->format( -5789.9876, tempString );
1149 
1150     if (tempString == expectedCurrency) {
1151         logln ("Bug 4071859 currency test assed.");
1152     } else {
1153         errln(UnicodeString("Failed:") +
1154         " Expected " + expectedCurrency +
1155         " Received " + tempString );
1156     }
1157     delete formatter;
1158     uloc_canonicalize("it_IT@currency=ITL", loc, 256, &status);
1159     formatter = NumberFormat::createPercentInstance(Locale(loc), status);
1160     failure(status, "NumberFormat::createPercentInstance");
1161     tempString.remove();
1162     tempString = formatter->format (-5789.9876, tempString);
1163 
1164     if (tempString == expectedPercent) {
1165         logln ("Bug 4071859 percentage test passed.");
1166     } else {
1167         errln(UnicodeString("Failed:") +
1168         " Expected " + expectedPercent +
1169         " Received " + tempString );
1170     }
1171 
1172     delete formatter;
1173 }
1174 /* @bug 4071859
1175  * Test rounding for nearest even.
1176  */
Test4093610(void)1177 void NumberFormatRegressionTest::Test4093610(void)
1178 {
1179     UErrorCode status = U_ZERO_ERROR;
1180     DecimalFormat df("#0.#", status);
1181     if (!failure(status, "new DecimalFormat")) {
1182         UnicodeString s("12.4");
1183         roundingTest(&df, 12.35, s);
1184         roundingTest(&df, 12.45, s);
1185         s = "12.5";
1186         roundingTest(&df, 12.452,s);
1187         s = "12.6";
1188         roundingTest(&df, 12.55, s);
1189         roundingTest(&df, 12.65, s);
1190         s = "12.7";
1191         roundingTest(&df, 12.652,s);
1192         s = "12.8";
1193         roundingTest(&df, 12.75, s);
1194         roundingTest(&df, 12.752,s);
1195         roundingTest(&df, 12.85, s);
1196         s = "12.9";
1197         roundingTest(&df, 12.852,s);
1198         s = "13";
1199         roundingTest(&df, 12.95, s);
1200         roundingTest(&df, 12.952,s);
1201     }
1202 }
1203 
roundingTest(DecimalFormat * df,double x,UnicodeString & expected)1204 void NumberFormatRegressionTest::roundingTest(DecimalFormat *df, double x, UnicodeString& expected)
1205 {
1206     UnicodeString out;
1207     FieldPosition pos(FieldPosition::DONT_CARE);
1208     out = df->format(x, out, pos);
1209     logln(UnicodeString("") + x + " formats with 1 fractional digits to " + out);
1210     if (out != expected) {
1211         dataerrln("FAIL: Expected '%s'; got '%s'", CStr(expected)(), CStr(out)());
1212     }
1213 }
1214 /* @bug 4098741
1215  * Tests the setMaximumFractionDigits limit.
1216  */
Test4098741(void)1217 void NumberFormatRegressionTest::Test4098741(void)
1218 {
1219     //try {
1220     UErrorCode status = U_ZERO_ERROR;
1221     NumberFormat *fmt = NumberFormat::createPercentInstance(status);
1222     if (U_FAILURE(status)) {
1223         dataerrln("Error calling NumberFormat::createPercentInstance");
1224         delete fmt;
1225         return;
1226     }
1227 
1228         fmt->setMaximumFractionDigits(20);
1229         UnicodeString temp;
1230         logln(fmt->format(.001, temp));
1231     /*} catch (Exception foo) {
1232         errln("Bug 4098471 failed with exception thrown : " + foo.getMessage());
1233     }*/
1234     delete fmt;
1235 }
1236 /* @bug 4074454
1237  * Tests illegal pattern exception.
1238  * Fix comment : HShih A31 Part1 will not be fixed and javadoc needs to be updated.
1239  * Part2 has been fixed.
1240  */
Test4074454(void)1241 void NumberFormatRegressionTest::Test4074454(void)
1242 {
1243     //try {
1244     UErrorCode status = U_ZERO_ERROR;
1245     DecimalFormat *fmt = new DecimalFormat("#,#00.00;-#.#", status);
1246     if(U_FAILURE(status)) {
1247       errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
1248       delete fmt;
1249       return;
1250     }
1251     failure(status, "new DecimalFormat");
1252       logln("Inconsistent negative pattern is fine.");
1253         DecimalFormat *newFmt = new DecimalFormat("#,#00.00 p''ieces;-#,#00.00 p''ieces", status);
1254         failure(status, "new DecimalFormat");
1255         UnicodeString tempString;
1256         FieldPosition pos(FieldPosition::DONT_CARE);
1257         tempString = newFmt->format(3456.78, tempString, pos);
1258         if (tempString != UnicodeString("3,456.78 p'ieces"))
1259             dataerrln("Failed!  3456.78 p'ieces expected, but got : " + tempString);
1260     /*} catch (Exception foo) {
1261         errln("An exception was thrown for any inconsistent negative pattern.");
1262     }*/
1263 
1264     delete fmt;
1265     delete newFmt;
1266 }
1267 /* @bug 4099404
1268  * Tests all different comments.
1269  * Response to some comments :
1270  * [1] DecimalFormat.parse API documentation is more than just one line.
1271  * This is not a reproducable doc error in 116 source code.
1272  * [2] See updated javadoc.
1273  * [3] Fixed.
1274  * [4] NumberFormat.parse(String, ParsePosition) : If parsing fails,
1275  * a null object will be returned.  The unchanged parse position also
1276  * reflects an error.
1277  * NumberFormat.parse(String) : If parsing fails, an ParseException
1278  * will be thrown.
1279  * See updated javadoc for more details.
1280  * [5] See updated javadoc.
1281  * [6] See updated javadoc.
1282  * [7] This is a correct behavior if the DateFormat object is linient.
1283  * Otherwise, an IllegalArgumentException will be thrown when formatting
1284  * "January 35".  See GregorianCalendar class javadoc for more details.
1285  */
Test4099404(void)1286 void NumberFormatRegressionTest::Test4099404(void)
1287 {
1288     //try {
1289         UErrorCode status = U_ZERO_ERROR;
1290         DecimalFormat *fmt = new DecimalFormat(UnicodeString("000.0#0"), status);
1291         if(! U_FAILURE(status))
1292             errln(UnicodeString("Bug 4099404 failed applying illegal pattern \"000.0#0\""));
1293     /*} catch (Exception foo) {
1294         logln("Bug 4099404 pattern \"000.0#0\" passed");
1295     }*/
1296     delete fmt;
1297     fmt = 0;
1298         //try {
1299         fmt = new DecimalFormat(UnicodeString("0#0.000"), status);
1300         if( !U_FAILURE(status))
1301            errln("Bug 4099404 failed applying illegal pattern \"0#0.000\"");
1302     /*} catch (Exception foo) {
1303         logln("Bug 4099404 pattern \"0#0.000\" passed");
1304     }*/
1305 
1306     delete fmt;
1307 }
1308 /* @bug 4101481
1309  * DecimalFormat.applyPattern doesn't set minimum integer digits
1310  */
Test4101481(void)1311 void NumberFormatRegressionTest::Test4101481(void)
1312 {
1313     UErrorCode status = U_ZERO_ERROR;
1314     DecimalFormat *sdf = new DecimalFormat(UnicodeString("#,##0"), status);
1315     if(U_FAILURE(status)) {
1316       errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
1317       delete sdf;
1318       return;
1319     }
1320     failure(status, "new DecimalFormat");
1321     if (sdf->getMinimumIntegerDigits() != 1)
1322         errln(UnicodeString("Minimum integer digits : ") + sdf->getMinimumIntegerDigits());
1323     delete sdf;
1324 }
1325 /* @bug 4052223 (API addition request A27)
1326  * Tests ParsePosition.setErrorPosition() and ParsePosition.getErrorPosition().
1327  */
Test4052223(void)1328 void NumberFormatRegressionTest::Test4052223(void)
1329 {
1330     //try {
1331     UErrorCode status = U_ZERO_ERROR;
1332         DecimalFormat *fmt = new DecimalFormat(UnicodeString("#,#00.00"), status);
1333         if(U_FAILURE(status)) {
1334           errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
1335           delete fmt;
1336           return;
1337         }
1338         failure(status, "new DecimalFormat");
1339         Formattable num;
1340         fmt->parse(UnicodeString("abc3"), num, status);
1341         if(! U_FAILURE(status))
1342             errln(UnicodeString("Bug 4052223 failed : can't parse string \"a\".  Got ") /*+ num*/);
1343     /*} catch (ParseException foo) {
1344         logln("Caught expected ParseException : " + foo.getMessage() + " at index : " + foo.getErrorOffset());
1345     }*/
1346     delete fmt;
1347 }
1348 /* @bug 4061302
1349  * API tests for API addition request A9.
1350  */
Test4061302(void)1351 void NumberFormatRegressionTest::Test4061302(void)
1352 {
1353     UErrorCode status = U_ZERO_ERROR;
1354     DecimalFormatSymbols *fmt = new DecimalFormatSymbols(status);
1355     if (U_FAILURE(status)) {
1356         dataerrln("Error creating DecimalFormatSymbols - %s", u_errorName(status));
1357         return;
1358     }
1359     UnicodeString currency(fmt->getSymbol(DecimalFormatSymbols::kCurrencySymbol));
1360     UnicodeString intlCurrency(fmt->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol));
1361     UnicodeString monDecSeparator(fmt->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol));
1362     if (currency == UnicodeString("") ||
1363         intlCurrency == UnicodeString("") ||
1364         monDecSeparator == UnicodeString(""))
1365     {
1366         errln("getCurrencySymbols failed, got empty string.");
1367     }
1368     UnicodeString monDecSeparatorStr;
1369     monDecSeparatorStr.append(monDecSeparator);
1370     logln((UnicodeString)"Before set ==> Currency : " + currency +(UnicodeString)" Intl Currency : " + intlCurrency + (UnicodeString)" Monetary Decimal Separator : " + monDecSeparatorStr);
1371     fmt->setSymbol(DecimalFormatSymbols::kCurrencySymbol, UnicodeString("XYZ"));
1372     fmt->setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol, UnicodeString("ABC"));
1373     fmt->setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol, UnicodeString((UChar)0x002A/*'*'*/));
1374     currency = fmt->getSymbol(DecimalFormatSymbols::kCurrencySymbol);
1375     intlCurrency = fmt->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol);
1376     monDecSeparator = fmt->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol);
1377     if (currency != UnicodeString("XYZ") ||
1378         intlCurrency != UnicodeString("ABC") ||
1379         monDecSeparator != UnicodeString((UChar)0x002A/*'*'*/)) {
1380         errln("setCurrencySymbols failed.");
1381     }
1382     monDecSeparatorStr.remove();
1383     monDecSeparatorStr.append(monDecSeparator);
1384     logln("After set ==> Currency : " + currency + " Intl Currency : " + intlCurrency + " Monetary Decimal Separator : " + monDecSeparatorStr);
1385 
1386     delete fmt;
1387 }
1388 /* @bug 4062486
1389  * API tests for API addition request A23. FieldPosition.getBeginIndex and
1390  * FieldPosition.getEndIndex.
1391  */
Test4062486(void)1392 void NumberFormatRegressionTest::Test4062486(void)
1393 {
1394     UErrorCode status = U_ZERO_ERROR;
1395     DecimalFormat *fmt = new DecimalFormat(UnicodeString("#,##0.00"), status);
1396     if (U_FAILURE(status)) {
1397         dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
1398         return;
1399     }
1400     UnicodeString formatted;
1401     FieldPosition field(FieldPosition::DONT_CARE);
1402     double num = 1234.5;
1403     fmt->format(num, formatted, field);
1404     if (field.getBeginIndex() != 0 && field.getEndIndex() != 5)
1405         errln(UnicodeString("Format 1234.5 failed. Begin index: ") /*+ field.getBeginIndex() + " End index: " + field.getEndIndex()*/);
1406     field.setBeginIndex(7);
1407     field.setEndIndex(4);
1408     if (field.getBeginIndex() != 7 && field.getEndIndex() != 4)
1409         errln("Set begin/end field indexes failed. Begin index: " /*+ field.getBeginIndex() + " End index: " + field.getEndIndex()*/);
1410 
1411     delete fmt;
1412 }
1413 
1414 /* @bug 4108738
1415  * DecimalFormat.parse incorrectly works with a group separator.
1416  */
Test4108738(void)1417 void NumberFormatRegressionTest::Test4108738(void)
1418 {
1419     UErrorCode status = U_ZERO_ERROR;
1420     DecimalFormatSymbols *syms = new DecimalFormatSymbols(Locale::getUS(), status);
1421     failure(status, "new DecimalFormatSymbols");
1422     DecimalFormat *df = new DecimalFormat("#,##0.###", syms, status);
1423     if(U_FAILURE(status)) {
1424       errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
1425       delete df;
1426       return;
1427     }
1428     failure(status, "new DecimalFormat");
1429     UnicodeString text("1.222,111");
1430     Formattable num;
1431     ParsePosition pp(0);
1432     df->parse(text, num, pp);
1433 
1434     // {sfb} how to do this (again) ?
1435     // shouldn't just be another round-trip test, should it?
1436     UnicodeString temp;
1437     FieldPosition pos(FieldPosition::DONT_CARE);
1438     temp = df->format(num.getDouble(), temp, pos);
1439     //if (!num.toString().equals("1.222"))
1440     if (temp != UnicodeString("1.222"))
1441         //errln("\"" + text + "\"  is parsed as " + num);
1442         errln("\"" + text + "\"  is parsed as " + temp);
1443     text = UnicodeString("1.222x111");
1444     pp = ParsePosition(0);
1445     df->parse(text, num, pp);
1446     temp.remove();
1447     temp = df->format(num.getDouble(), temp, pos);
1448     //if (!num.toString().equals("1.222"))
1449     if (temp != UnicodeString("1.222"))
1450         errln("\"" + text + "\"  is parsed as " + temp);
1451 
1452     delete df;
1453 }
1454 
1455 /* @bug 4106658
1456  * DecimalFormat.format() incorrectly formats negative doubles.
1457  */
Test4106658(void)1458 void NumberFormatRegressionTest::Test4106658(void)
1459 {
1460     UErrorCode status = U_ZERO_ERROR;
1461     DecimalFormat *df = new DecimalFormat(status); // Corrected; see 4147706
1462     if(U_FAILURE(status)) {
1463       errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
1464       delete df;
1465       return;
1466     }
1467     failure(status, "new DecimalFormat");
1468     volatile double d1 = 0.0;   // volatile to prevent code optimization
1469     double d2 = -0.0001;
1470     UnicodeString buffer;
1471     UnicodeString temp;
1472     FieldPosition pos(FieldPosition::DONT_CARE);
1473 
1474 #if U_PLATFORM == U_PF_HPUX
1475     d1 = 0.0 * -1.0;    // old HPUX compiler ignores volatile keyword
1476 #else
1477     d1 *= -1.0; // Some compilers have a problem with defining -0.0
1478 #endif
1479     logln("pattern: \"" + df->toPattern(temp) + "\"");
1480     df->format(d1, buffer, pos);
1481     if (buffer != UnicodeString("-0")) // Corrected; see 4147706
1482         errln(UnicodeString("") + d1 + "      is formatted as " + buffer);
1483     buffer.remove();
1484     df->format(d2, buffer, pos);
1485     if (buffer != UnicodeString("-0")) // Corrected; see 4147706
1486         errln(UnicodeString("") + d2 + "      is formatted as " + buffer);
1487 
1488     delete df;
1489 }
1490 
1491 /* @bug 4106662
1492  * DecimalFormat.parse returns 0 if string parameter is incorrect.
1493  */
Test4106662(void)1494 void NumberFormatRegressionTest::Test4106662(void)
1495 {
1496     UErrorCode status = U_ZERO_ERROR;
1497     DecimalFormat *df = new DecimalFormat(status);
1498     if(U_FAILURE(status)) {
1499       errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
1500       delete df;
1501       return;
1502     }
1503     failure(status, "new DecimalFormat");
1504     UnicodeString text("x");
1505     ParsePosition pos1(0), pos2(0);
1506 
1507     UnicodeString temp;
1508     logln("pattern: \"" + df->toPattern(temp) + "\"");
1509     Formattable num;
1510     df->parse(text, num, pos1);
1511     if (pos1 == ParsePosition(0)/*num != null*/) {
1512         errln(UnicodeString("Test Failed: \"") + text + "\" is parsed as " /*+ num*/);
1513     }
1514     delete df;
1515     df = new DecimalFormat(UnicodeString("$###.00"), status);
1516     failure(status, "new DecimalFormat");
1517     df->parse(UnicodeString("$"), num, pos2);
1518     if (pos2 == ParsePosition(0) /*num != null*/){
1519         errln(UnicodeString("Test Failed: \"$\" is parsed as ") /*+ num*/);
1520     }
1521 
1522     delete df;
1523 }
1524 
1525 /* @bug 4114639 (duplicate of 4106662)
1526  * NumberFormat.parse doesn't return null
1527  */
Test4114639(void)1528 void NumberFormatRegressionTest::Test4114639(void)
1529 {
1530     UErrorCode status = U_ZERO_ERROR;
1531     NumberFormat *format = NumberFormat::createInstance(status);
1532     if(U_FAILURE(status)) {
1533       dataerrln("Error creating DecimalFormat: %s", u_errorName(status));
1534       delete format;
1535       return;
1536     }
1537     failure(status, "NumberFormat::createInstance");
1538     UnicodeString text("time 10:x");
1539     ParsePosition pos(8);
1540     Formattable result;
1541     format->parse(text, result, pos);
1542     if (/*result != null*/pos.getErrorIndex() != 8)
1543         errln(UnicodeString("Should return null but got : ") /*+ result*/); // Should be null; it isn't
1544 
1545     delete format;
1546 }
1547 
1548 /* @bug 4106664
1549  * TODO: this test does not work because we need to use a 64 bit number and a
1550  * a double only MAY only have 52 bits of precision.
1551  * DecimalFormat.format(long n) fails if n * multiplier > MAX_LONG.
1552  */
Test4106664(void)1553 void NumberFormatRegressionTest::Test4106664(void)
1554 {
1555     UErrorCode status = U_ZERO_ERROR;
1556     DecimalFormat *df = new DecimalFormat(status);
1557     if(U_FAILURE(status)) {
1558       errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
1559       delete df;
1560       return;
1561     }
1562     failure(status, "new DecimalFormat");
1563     // {sfb} long in java is 64 bits
1564     /*long*/double n = 1234567890123456.0;
1565     /*int*/int32_t m = 12345678;
1566     // {sfb} will this work?
1567     //BigInteger bigN = BigInteger.valueOf(n);
1568     //bigN = bigN.multiply(BigInteger.valueOf(m));
1569     double bigN = n * m;
1570     df->setMultiplier(m);
1571     df->setGroupingUsed(FALSE);
1572     UnicodeString temp;
1573     FieldPosition pos(FieldPosition::DONT_CARE);
1574     logln("formated: " +
1575         df->format(n, temp, pos));
1576 
1577     char buf [128];
1578     sprintf(buf, "%g", bigN);
1579     //logln("expected: " + bigN.toString());
1580     logln(UnicodeString("expected: ") + buf);
1581 
1582     delete df;
1583 }
1584 /* @bug 4106667 (duplicate of 4106658)
1585  * DecimalFormat.format incorrectly formats -0.0.
1586  */
Test4106667(void)1587 void NumberFormatRegressionTest::Test4106667(void)
1588 {
1589     UErrorCode status = U_ZERO_ERROR;
1590     DecimalFormat *df = new DecimalFormat(status);
1591     if(U_FAILURE(status)) {
1592       errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
1593       delete df;
1594       return;
1595     }
1596     failure(status, "new DecimalFormat");
1597     UChar foo [] = { 0x002B };
1598     UnicodeString bar(foo, 1, 1);
1599     volatile double d = 0.0;   // volatile to prevent code optimization
1600     UnicodeString temp;
1601     UnicodeString buffer;
1602     FieldPosition pos(FieldPosition::DONT_CARE);
1603 
1604     logln("pattern: \"" + df->toPattern(temp) + "\"");
1605 #if U_PLATFORM == U_PF_HPUX
1606     d = 0.0 * -1.0;    // old HPUX compiler ignores volatile keyword
1607 #else
1608     d *= -1.0; // Some compilers have a problem with defining -0.0
1609 #endif
1610     df->setPositivePrefix(/*"+"*/bar);
1611     df->format(d, buffer, pos);
1612     if (buffer != UnicodeString("-0")) // Corrected; see 4147706
1613         errln(/*d + */UnicodeString("  is formatted as ") + buffer);
1614 
1615     delete df;
1616 }
1617 
1618 /* @bug 4110936
1619  * DecimalFormat.setMaximumIntegerDigits() works incorrectly.
1620  */
1621 #if U_PLATFORM == U_PF_OS390
1622 #   define MAX_INT_DIGITS 70
1623 #else
1624 #   define MAX_INT_DIGITS 128
1625 #endif
1626 
Test4110936(void)1627 void NumberFormatRegressionTest::Test4110936(void)
1628 {
1629     UErrorCode status = U_ZERO_ERROR;
1630     NumberFormat *nf = NumberFormat::createInstance(status);
1631     if(U_FAILURE(status)) {
1632       dataerrln("Error creating DecimalFormat: %s", u_errorName(status));
1633       delete nf;
1634       return;
1635     }
1636     failure(status, "NumberFormat::createInstance");
1637     nf->setMaximumIntegerDigits(MAX_INT_DIGITS);
1638     logln("setMaximumIntegerDigits(MAX_INT_DIGITS)");
1639     if (nf->getMaximumIntegerDigits() != MAX_INT_DIGITS)
1640         errln(UnicodeString("getMaximumIntegerDigits() returns ") +
1641             nf->getMaximumIntegerDigits());
1642 
1643     delete nf;
1644 }
1645 
1646 /* @bug 4122840
1647  * Locale data should use generic currency symbol
1648  *
1649  * 1) Make sure that all currency formats use the generic currency symbol.
1650  * 2) Make sure we get the same results using the generic symbol or a
1651  *    hard-coded one.
1652  */
Test4122840(void)1653 void NumberFormatRegressionTest::Test4122840(void)
1654 {
1655     int32_t count = 0;
1656     const Locale *locales = Locale::getAvailableLocales(count);
1657 
1658     for (int i = 0; i < count; i++) {
1659         UErrorCode status = U_ZERO_ERROR;
1660         ResourceBundle *rb = new ResourceBundle(
1661             NULL/*"java.text.resources.LocaleElements"*/,
1662             locales[i], status);
1663         failure(status, "new ResourceBundle");
1664         ResourceBundle numPat = rb->getWithFallback("NumberElements", status);
1665         failure(status, "rb.get(NumberElements)");
1666         numPat = numPat.getWithFallback("latn",status);
1667         failure(status, "rb.get(latn)");
1668         numPat = numPat.getWithFallback("patterns",status);
1669         failure(status, "rb.get(patterns)");
1670         numPat = numPat.getWithFallback("currencyFormat",status);
1671         failure(status, "rb.get(currencyFormat)");
1672        //
1673         // Get the currency pattern for this locale.  We have to fish it
1674         // out of the ResourceBundle directly, since DecimalFormat.toPattern
1675         // will return the localized symbol, not \00a4
1676         //
1677         UnicodeString pattern = numPat.getString(status);
1678         failure(status, "rb->getString()");
1679 
1680         UChar fo[] = { 0x00A4 };
1681         UnicodeString foo(fo, 1, 1);
1682 
1683         //if (pattern.indexOf("\u00A4") == -1 ) {
1684         if (pattern.indexOf(foo) == -1 ) {
1685             errln(UnicodeString("Currency format for ") + UnicodeString(locales[i].getName()) +
1686                     " does not contain generic currency symbol:" +
1687                     pattern );
1688         }
1689 
1690         // Create a DecimalFormat using the pattern we got and format a number
1691         DecimalFormatSymbols *symbols = new DecimalFormatSymbols(locales[i], status);
1692         failure(status, "new DecimalFormatSymbols");
1693 
1694         // Disable currency spacing for the purposes of this test.
1695         // To do this, set the spacing insert to the empty string both before and after the symbol.
1696         symbols->setPatternForCurrencySpacing(UNUM_CURRENCY_INSERT, FALSE, u"");
1697         symbols->setPatternForCurrencySpacing(UNUM_CURRENCY_INSERT, TRUE, u"");
1698 
1699         DecimalFormat *fmt1 = new DecimalFormat(pattern, *symbols, status);
1700         failure(status, "new DecimalFormat");
1701 
1702         UnicodeString result1;
1703         FieldPosition pos(FieldPosition::DONT_CARE);
1704         result1 = fmt1->format(1.111, result1, pos);
1705 
1706         //
1707         // Now substitute in the locale's currency symbol and create another
1708         // pattern.  We have to skip locales where the currency symbol
1709         // contains decimal separators, because that confuses things
1710         //
1711         UChar ba[] = { 0x002E/*'.'*/ };
1712         UnicodeString bar(ba, 1, 1);
1713 
1714         if (symbols->getSymbol(DecimalFormatSymbols::kCurrencySymbol).indexOf(bar) == -1) {
1715             // {sfb} Also, switch the decimal separator to the monetary decimal
1716             // separator to mimic the behavior of a currency format
1717             symbols->setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol,
1718                 symbols->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol));
1719 
1720             UnicodeString buf(pattern);
1721             for (int j = 0; j < buf.length(); j++) {
1722                 if (buf[j] == 0x00a4 ) {
1723                     if(buf[j + 1] == 0x00a4) {
1724                         // {sfb} added to support double currency marker (intl currency sign)
1725                         buf.replace(j, /*j+*/2, symbols->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol));
1726                         j += symbols->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol).length();
1727                     }
1728                     else {
1729                         buf.replace(j, /*j+*/1, symbols->getSymbol(DecimalFormatSymbols::kCurrencySymbol));
1730                         j += symbols->getSymbol(DecimalFormatSymbols::kCurrencySymbol).length() - 1;
1731                     }
1732                 }
1733             }
1734 
1735             DecimalFormat *fmt2 = new DecimalFormat(buf, *symbols, status);
1736             failure(status, "new DecimalFormat");
1737 
1738             // Get the currency (if there is one) so we can set the rounding and fraction
1739             const UChar *currency = fmt1->getCurrency();
1740             if (*currency != 0) {
1741                 double rounding = ucurr_getRoundingIncrement(currency, &status);
1742                 int32_t frac = ucurr_getDefaultFractionDigits(currency, &status);
1743                 if (U_SUCCESS(status)) {
1744                     fmt2->setRoundingIncrement(rounding);
1745                     fmt2->setMinimumFractionDigits(frac);
1746                     fmt2->setMaximumFractionDigits(frac);
1747                 }
1748                 else {
1749                     failure(status, "Fetching currency rounding/fractions");
1750                 }
1751             }
1752 
1753             UnicodeString result2;
1754             fmt2->format(1.111, result2, pos);
1755 
1756             if (result1 != result2) {
1757                 errln("Results for " + (UnicodeString)(locales[i].getName()) + " differ: " +
1758                         result1 + " vs " + result2);
1759             }
1760 
1761             delete fmt2;
1762         }
1763 
1764         delete rb;
1765         delete fmt1;
1766         delete symbols;
1767     }
1768 }
1769 
1770 /* @bug 4125885
1771  * DecimalFormat.format() delivers wrong string.
1772  */
Test4125885(void)1773 void NumberFormatRegressionTest::Test4125885(void)
1774 {
1775     UErrorCode status = U_ZERO_ERROR;
1776     double rate = 12.34;
1777     DecimalFormat *formatDec = new DecimalFormat ("000.00", status);
1778     if(U_FAILURE(status)) {
1779       errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
1780       delete formatDec;
1781       return;
1782     }
1783     failure(status, "new DecimalFormat");
1784     UnicodeString temp;
1785     logln("toPattern: " + formatDec->toPattern(temp));
1786     UnicodeString rateString;
1787     FieldPosition pos(FieldPosition::DONT_CARE);
1788     rateString = formatDec->format(rate, rateString, pos);
1789     if (rateString != UnicodeString("012.34"))
1790         errln("result : " + rateString + " expected : 012.34");
1791     rate = 0.1234;
1792     delete formatDec;// = null;
1793     formatDec = new DecimalFormat ("+000.00%;-000.00%", status);
1794     failure(status, "new DecimalFormat");
1795     logln("toPattern: " + formatDec->toPattern(temp));
1796     rateString.remove();
1797     rateString = formatDec->format(rate, rateString, pos);
1798     if (rateString != UnicodeString("+012.34%"))
1799         errln("result : " + rateString + " expected : +012.34%");
1800 
1801     delete formatDec;
1802 }
1803 
1804 /**
1805  * @bug 4134034
1806  * DecimalFormat produces extra zeros when formatting numbers.
1807  */
Test4134034(void)1808 void NumberFormatRegressionTest::Test4134034(void)
1809 {
1810     UErrorCode status = U_ZERO_ERROR;
1811     DecimalFormat *nf = new DecimalFormat("##,###,###.00", status);
1812     if (!failure(status, "new DecimalFormat")) {
1813         UnicodeString f;
1814         FieldPosition pos(FieldPosition::DONT_CARE);
1815         f = nf->format(9.02, f, pos);
1816         if (f == UnicodeString("9.02"))
1817             logln(f + " ok");
1818         else
1819             errln("9.02 -> " + f + "; want 9.02");
1820 
1821         f.remove();
1822         f = nf->format((int32_t)0, f, pos);
1823         if (f == UnicodeString(".00"))
1824             logln(f + " ok");
1825         else
1826             errln("0 -> " + f + "; want .00");
1827     }
1828 
1829     delete nf;
1830 }
1831 
1832 /**
1833  * @bug 4134300
1834  * CANNOT REPRODUCE - This bug could not be reproduced.  It may be
1835  * a duplicate of 4134034.
1836  *
1837  * JDK 1.1.6 Bug, did NOT occur in 1.1.5
1838  * Possibly related to bug 4125885.
1839  *
1840  * This class demonstrates a regression in version 1.1.6
1841  * of DecimalFormat class.
1842  *
1843  * 1.1.6 Results
1844  * Value 1.2 Format #.00 Result '01.20' !!!wrong
1845  * Value 1.2 Format 0.00 Result '001.20' !!!wrong
1846  * Value 1.2 Format 00.00 Result '0001.20' !!!wrong
1847  * Value 1.2 Format #0.0# Result '1.2'
1848  * Value 1.2 Format #0.00 Result '001.20' !!!wrong
1849  *
1850  * 1.1.5 Results
1851  * Value 1.2 Format #.00 Result '1.20'
1852  * Value 1.2 Format 0.00 Result '1.20'
1853  * Value 1.2 Format 00.00 Result '01.20'
1854  * Value 1.2 Format #0.0# Result '1.2'
1855  * Value 1.2 Format #0.00 Result '1.20'
1856  */
Test4134300(void)1857 void NumberFormatRegressionTest::Test4134300(void) {
1858     UnicodeString DATA [] = {
1859      // Pattern      Expected string
1860         UnicodeString("#.00"),      UnicodeString("1.20"),
1861         UnicodeString("0.00"),      UnicodeString("1.20"),
1862         UnicodeString("00.00"),     UnicodeString("01.20"),
1863         UnicodeString("#0.0#"),     UnicodeString("1.2"),
1864         UnicodeString("#0.00"),     UnicodeString("1.20")
1865     };
1866 
1867     for (int i=0; i< 10; i+=2) {
1868         UnicodeString result;
1869         UErrorCode status = U_ZERO_ERROR;
1870         DecimalFormat *df = new DecimalFormat(DATA[i], status);
1871         if (!failure(status, "new DecimalFormat")) {
1872             FieldPosition pos(FieldPosition::DONT_CARE);
1873             result = df->format(1.2, result, pos);
1874             if (result != DATA[i+1]) {
1875                 errln("Fail: 1.2 x " + DATA[i] + " = " + result +
1876                       "; want " + DATA[i+1]);
1877             }
1878             else {
1879                 logln("Ok: 1.2 x " + DATA[i] + " = " + result);
1880             }
1881         }
1882 
1883         delete df;
1884     }
1885 }
1886 
1887 /**
1888  * @bug 4140009
1889  * Empty pattern produces double negative prefix.
1890  */
Test4140009(void)1891 void NumberFormatRegressionTest::Test4140009(void)
1892 {
1893     UErrorCode status = U_ZERO_ERROR;
1894     LocalPointer<DecimalFormatSymbols> syms(new DecimalFormatSymbols(Locale::getEnglish(), status), status);
1895     if (failure(status, "new DecimalFormatSymbols")) {
1896         return;
1897     }
1898     DecimalFormat *f = new DecimalFormat(UnicodeString(u""), syms.orphan(), status);
1899     if (!failure(status, "new DecimalFormat")) {
1900         UnicodeString s;
1901         FieldPosition pos(FieldPosition::DONT_CARE);
1902         s = f->format(123.456, s, pos);
1903         if (s != UnicodeString("123.456"))
1904             errln("Fail: Format empty pattern x 123.456 => " + s);
1905         s.remove();
1906         s = f->format(-123.456, s, pos);
1907         if (s != UnicodeString("-123.456"))
1908             errln("Fail: Format empty pattern x -123.456 => " + s);
1909     }
1910     delete f;
1911 }
1912 
1913 /**
1914  * @bug 4141750
1915  * BigDecimal numbers get their fractions truncated by NumberFormat.
1916  */
1917 // {sfb} not pertinent in C++ ??
Test4141750(void)1918 void NumberFormatRegressionTest::Test4141750(void) {
1919     /*try {
1920         UnicodeString str("12345.67");
1921         BigDecimal bd = new BigDecimal(str);
1922         String sd = NumberFormat.getInstance(Locale.US).format(bd);
1923         if (!sd.endsWith("67")) errln("Fail: " + str + " x format -> " + sd);
1924     }
1925     catch (Exception e) {
1926         errln(e.toString());
1927         e.printStackTrace();
1928     }*/
1929 }
1930 
1931 /**
1932  * @bug 4145457
1933  * DecimalFormat toPattern() doesn't quote special characters or handle
1934  * single quotes.
1935  */
Test4145457()1936 void NumberFormatRegressionTest::Test4145457() {
1937     //try {
1938     UErrorCode status = U_ZERO_ERROR;
1939     NumberFormat *nff = NumberFormat::createInstance(status);
1940     if (failure(status, "NumberFormat::createInstance", TRUE)){
1941         delete nff;
1942         return;
1943     }
1944     DecimalFormat *nf = dynamic_cast<DecimalFormat *>(nff);
1945     if(nf == NULL) {
1946         errln("DecimalFormat needed to continue");
1947         return;
1948     }
1949 
1950     DecimalFormatSymbols *sym = (DecimalFormatSymbols*) nf->getDecimalFormatSymbols();
1951     sym->setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, (UChar)/*'\''*/0x0027);
1952     nf->setDecimalFormatSymbols(*sym);
1953     double pi = 3.14159;
1954 
1955     UnicodeString PATS [] = {
1956         UnicodeString("#.00 'num''ber'"), UnicodeString("''#.00''")
1957     };
1958 
1959     for (int32_t i=0; i<2; ++i) {
1960         nf->applyPattern(PATS[i], status);
1961         failure(status, "nf->applyPattern");
1962         UnicodeString out;
1963         FieldPosition pos(FieldPosition::DONT_CARE);
1964         out = nf->format(pi, out, pos);
1965         UnicodeString pat;
1966         pat = nf->toPattern(pat);
1967         Formattable num;
1968         ParsePosition pp(0);
1969         nf->parse(out, num, pp);
1970         double val = num.getDouble();
1971 
1972         nf->applyPattern(pat, status);
1973         failure(status, "nf->applyPattern");
1974         UnicodeString out2;
1975         out2 = nf->format(pi, out2, pos);
1976         UnicodeString pat2;
1977         pat2 = nf->toPattern(pat2);
1978         pp.setIndex(0);
1979         nf->parse(out2, num, pp);
1980         double val2 = num.getDouble();
1981 
1982         if (pat != pat2)
1983             errln("Fail with \"" + PATS[i] + "\": Patterns should concur, \"" +
1984                 pat + "\" vs. \"" + pat2 + "\"");
1985         else
1986             logln("Ok \"" + PATS[i] + "\" toPattern() -> \"" + pat + '"');
1987 
1988         if (val == val2 && out == out2) {
1989             logln(UnicodeString("Ok ") + pi + " x \"" + PATS[i] + "\" -> \"" +
1990                 out + "\" -> " + val + " -> \"" +
1991                 out2 + "\" -> " + val2);
1992         }
1993         else {
1994             errln(UnicodeString("Fail ") + pi + " x \"" + PATS[i] + "\" -> \"" +
1995                 out + "\" -> " + val + " -> \"" +
1996                 out2 + "\" -> " + val2);
1997         }
1998     }
1999     /*}
2000     catch (ParseException e) {
2001         errln("Fail: " + e);
2002         e.printStackTrace();
2003     }*/
2004 
2005     delete nff;
2006 }
2007 
2008 /**
2009  * @bug 4147295
2010  * DecimalFormat.applyPattern() sets minimum integer digits incorrectly.
2011  * CANNOT REPRODUCE
2012  * This bug is a duplicate of 4139344, which is a duplicate of 4134300
2013  *
2014  * ICU 62: minInt is always at least one, and the getter should reflect that!
2015  */
Test4147295(void)2016 void NumberFormatRegressionTest::Test4147295(void)
2017 {
2018     UErrorCode status = U_ZERO_ERROR;
2019     DecimalFormat *sdf = new DecimalFormat(status);
2020     UnicodeString pattern("#,###");
2021     logln("Applying pattern \"" + pattern + "\"");
2022     sdf->applyPattern(pattern, status);
2023     if (!failure(status, "sdf->applyPattern")) {
2024         int minIntDig = sdf->getMinimumIntegerDigits();
2025         if (minIntDig != 1) {
2026             errln("Test failed");
2027             errln(UnicodeString(" Minimum integer digits : ") + minIntDig);
2028             UnicodeString temp;
2029             errln(UnicodeString(" new pattern: ") + sdf->toPattern(temp));
2030         } else {
2031             logln("Test passed");
2032             logln(UnicodeString(" Minimum integer digits : ") + minIntDig);
2033         }
2034     }
2035     delete sdf;
2036 }
2037 
2038 /**
2039  * @bug 4147706
2040  * DecimalFormat formats -0.0 as +0.0
2041  * See also older related bug 4106658, 4106667
2042  */
Test4147706(void)2043 void NumberFormatRegressionTest::Test4147706(void)
2044 {
2045     UErrorCode status = U_ZERO_ERROR;
2046     DecimalFormat *df = new DecimalFormat("#,##0.0##", status);
2047     failure(status, "new DecimalFormat");
2048     DecimalFormatSymbols *syms = new DecimalFormatSymbols(Locale::getEnglish(), status);
2049     if (!failure(status, "new DecimalFormatSymbols")) {
2050         UnicodeString f1;
2051         UnicodeString f2, temp;
2052         FieldPosition pos(FieldPosition::DONT_CARE);
2053         volatile double d1 = 0.0;   // volatile to prevent code optimization
2054         double d2 = -0.0001;
2055 
2056 #if U_PLATFORM == U_PF_HPUX
2057         d1 = 0.0 * -1.0;    // old HPUX compiler ignores volatile keyword
2058 #else
2059         d1 *= -1.0; // Some compilers have a problem with defining -0.0
2060 #endif
2061         df->adoptDecimalFormatSymbols(syms);
2062         f1 = df->format(d1, f1, pos);
2063         f2 = df->format(d2, f2, pos);
2064         if (f1 != UnicodeString("-0.0")) {
2065             errln(UnicodeString("") + d1 + UnicodeString(" x \"") + df->toPattern(temp) + "\" is formatted as \"" + f1 + '"');
2066         }
2067         if (f2 != UnicodeString("-0.0")) {
2068             errln(UnicodeString("") + d2 + UnicodeString(" x \"") + df->toPattern(temp) + "\" is formatted as \"" + f2 + '"');
2069         }
2070     }
2071 
2072     delete df;
2073 }
2074 
2075 
2076 // Not applicable, since no serialization in C++
2077 /*class myformat implements Serializable
2078 {
2079 DateFormat _dateFormat = DateFormat.getDateInstance();
2080 
2081 public String Now()
2082 {
2083     GregorianCalendar calendar = new GregorianCalendar();
2084     Date t = calendar.getTime();
2085     String nowStr = _dateFormat.format(t);
2086     return nowStr;
2087 }
2088 }*/
2089 
2090 /**
2091  * @bug 4162198
2092  * NumberFormat cannot format Double.MAX_VALUE
2093  */
2094 // TODO: make this test actually test something
2095 void
Test4162198(void)2096 NumberFormatRegressionTest::Test4162198(void)
2097 {
2098     // for some reason, DBL_MAX will not round trip. (bug in sprintf/atof)
2099     double dbl = INT32_MAX * 1000.0;
2100     UErrorCode status = U_ZERO_ERROR;
2101     NumberFormat *f = NumberFormat::createInstance(status);
2102     if(U_FAILURE(status)) {
2103         dataerrln("Couldn't create number format - %s", u_errorName(status));
2104         return;
2105     }
2106     f->setMaximumFractionDigits(INT32_MAX);
2107     f->setMaximumIntegerDigits(INT32_MAX);
2108     UnicodeString s;
2109     f->format(dbl,s);
2110     logln(UnicodeString("The number ") + dbl + " formatted to " + s);
2111     Formattable n;
2112     //try {
2113     f->parse(s, n, status);
2114     if(U_FAILURE(status))
2115         errln("Couldn't parse!");
2116     //} catch (java.text.ParseException e) {
2117     //    errln("Caught a ParseException:");
2118     //    e.printStackTrace();
2119     //}
2120 
2121     //logln("The string " + s + " parsed as " + n);
2122 
2123     // {dlf} The old code assumes n is a double, but it isn't any more...
2124     // Formattable apparently does not and never did interconvert... too bad.
2125     //if(n.getDouble() != dbl) {
2126     //    errln("Round trip failure");
2127     //}
2128     if (n.getInt64() != dbl) {
2129         errln("Round trip failure");
2130     }
2131 
2132     delete f;
2133 }
2134 
2135 /**
2136  * @bug 4162852
2137  * NumberFormat does not parse negative zero.
2138  */
2139 void
Test4162852(void)2140 NumberFormatRegressionTest::Test4162852(void)
2141 {
2142     UErrorCode status = U_ZERO_ERROR;
2143     for(int32_t i=0; i < 2; ++i) {
2144         LocalPointer<NumberFormat> f(
2145             ((i == 0) ? NumberFormat::createInstance(status) : NumberFormat::createPercentInstance(status)),
2146             status);
2147         if(U_FAILURE(status)) {
2148             dataerrln("Couldn't create number format - %s", u_errorName(status));
2149             return;
2150         }
2151         double d = 0.0;
2152         d *= -1.0;
2153         UnicodeString s;
2154         f->format(d, s);
2155         Formattable n;
2156         f->parse(s, n, status);
2157         if(U_FAILURE(status)) {
2158             errln("Couldn't parse!");
2159             return;
2160         }
2161         double e = n.getDouble();
2162         logln("%f -> \"%s\" -> %f", d, CStr(s)(), e);
2163 #if (U_PLATFORM == U_PF_OS390 && !defined(IEEE_754)) || U_PLATFORM == U_PF_OS400
2164         if (e != 0.0) {
2165 #else
2166         if (e != 0.0 || (std::signbit(e) == false)) {
2167 #endif
2168             errln("Failed to parse negative zero");
2169         }
2170     }
2171 }
2172 
2173 static double _u_abs(double a) { return a<0?-a:a; }
2174 
2175 /**
2176  * May 17 1999 sync up - liu
2177  * @bug 4167494
2178  * NumberFormat truncates data
2179  */
2180 void NumberFormatRegressionTest::Test4167494(void) {
2181     UErrorCode status = U_ZERO_ERROR;
2182     NumberFormat *fmt = NumberFormat::createInstance(Locale::getUS(), status);
2183     if (failure(status, "NumberFormat::createInstance", TRUE)){
2184         delete fmt;
2185         return;
2186     }
2187 
2188     double a = DBL_MAX * 0.99; // DBL_MAX itself overflows to +Inf
2189     UnicodeString s;
2190     fmt->format(a, s);
2191     Formattable num;
2192     fmt->parse(s, num, status);
2193     failure(status, "Parse");
2194     if (num.getType() == Formattable::kDouble &&
2195         _u_abs(num.getDouble() - a) / a < 0.01) { // RT within 1%
2196         logln(UnicodeString("") + a + " -> \"" + s + "\" -> " +
2197               toString(num) + " ok");
2198     } else {
2199         errln(UnicodeString("") + a + " -> \"" + s + "\" -> " +
2200               toString(num) + " FAIL");
2201     }
2202 
2203     // We don't test Double.MIN_VALUE because the locale data for the US
2204     // currently doesn't specify enough digits to display Double.MIN_VALUE.
2205     // This is correct for now; however, we leave this here as a reminder
2206     // in case we want to address this later.
2207 
2208     delete fmt;
2209 }
2210 
2211 /**
2212  * May 17 1999 sync up - liu
2213  * @bug 4170798
2214  * DecimalFormat.parse() fails when ParseIntegerOnly set to true
2215  */
2216 void NumberFormatRegressionTest::Test4170798(void) {
2217     IcuTestErrorCode status(*this, "Test4170798");
2218     LocalPointer<DecimalFormat> df(dynamic_cast<DecimalFormat*>(
2219             NumberFormat::createInstance(Locale::getUS(), status)), status);
2220     if (!assertSuccess("", status, true, __FILE__, __LINE__)) {
2221         return;
2222     }
2223     {
2224         Formattable n;
2225         ParsePosition pos(0);
2226         df->parse("-0.0", n, pos);
2227         if (n.getType() != Formattable::kDouble
2228             || n.getDouble() != -0.0) {
2229             errln(UnicodeString("FAIL: default parse(\"-0.0\") returns ") + toString(n));
2230         }
2231     }
2232     df->setParseIntegerOnly(TRUE);
2233     {
2234         Formattable n;
2235         ParsePosition pos(0);
2236         df->parse("-0.0", n, pos);
2237         if (n.getType() != Formattable::kLong
2238             || n.getLong() != 0) {
2239             errln(UnicodeString("FAIL: integer parse(\"-0.0\") returns ") + toString(n));
2240         }
2241     }
2242 }
2243 
2244 /**
2245  * May 17 1999 sync up - liu
2246  * toPattern only puts the first grouping separator in.
2247  */
2248 void NumberFormatRegressionTest::Test4176114(void) {
2249     const char* DATA[] = {
2250         "00", "00",
2251         "000", "000", // No grouping
2252         "#000", "000", // No grouping
2253         "#,##0", "#,##0",
2254         "#,000", "#,000",
2255         "0,000", "0,000",
2256         "00,000", "00,000",
2257         "000,000", "000,000",
2258         "0,000,000,000,000.0000", "0,000,000,000,000.0000", // Reported
2259     };
2260     int DATA_length = UPRV_LENGTHOF(DATA);
2261     UErrorCode status = U_ZERO_ERROR;
2262     UnicodeString s;
2263     for (int i=0; i<DATA_length; i+=2) {
2264         DecimalFormat df(DATA[i], status);
2265         if (!failure(status, "DecimalFormat constructor")) {
2266             df.toPattern(s);
2267             UnicodeString exp(DATA[i+1]);
2268             if (s != exp) {
2269                 errln(UnicodeString("FAIL: ") + DATA[i] + " -> " +
2270                       s + ", want " + exp);
2271             }
2272         }
2273     }
2274 }
2275 
2276 /**
2277  * May 17 1999 sync up - liu
2278  * @bug 4179818
2279  * DecimalFormat is incorrectly rounding numbers like 1.2501 to 1.2
2280  */
2281 void NumberFormatRegressionTest::Test4179818(void) {
2282     const char* DATA[] = {
2283         // Input  Pattern  Expected output
2284         "1.2511", "#.#",   "1.3",
2285         "1.2501", "#.#",   "1.3",
2286         "0.9999", "#",     "1",
2287     };
2288     int DATA_length = UPRV_LENGTHOF(DATA);
2289     double DOUBLE[] = {
2290         1.2511,
2291         1.2501,
2292         0.9999,
2293     };
2294     UErrorCode status = U_ZERO_ERROR;
2295     DecimalFormatSymbols sym(Locale::getUS(), status);
2296     failure(status, "Construct DecimalFormatSymbols");
2297     DecimalFormat fmt("#", sym, status);
2298     if (!failure(status, "Construct DecimalFormat")) {
2299         for (int i=0; i<DATA_length; i+=3) {
2300             double in = DOUBLE[i/3];
2301             UnicodeString pat(DATA[i+1]);
2302             UnicodeString exp(DATA[i+2]);
2303             fmt.applyPattern(pat, status);
2304             failure(status, "applyPattern");
2305             UnicodeString out;
2306             FieldPosition pos;
2307             fmt.format(in, out, pos);
2308             if (out == exp) {
2309                 logln(UnicodeString("Ok: ") + in + " x " + pat + " = " + out);
2310             } else {
2311                 errln(UnicodeString("FAIL: ") + in + " x  " + pat + " = " + out +
2312                       ", expected " + exp);
2313             }
2314         }
2315     }
2316 }
2317 
2318 /**
2319  * May 17 1999 sync up - liu
2320  * Some DecimalFormatSymbols changes are not picked up by DecimalFormat.
2321  * This includes the minus sign, currency symbol, international currency
2322  * symbol, percent, and permille.  This is filed as bugs 4212072 and
2323  * 4212073.
2324  */
2325 void NumberFormatRegressionTest::Test4212072(void) {
2326     UErrorCode status = U_ZERO_ERROR;
2327     DecimalFormatSymbols sym(Locale::getUS(), status);
2328 
2329     failure(status, "DecimalFormatSymbols ct", Locale::getUS());
2330     DecimalFormat fmt(UnicodeString("#"), sym, status);
2331     if(failure(status, "DecimalFormat ct", Locale::getUS())) {
2332         return;
2333     }
2334 
2335     UnicodeString s;
2336     FieldPosition pos;
2337 
2338     sym.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, (UChar)0x5e);
2339     fmt.setDecimalFormatSymbols(sym);
2340     s.remove();
2341     if (fmt.format((int32_t)-1, s, pos) != UNICODE_STRING("^1", 2)) {
2342         errln(UnicodeString("FAIL: -1 x (minus=^) -> ") + s +
2343               ", exp ^1");
2344     }
2345     s.remove();
2346     if (fmt.getNegativePrefix(s) != UnicodeString((UChar)0x5e)) {
2347         errln(UnicodeString("FAIL: (minus=^).getNegativePrefix -> ") +
2348               s + ", exp ^");
2349     }
2350     sym.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, (UChar)0x2d);
2351 
2352     fmt.applyPattern(UnicodeString("#%"), status);
2353     failure(status, "applyPattern percent");
2354     sym.setSymbol(DecimalFormatSymbols::kPercentSymbol, (UChar)0x5e);
2355     fmt.setDecimalFormatSymbols(sym);
2356     s.remove();
2357     if (fmt.format(0.25, s, pos) != UNICODE_STRING("25^", 3)) {
2358         errln(UnicodeString("FAIL: 0.25 x (percent=^) -> ") + s +
2359               ", exp 25^");
2360     }
2361     s.remove();
2362     if (fmt.getPositiveSuffix(s) != UnicodeString((UChar)0x5e)) {
2363         errln(UnicodeString("FAIL: (percent=^).getPositiveSuffix -> ") +
2364               s + ", exp ^");
2365     }
2366     sym.setSymbol(DecimalFormatSymbols::kPercentSymbol, (UChar)0x25);
2367 
2368     fmt.applyPattern(str("#\\u2030"), status);
2369     failure(status, "applyPattern permill");
2370     sym.setSymbol(DecimalFormatSymbols::kPerMillSymbol, (UChar)0x5e);
2371     fmt.setDecimalFormatSymbols(sym);
2372     s.remove();
2373     if (fmt.format(0.25, s, pos) != UNICODE_STRING("250^", 4)) {
2374         errln(UnicodeString("FAIL: 0.25 x (permill=^) -> ") + s +
2375               ", exp 250^");
2376     }
2377     s.remove();
2378     if (fmt.getPositiveSuffix(s) != UnicodeString((UChar)0x5e)) {
2379         errln(UnicodeString("FAIL: (permill=^).getPositiveSuffix -> ") +
2380               s + ", exp ^");
2381     }
2382     sym.setSymbol(DecimalFormatSymbols::kPerMillSymbol, (UChar)0x2030);
2383 
2384     fmt.applyPattern(str("\\u00A4#.00"), status);
2385     failure(status, "applyPattern currency");
2386     sym.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "usd");
2387     fmt.setDecimalFormatSymbols(sym);
2388     s.remove();
2389     if (fmt.format(12.5, s, pos) != UnicodeString(u"usd\u00A012.50")) {
2390         errln(UnicodeString("FAIL: 12.5 x (currency=usd) -> ") + s +
2391               u", exp usd\u00A012.50");
2392     }
2393     s.remove();
2394     if (fmt.getPositivePrefix(s) != UnicodeString("usd")) {
2395         errln(UnicodeString("FAIL: (currency=usd).getPositivePrefix -> ") +
2396               s + ", exp usd");
2397     }
2398     sym.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "$");
2399 
2400     fmt.applyPattern(str("\\u00A4\\u00A4#.00"), status);
2401     failure(status, "applyPattern intl currency");
2402     sym.setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol, "DOL");
2403     fmt.setDecimalFormatSymbols(sym);
2404     s.remove();
2405     if (fmt.format(12.5, s, pos) != UnicodeString(u"DOL\u00A012.50")) {
2406         errln(UnicodeString("FAIL: 12.5 x (intlcurrency=DOL) -> ") + s +
2407               u", exp DOL\u00A012.50");
2408     }
2409     s.remove();
2410     if (fmt.getPositivePrefix(s) != UnicodeString("DOL")) {
2411         errln(UnicodeString("FAIL: (intlcurrency=DOL).getPositivePrefix -> ") +
2412               s + ", exp DOL");
2413     }
2414     sym.setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol, "USD");
2415 
2416     // Since the pattern logic has changed, make sure that patterns round
2417     // trip properly.  Test stream in/out integrity too.
2418     int32_t n;
2419     const Locale* avail = NumberFormat::getAvailableLocales(n);
2420     static const char* type[] = {
2421         "",
2422         "$ ",
2423         "% ",
2424     };
2425     for (int i=0; i<n; ++i) {
2426         for (int j=0; j<3; ++j) {
2427             status = U_ZERO_ERROR;
2428             NumberFormat *nf;
2429             switch (j) {
2430             case 0:
2431                 nf = NumberFormat::createInstance(avail[i], status);
2432                 failure(status, "createInstance", avail[i]);
2433                 break;
2434             case 1:
2435                 nf = NumberFormat::createCurrencyInstance(avail[i], status);
2436                 failure(status, "createCurrencyInstance", avail[i]);
2437                 break;
2438             default:
2439                 nf = NumberFormat::createPercentInstance(avail[i], status);
2440                 failure(status, "createPercentInstance", avail[i]);
2441                 break;
2442             }
2443             if (U_FAILURE(status)) {
2444                 continue;
2445             }
2446             DecimalFormat *df = (DecimalFormat*) nf;
2447 
2448             // Test toPattern/applyPattern round trip
2449             UnicodeString pat;
2450             df->toPattern(pat);
2451             DecimalFormatSymbols symb(avail[i], status);
2452             failure(status, "Construct DecimalFormatSymbols", avail[i]);
2453             DecimalFormat f2(pat, symb, status);
2454             if (failure(status,
2455                         UnicodeString("Construct DecimalFormat(") + pat + ")")) {
2456                 continue;
2457             }
2458             if (*df != f2) {
2459                 UnicodeString l, p;
2460                 errln(UnicodeString("FAIL: ") + type[j] + avail[i].getDisplayName(l) +
2461                       " -> \"" + pat +
2462                       "\" -> \"" + f2.toPattern(p) + "\"");
2463             } else {
2464                 UnicodeString l, p;
2465                 logln(UnicodeString("PASS: ") + type[j] + avail[i].getDisplayName(l) +
2466                       " -> \"" + pat +
2467                       "\"");
2468             }
2469 
2470             // Test toLocalizedPattern/applyLocalizedPattern round trip
2471 // TODO(refactor): don't worry about localized patterns for now.
2472 //            df->toLocalizedPattern(pat);
2473 //           f2.applyLocalizedPattern(pat, status);
2474             failure(status,
2475                     UnicodeString("applyLocalizedPattern(") + pat + ")", avail[i]);
2476             if (U_FAILURE(status)) {
2477                 continue;
2478             }
2479 
2480 // TODO(refactor): don't worry about localized patterns for now.
2481             // Make sure we set the currency attributes appropriately
2482 //            if (j == 1) {   // Currency format
2483 //                f2.setCurrency(f2.getCurrency(), status);
2484 //            }
2485             failure(status,
2486                     UnicodeString("setCurrency() for (") + pat + ")", avail[i]);
2487             if (U_FAILURE(status)) {
2488                 continue;
2489             }
2490 
2491             if (*df != f2) {
2492                 UnicodeString l, p;
2493                 errln(UnicodeString("FAIL: ") + type[j] + avail[i].getDisplayName(l) +
2494                       " -> localized \"" + pat +
2495                       "\" -> \"" + f2.toPattern(p) + "\"");
2496             }
2497 
2498             delete nf;
2499 
2500             // Test writeObject/readObject round trip
2501             // NOT ON ICU -- Java only
2502         }
2503     }
2504 }
2505 
2506 /**
2507  * May 17 1999 sync up - liu
2508  * DecimalFormat.parse() fails for mulipliers 2^n.
2509  */
2510 void NumberFormatRegressionTest::Test4216742(void) {
2511     UErrorCode status = U_ZERO_ERROR;
2512     DecimalFormat *fmt = (DecimalFormat*) NumberFormat::createInstance(Locale::getUS(), status);
2513     if (failure(status, "createInstance", Locale::getUS(), TRUE)){
2514         delete fmt;
2515         return;
2516     }
2517     int32_t DATA[] = { INT32_MIN, INT32_MAX, -100000000, 100000000 };
2518     int DATA_length = UPRV_LENGTHOF(DATA);
2519     for (int i=0; i<DATA_length; ++i) {
2520         UnicodeString str((UnicodeString)"" + DATA[i]);
2521         for (int m = 1; m <= 100; m++) {
2522             fmt->setMultiplier(m);
2523             Formattable num;
2524             fmt->parse(str, num, status);
2525             failure(status, "parse", Locale::getUS());
2526             if (num.getType() != Formattable::kLong &&
2527                 num.getType() != Formattable::kDouble) {
2528                 errln(UnicodeString("FAIL: Wanted number, got ") +
2529                       toString(num));
2530             } else {
2531                 double d = num.getType() == Formattable::kDouble ?
2532                     num.getDouble() : (double) num.getLong();
2533                 if ((d > 0) != (DATA[i] > 0)) {
2534                     errln(UnicodeString("\"") + str + "\" parse(x " +
2535                           fmt->getMultiplier() +
2536                           ") => " + toString(num));
2537                 }
2538             }
2539         }
2540     }
2541     delete fmt;
2542 }
2543 
2544 /**
2545  * May 17 1999 sync up - liu
2546  * DecimalFormat formats 1.001 to "1.00" instead of "1" with 2 fraction
2547  * digits.
2548  */
2549 void NumberFormatRegressionTest::Test4217661(void) {
2550     const double D[] = {  0.001, 1.001, 0.006,  1.006 };
2551     const char*  S[] = { "0",   "1",   "0.01", "1.01" };
2552     int D_length = UPRV_LENGTHOF(D);
2553     UErrorCode status = U_ZERO_ERROR;
2554     NumberFormat *fmt = NumberFormat::createInstance(Locale::getUS(), status);
2555     if (failure(status, "createInstance", Locale::getUS(), TRUE)){
2556         delete fmt;
2557         return;
2558     }
2559     fmt->setMaximumFractionDigits(2);
2560     for (int i=0; i<D_length; i++) {
2561         UnicodeString s;
2562         fmt->format(D[i], s);
2563         if (s != UnicodeString(S[i])) {
2564             errln(UnicodeString("FAIL: Got ") + s + ", exp " + S[i]);
2565         }
2566     }
2567     delete fmt;
2568 }
2569 
2570 /**
2571  * alphaWorks upgrade
2572  */
2573 void NumberFormatRegressionTest::Test4161100(void) {
2574     UErrorCode status = U_ZERO_ERROR;
2575     NumberFormat *nf = NumberFormat::createInstance(Locale::getUS(), status);
2576     if (failure(status, "createInstance", Locale::getUS(), TRUE)){
2577         delete nf;
2578         return;
2579     }
2580     nf->setMinimumFractionDigits(1);
2581     nf->setMaximumFractionDigits(1);
2582     double a = -0.09;
2583     UnicodeString s;
2584     nf->format(a, s);
2585     UnicodeString pat;
2586     logln(UnicodeString() + a + " x " +
2587           ((DecimalFormat*) nf)->toPattern(pat) + " = " + s);
2588     if (s != UnicodeString("-0.1")) {
2589         errln("FAIL");
2590     }
2591     delete nf;
2592 }
2593 
2594 /**
2595  * June 16 1999 sync up - liu
2596  * Formatting .5 rounds to "1" instead of "0". (Regression in 1.2.2 RC1)
2597  */
2598 void NumberFormatRegressionTest::Test4243011(void) {
2599     UErrorCode status = U_ZERO_ERROR;
2600     DecimalFormatSymbols sym(Locale::getUS(), status);
2601     failure(status, "DecimalFormatSymbols ct", Locale::getUS());
2602     DecimalFormat fmt(UnicodeString("0."), sym, status);
2603 
2604     if (!failure(status, "DecimalFormat ct", Locale::getUS())) {
2605         const double NUM[] = {  -2.5,  -1.5,  -0.5,  0.5,  1.5,  2.5,  3.5,  4.5 };
2606         const char*  STR[] = { "-2.", "-2.", "-0.", "0.", "2.", "2.", "4.", "4." };
2607         int32_t N = UPRV_LENGTHOF(NUM);
2608 
2609         for (int32_t i=0; i<N; ++i) {
2610             UnicodeString str;
2611             UnicodeString exp(STR[i]);
2612             FieldPosition pos;
2613             fmt.format(NUM[i], str, pos);
2614             if (str == exp) {
2615                 logln(UnicodeString("Ok   ") + NUM[i] + " x 0. = " + str);
2616             } else {
2617                 errln(UnicodeString("FAIL ") + NUM[i] + " x 0. = " + str +
2618                       ", want " + exp);
2619             }
2620         }
2621     }
2622 }
2623 
2624 /**
2625  * June 16 1999 sync up - liu
2626  * format(0.0) gives "0.1" if preceded by parse("99.99").
2627  * (Regression in 1.2.2 RC1)
2628  */
2629 void NumberFormatRegressionTest::Test4243108(void) {
2630     UErrorCode status = U_ZERO_ERROR;
2631     DecimalFormatSymbols sym(Locale::getUS(), status);
2632     failure(status, "DecimalFormatSymbols ct", Locale::getUS());
2633     DecimalFormat fmt(UnicodeString("#.#"), sym, status);
2634     if (failure(status, "DecimalFormat ct", Locale::getUS())) {
2635         return;
2636     }
2637 
2638     UnicodeString str;
2639     FieldPosition pos;
2640 
2641     fmt.format(0.0, str, pos);
2642     UnicodeString exp("0");
2643     if (str == exp) {
2644         logln(UnicodeString("Ok   0.0 x #.# = ") + str);
2645     } else {
2646         errln(UnicodeString("FAIL 0.0 x #.# = ") + str +
2647               ", want " + exp);
2648     }
2649 
2650     str = "99.99";
2651     Formattable val;
2652     fmt.parse(str, val, status);
2653     failure(status, "DecimalFormat.parse(99.99)", Locale::getUS());
2654     if (val.getType() == Formattable::kDouble &&
2655         val.getDouble() == 99.99) {
2656         logln(UnicodeString("Ok   99.99 / #.# = ") + toString(val));
2657     } else {
2658         errln(UnicodeString("FAIL 99.99 / #.# = ") + toString(val) +
2659               ", want " + 99.99);
2660     }
2661 
2662     str.remove();
2663     fmt.format(0.0, str, pos);
2664     if (str == exp) {
2665         logln(UnicodeString("Ok   0.0 x #.# = ") + str);
2666     } else {
2667         errln(UnicodeString("FAIL 0.0 x #.# = ") + str +
2668               ", want " + exp);
2669     }
2670 }
2671 
2672 
2673 /**
2674  * DateFormat should call setIntegerParseOnly(TRUE) on adopted
2675  * NumberFormat objects.
2676  */
2677 void NumberFormatRegressionTest::TestJ691(void) {
2678     UErrorCode status = U_ZERO_ERROR;
2679     Locale loc("fr", "CH");
2680 
2681     // set up the input date string & expected output
2682     UnicodeString udt(u"11.10.2000");
2683     UnicodeString exp(u"11.10.00");
2684 
2685     // create a Calendar for this locale
2686     LocalPointer<Calendar> cal(Calendar::createInstance(loc, status));
2687     if (U_FAILURE(status)) {
2688         dataerrln("FAIL: Calendar::createInstance() returned " + (UnicodeString)u_errorName(status));
2689         return;
2690     }
2691 
2692     // create a NumberFormat for this locale
2693     LocalPointer<NumberFormat> nf(NumberFormat::createInstance(loc, status));
2694     if (U_FAILURE(status)) {
2695         dataerrln("FAIL: NumberFormat::createInstance() returned " + (UnicodeString)u_errorName(status));
2696         return;
2697     }
2698 
2699     // *** Here's the key: We don't want to have to do THIS:
2700     // nf->setParseIntegerOnly(TRUE);
2701     // or this (with changes to fr_CH per cldrbug:9370):
2702     // nf->setGroupingUsed(FALSE);
2703     // so they are done in DateFormat::adoptNumberFormat
2704 
2705     // create the DateFormat
2706     LocalPointer<DateFormat> df(DateFormat::createDateInstance(DateFormat::kShort, loc));
2707     if (U_FAILURE(status)) {
2708         errln("FAIL: DateFormat::createInstance() returned " + (UnicodeString)u_errorName(status));
2709         return;
2710     }
2711 
2712     df->adoptCalendar(cal.orphan());
2713     df->adoptNumberFormat(nf.orphan());
2714 
2715     // set parsing to lenient & parse
2716     df->setLenient(TRUE);
2717     UDate ulocdat = df->parse(udt, status);
2718 
2719     // format back to a string
2720     UnicodeString outString;
2721     df->format(ulocdat, outString);
2722 
2723     if (outString != exp) {
2724         errln("FAIL: " + udt + " => " + outString);
2725     }
2726 }
2727 
2728 //---------------------------------------------------------------------------
2729 //
2730 //   Error Checking / Reporting macros
2731 //
2732 //---------------------------------------------------------------------------
2733 #define TEST_CHECK_STATUS(status) UPRV_BLOCK_MACRO_BEGIN { \
2734     if (U_FAILURE(status)) { \
2735         if (status == U_MISSING_RESOURCE_ERROR) { \
2736             dataerrln("File %s, Line %d: status=%s", __FILE__, __LINE__, u_errorName(status)); \
2737         } else { \
2738             errln("File %s, Line %d: status=%s", __FILE__, __LINE__, u_errorName(status)); \
2739         } return; \
2740     } \
2741 } UPRV_BLOCK_MACRO_END
2742 
2743 #define TEST_ASSERT(expr) UPRV_BLOCK_MACRO_BEGIN { \
2744     if ((expr)==FALSE) {\
2745         errln("File %s, line %d: Assertion Failed: " #expr "\n", __FILE__, __LINE__);\
2746     } \
2747 } UPRV_BLOCK_MACRO_END
2748 #define TEST_ASSERT_EQUALS(x,y) UPRV_BLOCK_MACRO_BEGIN { \
2749       char _msg[1000]; \
2750       int32_t len = sprintf (_msg,"File %s, line %d: " #x "==" #y, __FILE__, __LINE__); \
2751       (void)len;                                                         \
2752       U_ASSERT(len < (int32_t) sizeof(_msg));                            \
2753       assertEquals((const char*) _msg, x,y);                             \
2754 } UPRV_BLOCK_MACRO_END
2755 
2756 
2757 // Ticket 8199:  Parse failure for numbers in the range of 1E10 - 1E18
2758 
2759 void NumberFormatRegressionTest::Test8199(void) {
2760     UErrorCode status = U_ZERO_ERROR;
2761     NumberFormat *nf = NumberFormat::createInstance(Locale::getEnglish(), status);
2762     if (nf == NULL) {
2763         dataerrln("Fail: NumberFormat::createInstance(Locale::getEnglish(), status)");
2764         return;
2765     }
2766     TEST_CHECK_STATUS(status);
2767 
2768     // Note:  Retrieving parsed values from a Formattable as a reduced-precision type
2769     //        should always truncate, no other rounding scheme.
2770 
2771     UnicodeString numStr = "1000000000.6";   // 9 zeroes
2772     Formattable val;
2773     nf->parse(numStr, val, status);
2774     TEST_CHECK_STATUS(status);
2775     TEST_ASSERT_EQUALS(Formattable::kDouble, val.getType());
2776     TEST_ASSERT_EQUALS(1000000000LL, val.getInt64(status));
2777     TEST_CHECK_STATUS(status);
2778     TEST_ASSERT_EQUALS(1000000000.6, val.getDouble(status));
2779     TEST_CHECK_STATUS(status);
2780 
2781     numStr = "100000000000000001.1";   // approx 1E17, parses as a double rather
2782                                        //   than int64 because of the fraction
2783                                        //   even though int64 is more precise.
2784     nf->parse(numStr, val, status);
2785     TEST_CHECK_STATUS(status);
2786     TEST_ASSERT_EQUALS(Formattable::kDouble, val.getType());
2787     TEST_ASSERT_EQUALS(100000000000000001LL, val.getInt64(status));
2788     TEST_CHECK_STATUS(status);
2789     TEST_ASSERT_EQUALS(100000000000000000.0, val.getDouble(status));
2790     TEST_CHECK_STATUS(status);
2791 
2792     numStr = "1E17";  // Parses with the internal decimal number having non-zero exponent
2793     nf->parse(numStr, val, status);
2794     TEST_CHECK_STATUS(status);
2795     TEST_ASSERT_EQUALS(Formattable::kInt64, val.getType());
2796     TEST_ASSERT_EQUALS(100000000000000000LL, val.getInt64());
2797     TEST_ASSERT_EQUALS(1.0E17, val.getDouble(status));
2798     TEST_CHECK_STATUS(status);
2799 
2800     numStr = "9223372036854775807";  // largest int64_t
2801     nf->parse(numStr, val, status);
2802     TEST_CHECK_STATUS(status);
2803     TEST_ASSERT_EQUALS(Formattable::kInt64, val.getType());
2804     TEST_ASSERT_EQUALS(9223372036854775807LL, val.getInt64());
2805     // In the following check, note that a substantial range of integers will
2806     //    convert to the same double value.  There are also platform variations
2807     //    in the rounding at compile time of double constants.
2808     TEST_ASSERT(9223372036854775808.0 >= val.getDouble(status));
2809     TEST_ASSERT(9223372036854774700.0 <= val.getDouble(status));
2810     TEST_CHECK_STATUS(status);
2811 
2812     numStr = "-9223372036854775808";  // smallest int64_t
2813     nf->parse(numStr, val, status);
2814     TEST_CHECK_STATUS(status);
2815     TEST_ASSERT_EQUALS(Formattable::kInt64, val.getType());
2816     // TEST_ASSERT_EQUALS(-9223372036854775808LL, val.getInt64()); // Compiler chokes on constant.
2817     TEST_ASSERT_EQUALS((int64_t)0x8000000000000000LL, val.getInt64());
2818     TEST_ASSERT_EQUALS(-9223372036854775808.0, val.getDouble(status));
2819     TEST_CHECK_STATUS(status);
2820 
2821     numStr = "9223372036854775808";  // largest int64_t + 1
2822     nf->parse(numStr, val, status);
2823     TEST_CHECK_STATUS(status);
2824     TEST_ASSERT_EQUALS(Formattable::kDouble, val.getType());
2825     TEST_ASSERT_EQUALS(9223372036854775807LL, val.getInt64(status));
2826     TEST_ASSERT_EQUALS(status, U_INVALID_FORMAT_ERROR);
2827     status = U_ZERO_ERROR;
2828     TEST_ASSERT_EQUALS(9223372036854775810.0, val.getDouble(status));
2829     TEST_CHECK_STATUS(status);
2830 
2831     numStr = "-9223372036854775809";  // smallest int64_t - 1
2832     nf->parse(numStr, val, status);
2833     TEST_CHECK_STATUS(status);
2834     TEST_ASSERT_EQUALS(Formattable::kDouble, val.getType());
2835     // TEST_ASSERT_EQUALS(-9223372036854775808LL, val.getInt64(status));  // spurious compiler warnings
2836     TEST_ASSERT_EQUALS((int64_t)0x8000000000000000LL, val.getInt64(status));
2837     TEST_ASSERT_EQUALS(status, U_INVALID_FORMAT_ERROR);
2838     status = U_ZERO_ERROR;
2839     TEST_ASSERT_EQUALS(-9223372036854775810.0, val.getDouble(status));
2840     TEST_CHECK_STATUS(status);
2841 
2842     // Test values near the limit of where doubles can represent all integers.
2843     // The implementation strategy of getInt64() changes at this boundary.
2844     // Strings to be parsed include a decimal fraction to force them to be
2845     //   parsed as doubles rather than ints.  The fraction is discarded
2846     //   from the parsed double value because it is beyond what can be represented.
2847 
2848     status = U_ZERO_ERROR;
2849     numStr = "9007199254740991.1";  // largest 53 bit int
2850     nf->parse(numStr, val, status);
2851     TEST_CHECK_STATUS(status);
2852     // printf("getInt64() returns %lld\n", val.getInt64(status));
2853     TEST_ASSERT_EQUALS(Formattable::kDouble, val.getType());
2854     TEST_ASSERT_EQUALS(9007199254740991LL, val.getInt64(status));
2855     TEST_ASSERT_EQUALS(9007199254740991.0, val.getDouble(status));
2856     TEST_CHECK_STATUS(status);
2857 
2858     status = U_ZERO_ERROR;
2859     numStr = "9007199254740992.1";  // 54 bits for the int part.
2860     nf->parse(numStr, val, status);
2861     TEST_CHECK_STATUS(status);
2862     TEST_ASSERT_EQUALS(Formattable::kDouble, val.getType());
2863     TEST_ASSERT_EQUALS(9007199254740992LL, val.getInt64(status));
2864     TEST_ASSERT_EQUALS(9007199254740992.0, val.getDouble(status));
2865     TEST_CHECK_STATUS(status);
2866 
2867     status = U_ZERO_ERROR;
2868     numStr = "9007199254740993.1";  // 54 bits for the int part.  Double will round
2869     nf->parse(numStr, val, status); //    the ones digit, putting it up to ...994
2870     TEST_CHECK_STATUS(status);
2871     TEST_ASSERT_EQUALS(Formattable::kDouble, val.getType());
2872     TEST_ASSERT_EQUALS((int64_t)9007199254740993LL,val.getInt64(status));
2873     TEST_ASSERT_EQUALS((double)9007199254740994.0,(double)val.getDouble(status));
2874     TEST_CHECK_STATUS(status);
2875 
2876     delete nf;
2877 }
2878 
2879 void NumberFormatRegressionTest::Test9109(void) {
2880     UErrorCode status = U_ZERO_ERROR;
2881     Formattable val;
2882     ParsePosition pos;
2883     DecimalFormat fmt("+##", status);
2884     if (U_FAILURE(status)) {
2885         dataerrln("Failed to create DecimalFormat with pattern '+##' - %s", u_errorName(status));
2886         return;
2887     }
2888 
2889     fmt.setLenient(TRUE);
2890     UnicodeString text("123");
2891     int32_t expected = 123;
2892     int32_t expos = 3;
2893 
2894     fmt.parse(text, val, pos);
2895     if (pos.getErrorIndex() >= 0) {
2896         errln(UnicodeString("Parse failure at ") + pos.getErrorIndex());
2897     } else if (val.getLong() != 123) {
2898         errln(UnicodeString("Incorrect parse result: ") + val.getLong() + " expected: " + expected);
2899     } else if (pos.getIndex() != 3) {
2900         errln(UnicodeString("Incorrect parse position: ") + pos.getIndex() + " expected: " + expos);
2901     }
2902 }
2903 
2904 
2905 void NumberFormatRegressionTest::Test9780(void) {
2906     UErrorCode status = U_ZERO_ERROR;
2907     NumberFormat *nf = NumberFormat::createInstance(Locale::getUS(), status);
2908     if (failure(status, "NumberFormat::createInstance", TRUE)){
2909         delete nf;
2910         return;
2911     }
2912     DecimalFormat *df = dynamic_cast<DecimalFormat *>(nf);
2913     if(df == NULL) {
2914         errln("DecimalFormat needed to continue");
2915         return;
2916     }
2917     df->setParseIntegerOnly(TRUE);
2918 
2919     {
2920       Formattable n;
2921       ParsePosition pos(0);
2922       UnicodeString toParse("1,234","");
2923       df->parse(toParse, n, pos);
2924       if (n.getType() != Formattable::kLong
2925           || n.getLong() != 1234) {
2926         errln(UnicodeString("FAIL: parse(\"") + toParse + UnicodeString("\") returns ") + toString(n));
2927       }
2928     }
2929     // should still work in lenient mode, just won't get fastpath
2930     df->setLenient(TRUE);
2931     {
2932       Formattable n;
2933       ParsePosition pos(0);
2934       UnicodeString toParse("1,234","");
2935       df->parse(toParse, n, pos);
2936       if (n.getType() != Formattable::kLong
2937           || n.getLong() != 1234) {
2938         errln(UnicodeString("FAIL: parse(\"") + toParse + UnicodeString("\") returns ") + toString(n));
2939       }
2940     }
2941     delete nf;
2942 }
2943 
2944 
2945 void NumberFormatRegressionTest::Test9677(void) {
2946   static const UChar pattern[] = { 0x23,0x23,0x23,0x23,0x2E,0x23,0x23,0x23,0x23,0 }; // "####.####"
2947   static const UChar positivePrefix[] = { 0x40,0 }; // "@"
2948   static const UChar negativePrefix[] = { 0x6E,0 }; // "n"
2949   static const UChar text[] = { 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0 }; // 123456789
2950   static const UChar text2[] = { 0x6E, 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0 }; // n123456789
2951 
2952   UErrorCode status = U_ZERO_ERROR;
2953   LocalUNumberFormatPointer f(unum_open(UNUM_DEFAULT, NULL, 0, "en_US", NULL, &status));
2954   if (U_FAILURE(status)) {
2955       dataerrln("Failure opening unum_open");
2956       return;
2957   }
2958 
2959   if (U_SUCCESS(status)) {
2960     unum_applyPattern(f.getAlias(), FALSE, pattern, -1, NULL, &status);
2961     unum_setTextAttribute(f.getAlias(), UNUM_POSITIVE_PREFIX, positivePrefix, -1, &status);
2962     assertSuccess("setting attributes", status);
2963   }
2964 
2965   if(U_SUCCESS(status)) {
2966     int32_t n = unum_parse(f.getAlias(), text, -1, NULL, &status);
2967     logln("unum_parse status %s, result %d\n", u_errorName(status), n);
2968 
2969     if(U_FAILURE(status)) {
2970         logln("Got expected parse error %s\n", u_errorName(status));
2971         status = U_ZERO_ERROR;
2972     } else {
2973         errln("FAIL: unum_parse status %s, result %d - expected failure\n", u_errorName(status), n);
2974     }
2975   }
2976 
2977   if (U_SUCCESS(status)) {
2978     unum_setTextAttribute(f.getAlias(), UNUM_POSITIVE_PREFIX, NULL, 0, &status);
2979     assertSuccess("setting attributes", status);
2980     logln("removed positive prefix");
2981   }
2982 
2983   if(U_SUCCESS(status)) {
2984     int32_t n = unum_parse(f.getAlias(), text, -1, NULL, &status);
2985     logln("unum_parse status %s, result %d\n", u_errorName(status), n);
2986 
2987     if(U_FAILURE(status)) {
2988         errln("FAIL: with pos prefix removed, parse error %s\n", u_errorName(status));
2989         status = U_ZERO_ERROR;
2990     } else {
2991         if(n!=123456789) {
2992           errln("FAIL: with pos prefix removed , unum_parse status %s, result %d expected 123456789\n", u_errorName(status), n);
2993         } else {
2994           logln("PASS: with pos prefix removed , unum_parse status %s, result %d expected 123456789\n", u_errorName(status),n);
2995         }
2996     }
2997   }
2998 
2999   if(U_SUCCESS(status)) {
3000     int32_t n = unum_parse(f.getAlias(), text2, -1, NULL, &status);
3001     logln("unum_parse status %s, result %d\n", u_errorName(status), n);
3002 
3003     if(U_FAILURE(status)) {
3004         logln("text2: Got expected parse error %s\n", u_errorName(status));
3005         status = U_ZERO_ERROR;
3006     } else {
3007         errln("FAIL: text2: unum_parse status %s, result %d - expected failure\n", u_errorName(status), n);
3008     }
3009   }
3010 
3011   if (U_SUCCESS(status)) {
3012     unum_setTextAttribute(f.getAlias(), UNUM_NEGATIVE_PREFIX, negativePrefix, -1, &status);
3013     assertSuccess("setting attributes", status);
3014     logln("Set a different neg prefix prefix");
3015   }
3016 
3017   if(U_SUCCESS(status)) {
3018     int32_t n = unum_parse(f.getAlias(), text2, -1, NULL, &status);
3019     logln("unum_parse status %s, result %d\n", u_errorName(status), n);
3020 
3021     if(U_FAILURE(status)) {
3022         errln("FAIL: with different neg prefix , parse error %s\n", u_errorName(status));
3023         status = U_ZERO_ERROR;
3024     } else {
3025         if(n!=-123456789) {
3026           errln("FAIL: with different neg prefix , unum_parse status %s, result %d expected -123456789\n", u_errorName(status), n);
3027         } else {
3028           logln("PASS: with different neg prefix , unum_parse status %s, result %d expected -123456789\n", u_errorName(status), n);
3029         }
3030     }
3031   }
3032 }
3033 
3034 void NumberFormatRegressionTest::Test10361(void) {
3035     // DecimalFormat/NumberFormat were artificially limiting the number of digits,
3036     //    preventing formatting of big decimals.
3037     UErrorCode status = U_ZERO_ERROR;
3038     DecimalFormatSymbols symbols(Locale::getEnglish(), status);
3039     LocalPointer<DecimalFormat> df(new DecimalFormat("###.##", symbols, status), status);
3040     TEST_CHECK_STATUS(status);
3041 
3042     // Create a decimal number with a million digits.
3043     const int32_t NUMSIZE=1000000;
3044     char *num = new char[NUMSIZE];
3045     for (int32_t i=0; i<NUMSIZE; i++) {
3046         num[i] = '0' + (i+1) % 10;
3047     }
3048     num[NUMSIZE-3] = '.';
3049     num[NUMSIZE-1] = 0;
3050 
3051     UnicodeString    s;
3052     Formattable      fmtable;
3053     fmtable.setDecimalNumber(num, status);
3054     TEST_CHECK_STATUS(status);
3055 
3056     FieldPosition pos(UNUM_DECIMAL_SEPARATOR_FIELD);
3057     df->format(fmtable, s, pos, status);
3058     TEST_CHECK_STATUS(status);
3059     TEST_ASSERT(999999 == s.length());
3060     TEST_ASSERT(999997 == pos.getBeginIndex());
3061     TEST_ASSERT(999998 == pos.getEndIndex());
3062 
3063     UnicodeString expected(num, -1, US_INV);
3064     TEST_ASSERT(expected == s);
3065     delete [] num;
3066 }
3067 
3068 #endif /* #if !UCONFIG_NO_FORMATTING */
3069