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