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