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