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