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