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