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