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 Format* 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 uloc_canonicalize("pt_PT_PREEURO", loc, 256, &status);
854 Locale *de = new Locale(loc);
855 NumberFormat *nf = NumberFormat::createCurrencyInstance(*de, status);
856 if(U_FAILURE(status)) {
857 dataerrln("Error creating DecimalFormat: %s", u_errorName(status));
858 delete nf;
859 return;
860 }
861 DecimalFormat *df = dynamic_cast<DecimalFormat *>(nf);
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 delete de;
891 delete nf;
892 }
893 /* @bug 4070798
894 * Number format data rounding errors for locale FR
895 */
Test4070798(void)896 void NumberFormatRegressionTest::Test4070798 (void)
897 {
898 NumberFormat *formatter;
899 UnicodeString tempString;
900
901 /* User error :
902 String expectedDefault = "-5\u202f789,987";
903 String expectedCurrency = "5\u202f789,98\u00a0F";
904 String expectedPercent = "-578\u202f998%";
905 */
906 UChar chars1 [] = {
907 0x2d, 0x35, 0x202f, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x38, 0x38
908 };
909 UChar chars2 [] = {
910 0x35, 0x202f, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x39, 0x00a0, 0x46
911 };
912 UChar chars3 [] = {
913 0x2d, 0x35, 0x37, 0x38, 0x202f, 0x39, 0x39, 0x39, 0x00a0, 0x25
914 };
915 UnicodeString expectedDefault(chars1, 10, 10);
916 UnicodeString expectedCurrency(chars2, 10, 10);
917 UnicodeString expectedPercent(chars3, 10, 10);
918
919 UErrorCode status = U_ZERO_ERROR;
920 char loc[256]={0};
921 int len = uloc_canonicalize("fr_FR_PREEURO", loc, 256, &status);
922 (void)len; // Suppress set but not used warning.
923 formatter = NumberFormat::createInstance(Locale(loc), status);
924 if(U_FAILURE(status)) {
925 dataerrln("Error creating DecimalFormat: %s", u_errorName(status));
926 delete formatter;
927 return;
928 }
929 failure(status, "NumberFormat::createInstance", loc);
930 tempString = formatter->format (-5789.9876, tempString);
931
932 if (tempString == expectedDefault) {
933 logln ("Bug 4070798 default test passed.");
934 } else {
935 errln(UnicodeString("Failed:") +
936 " Expected " + expectedDefault +
937 " Received " + tempString );
938 }
939 delete formatter;
940 len = uloc_canonicalize("fr_FR_PREEURO", loc, 256, &status);
941 formatter = NumberFormat::createCurrencyInstance(loc, status);
942 failure(status, "NumberFormat::createCurrencyInstance", loc);
943 tempString.remove();
944 tempString = formatter->format( 5789.9876, tempString );
945
946 if (tempString == expectedCurrency) {
947 logln ("Bug 4070798 currency test passed.");
948 } else {
949 errln(UnicodeString("Failed:") +
950 " Expected " + expectedCurrency +
951 " Received " + tempString );
952 }
953 delete formatter;
954
955 uloc_canonicalize("fr_FR_PREEURO", loc, 256, &status);
956 formatter = NumberFormat::createPercentInstance(Locale(loc), status);
957 failure(status, "NumberFormat::createPercentInstance", loc);
958 tempString.remove();
959 tempString = formatter->format (-5789.9876, tempString);
960
961 if (tempString == expectedPercent) {
962 logln ("Bug 4070798 percentage test passed.");
963 } else {
964 errln(UnicodeString("Failed:") +
965 " Expected " + expectedPercent +
966 " Received " + tempString );
967 }
968
969 delete formatter;
970 }
971 /* @bug 4071005
972 * Data rounding errors for French (Canada) locale
973 */
Test4071005(void)974 void NumberFormatRegressionTest::Test4071005 (void)
975 {
976 NumberFormat *formatter;
977 UnicodeString tempString;
978 /* User error :
979 String expectedDefault = "-5\u00a0789,987";
980 String expectedCurrency = "5\u00a0789,98\u00a0$";
981 String expectedPercent = "-578\u00a0998%";
982 */
983 UChar chars1 [] = {
984 0x2d, 0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x38, 0x38
985 };
986 UChar chars2 [] = {
987 0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x39, 0x00a0, 0x24
988 };
989 UChar chars3 [] = {
990 0x2d, 0x35, 0x37, 0x38, 0x00a0, 0x39, 0x39, 0x39, 0x00a0, 0x25
991 };
992 UnicodeString expectedDefault(chars1, 10, 10);
993 UnicodeString expectedCurrency(chars2, 10, 10);
994 UnicodeString expectedPercent(chars3, 10, 10);
995
996 UErrorCode status = U_ZERO_ERROR;
997 formatter = NumberFormat::createInstance(Locale::getCanadaFrench(), status);
998 if (failure(status, "NumberFormat::createInstance", Locale::getCanadaFrench(), TRUE)){
999 delete formatter;
1000 return;
1001 };
1002 tempString = formatter->format (-5789.9876, tempString);
1003
1004 if (tempString == expectedDefault) {
1005 logln ("Bug 4071005 default test passed.");
1006 } else {
1007 errln(UnicodeString("Failed:") +
1008 " Expected " + expectedDefault +
1009 " Received " + tempString );
1010 }
1011 delete formatter;
1012
1013 formatter = NumberFormat::createCurrencyInstance(Locale::getCanadaFrench(), status);
1014 failure(status, "NumberFormat::createCurrencyInstance", Locale::getCanadaFrench());
1015 tempString.remove();
1016 tempString = formatter->format( 5789.9876, tempString );
1017
1018 if (tempString == expectedCurrency) {
1019 logln ("Bug 4071005 currency test assed.");
1020 } else {
1021 errln(UnicodeString("Failed:") +
1022 " Expected " + expectedCurrency +
1023 " Received " + tempString );
1024 }
1025 delete formatter;
1026
1027 formatter = NumberFormat::createPercentInstance(Locale::getCanadaFrench(), status);
1028 failure(status, "NumberFormat::createPercentInstance", Locale::getCanadaFrench());
1029 tempString.remove();
1030 tempString = formatter->format (-5789.9876, tempString);
1031
1032 if (tempString == expectedPercent) {
1033 logln ("Bug 4071005 percentage test passed.");
1034 } else {
1035 errln(UnicodeString("Failed:") +
1036 " Expected " + expectedPercent +
1037 " Received " + tempString );
1038 }
1039
1040 delete formatter;
1041 }
1042
1043 /* @bug 4071014
1044 * Data rounding errors for German (Germany) locale
1045 */
Test4071014(void)1046 void NumberFormatRegressionTest::Test4071014 (void)
1047 {
1048 NumberFormat *formatter;
1049 UnicodeString tempString;
1050 /* user error :
1051 String expectedDefault = "-5.789,987";
1052 String expectedCurrency = "5.789,98 DM";
1053 String expectedPercent = "-578.998%";
1054 */
1055 UnicodeString expectedDefault("-5.789,988");
1056 UnicodeString expectedCurrency("5.789,99\\u00A0DM");
1057 UnicodeString expectedPercent("-578.999\\u00A0%");
1058
1059 expectedCurrency = expectedCurrency.unescape();
1060 expectedPercent = expectedPercent.unescape();
1061
1062 UErrorCode status = U_ZERO_ERROR;
1063 char loc[256]={0};
1064 uloc_canonicalize("de_DE_PREEURO", loc, 256, &status);
1065 formatter = NumberFormat::createInstance(Locale(loc), status);
1066 if (failure(status, "NumberFormat::createInstance", loc, TRUE)){
1067 delete formatter;
1068 return;
1069 }
1070 tempString.remove();
1071 tempString = formatter->format (-5789.9876, tempString);
1072
1073 if (tempString == expectedDefault) {
1074 logln ("Bug 4071014 default test passed.");
1075 } else {
1076 errln(UnicodeString("Failed:") +
1077 " Expected " + expectedDefault +
1078 " Received " + tempString );
1079 }
1080 delete formatter;
1081 uloc_canonicalize("de_DE_PREEURO", loc, 256, &status);
1082 formatter = NumberFormat::createCurrencyInstance(Locale(loc), status);
1083 failure(status, "NumberFormat::createCurrencyInstance", loc);
1084 tempString.remove();
1085 tempString = formatter->format( 5789.9876, tempString );
1086
1087 if (tempString == expectedCurrency) {
1088 logln ("Bug 4071014 currency test assed.");
1089 } else {
1090 errln(UnicodeString("Failed:") +
1091 " Expected " + expectedCurrency +
1092 " Received " + tempString );
1093 }
1094 delete formatter;
1095
1096 formatter = NumberFormat::createPercentInstance(Locale::getGermany(), status);
1097 failure(status, "NumberFormat::createPercentInstance", Locale::getGermany());
1098 tempString.remove();
1099 tempString = formatter->format (-5789.9876, tempString);
1100
1101 if (tempString == expectedPercent) {
1102 logln ("Bug 4071014 percentage test passed.");
1103 } else {
1104 errln(UnicodeString("Failed:") +
1105 " Expected " + expectedPercent +
1106 " Received " + tempString );
1107 }
1108
1109 delete formatter;
1110 }
1111 /* @bug 4071859
1112 * Data rounding errors for Italian locale number formats
1113 */
Test4071859(void)1114 void NumberFormatRegressionTest::Test4071859 (void)
1115 {
1116 NumberFormat *formatter;
1117 UnicodeString tempString;
1118 /* user error :
1119 String expectedDefault = "-5.789,987";
1120 String expectedCurrency = "-L.\\u00A05.789,98";
1121 String expectedPercent = "-578.998%";
1122 */
1123 UnicodeString expectedDefault("-5.789,988");
1124 UnicodeString expectedCurrency("-ITL\\u00A05.790", -1, US_INV);
1125 UnicodeString expectedPercent("-578.999%");
1126 expectedCurrency = expectedCurrency.unescape();
1127
1128 UErrorCode status = U_ZERO_ERROR;
1129 char loc[256]={0};
1130 uloc_canonicalize("it_IT_PREEURO", loc, 256, &status);
1131 formatter = NumberFormat::createInstance(Locale(loc), status);
1132 if (failure(status, "NumberFormat::createNumberInstance", TRUE)){
1133 delete formatter;
1134 return;
1135 };
1136 tempString = formatter->format (-5789.9876, tempString);
1137
1138 if (tempString == expectedDefault) {
1139 logln ("Bug 4071859 default test passed.");
1140 } else {
1141 errln(UnicodeString("Failed:") +
1142 " Expected " + expectedDefault +
1143 " Received " + tempString );
1144 }
1145 delete formatter;
1146 uloc_canonicalize("it_IT_PREEURO", loc, 256, &status);
1147 formatter = NumberFormat::createCurrencyInstance(Locale(loc), status);
1148 failure(status, "NumberFormat::createCurrencyInstance");
1149 tempString.remove();
1150 tempString = formatter->format( -5789.9876, tempString );
1151
1152 if (tempString == expectedCurrency) {
1153 logln ("Bug 4071859 currency test assed.");
1154 } else {
1155 errln(UnicodeString("Failed:") +
1156 " Expected " + expectedCurrency +
1157 " Received " + tempString );
1158 }
1159 delete formatter;
1160 uloc_canonicalize("it_IT_PREEURO", loc, 256, &status);
1161 formatter = NumberFormat::createPercentInstance(Locale(loc), status);
1162 failure(status, "NumberFormat::createPercentInstance");
1163 tempString.remove();
1164 tempString = formatter->format (-5789.9876, tempString);
1165
1166 if (tempString == expectedPercent) {
1167 logln ("Bug 4071859 percentage test passed.");
1168 } else {
1169 errln(UnicodeString("Failed:") +
1170 " Expected " + expectedPercent +
1171 " Received " + tempString );
1172 }
1173
1174 delete formatter;
1175 }
1176 /* @bug 4071859
1177 * Test rounding for nearest even.
1178 */
Test4093610(void)1179 void NumberFormatRegressionTest::Test4093610(void)
1180 {
1181 UErrorCode status = U_ZERO_ERROR;
1182 DecimalFormat df("#0.#", status);
1183 if (!failure(status, "new DecimalFormat")) {
1184 UnicodeString s("12.4");
1185 roundingTest(&df, 12.35, s);
1186 roundingTest(&df, 12.45, s);
1187 s = "12.5";
1188 roundingTest(&df, 12.452,s);
1189 s = "12.6";
1190 roundingTest(&df, 12.55, s);
1191 roundingTest(&df, 12.65, s);
1192 s = "12.7";
1193 roundingTest(&df, 12.652,s);
1194 s = "12.8";
1195 roundingTest(&df, 12.75, s);
1196 roundingTest(&df, 12.752,s);
1197 roundingTest(&df, 12.85, s);
1198 s = "12.9";
1199 roundingTest(&df, 12.852,s);
1200 s = "13";
1201 roundingTest(&df, 12.95, s);
1202 roundingTest(&df, 12.952,s);
1203 }
1204 }
1205
roundingTest(DecimalFormat * df,double x,UnicodeString & expected)1206 void NumberFormatRegressionTest::roundingTest(DecimalFormat *df, double x, UnicodeString& expected)
1207 {
1208 UnicodeString out;
1209 FieldPosition pos(FieldPosition::DONT_CARE);
1210 out = df->format(x, out, pos);
1211 logln(UnicodeString("") + x + " formats with 1 fractional digits to " + out);
1212 if (out != expected) {
1213 dataerrln("FAIL: Expected '%s'; got '%s'", CStr(expected)(), CStr(out)());
1214 }
1215 }
1216 /* @bug 4098741
1217 * Tests the setMaximumFractionDigits limit.
1218 */
Test4098741(void)1219 void NumberFormatRegressionTest::Test4098741(void)
1220 {
1221 //try {
1222 UErrorCode status = U_ZERO_ERROR;
1223 NumberFormat *fmt = NumberFormat::createPercentInstance(status);
1224 if (U_FAILURE(status)) {
1225 dataerrln("Error calling NumberFormat::createPercentInstance");
1226 delete fmt;
1227 return;
1228 }
1229
1230 fmt->setMaximumFractionDigits(20);
1231 UnicodeString temp;
1232 logln(fmt->format(.001, temp));
1233 /*} catch (Exception foo) {
1234 errln("Bug 4098471 failed with exception thrown : " + foo.getMessage());
1235 }*/
1236 delete fmt;
1237 }
1238 /* @bug 4074454
1239 * Tests illegal pattern exception.
1240 * Fix comment : HShih A31 Part1 will not be fixed and javadoc needs to be updated.
1241 * Part2 has been fixed.
1242 */
Test4074454(void)1243 void NumberFormatRegressionTest::Test4074454(void)
1244 {
1245 //try {
1246 UErrorCode status = U_ZERO_ERROR;
1247 DecimalFormat *fmt = new DecimalFormat("#,#00.00;-#.#", status);
1248 if(U_FAILURE(status)) {
1249 errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
1250 delete fmt;
1251 return;
1252 }
1253 failure(status, "new DecimalFormat");
1254 logln("Inconsistent negative pattern is fine.");
1255 DecimalFormat *newFmt = new DecimalFormat("#,#00.00 p''ieces;-#,#00.00 p''ieces", status);
1256 failure(status, "new DecimalFormat");
1257 UnicodeString tempString;
1258 FieldPosition pos(FieldPosition::DONT_CARE);
1259 tempString = newFmt->format(3456.78, tempString, pos);
1260 if (tempString != UnicodeString("3,456.78 p'ieces"))
1261 dataerrln("Failed! 3456.78 p'ieces expected, but got : " + tempString);
1262 /*} catch (Exception foo) {
1263 errln("An exception was thrown for any inconsistent negative pattern.");
1264 }*/
1265
1266 delete fmt;
1267 delete newFmt;
1268 }
1269 /* @bug 4099404
1270 * Tests all different comments.
1271 * Response to some comments :
1272 * [1] DecimalFormat.parse API documentation is more than just one line.
1273 * This is not a reproducable doc error in 116 source code.
1274 * [2] See updated javadoc.
1275 * [3] Fixed.
1276 * [4] NumberFormat.parse(String, ParsePosition) : If parsing fails,
1277 * a null object will be returned. The unchanged parse position also
1278 * reflects an error.
1279 * NumberFormat.parse(String) : If parsing fails, an ParseException
1280 * will be thrown.
1281 * See updated javadoc for more details.
1282 * [5] See updated javadoc.
1283 * [6] See updated javadoc.
1284 * [7] This is a correct behavior if the DateFormat object is linient.
1285 * Otherwise, an IllegalArgumentException will be thrown when formatting
1286 * "January 35". See GregorianCalendar class javadoc for more details.
1287 */
Test4099404(void)1288 void NumberFormatRegressionTest::Test4099404(void)
1289 {
1290 //try {
1291 UErrorCode status = U_ZERO_ERROR;
1292 DecimalFormat *fmt = new DecimalFormat(UnicodeString("000.0#0"), status);
1293 if(! U_FAILURE(status))
1294 errln(UnicodeString("Bug 4099404 failed applying illegal pattern \"000.0#0\""));
1295 /*} catch (Exception foo) {
1296 logln("Bug 4099404 pattern \"000.0#0\" passed");
1297 }*/
1298 delete fmt;
1299 fmt = 0;
1300 //try {
1301 fmt = new DecimalFormat(UnicodeString("0#0.000"), status);
1302 if( !U_FAILURE(status))
1303 errln("Bug 4099404 failed applying illegal pattern \"0#0.000\"");
1304 /*} catch (Exception foo) {
1305 logln("Bug 4099404 pattern \"0#0.000\" passed");
1306 }*/
1307
1308 delete fmt;
1309 }
1310 /* @bug 4101481
1311 * DecimalFormat.applyPattern doesn't set minimum integer digits
1312 */
Test4101481(void)1313 void NumberFormatRegressionTest::Test4101481(void)
1314 {
1315 UErrorCode status = U_ZERO_ERROR;
1316 DecimalFormat *sdf = new DecimalFormat(UnicodeString("#,##0"), status);
1317 if(U_FAILURE(status)) {
1318 errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
1319 delete sdf;
1320 return;
1321 }
1322 failure(status, "new DecimalFormat");
1323 if (sdf->getMinimumIntegerDigits() != 1)
1324 errln(UnicodeString("Minimum integer digits : ") + sdf->getMinimumIntegerDigits());
1325 delete sdf;
1326 }
1327 /* @bug 4052223 (API addition request A27)
1328 * Tests ParsePosition.setErrorPosition() and ParsePosition.getErrorPosition().
1329 */
Test4052223(void)1330 void NumberFormatRegressionTest::Test4052223(void)
1331 {
1332 //try {
1333 UErrorCode status = U_ZERO_ERROR;
1334 DecimalFormat *fmt = new DecimalFormat(UnicodeString("#,#00.00"), status);
1335 if(U_FAILURE(status)) {
1336 errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
1337 delete fmt;
1338 return;
1339 }
1340 failure(status, "new DecimalFormat");
1341 Formattable num;
1342 fmt->parse(UnicodeString("abc3"), num, status);
1343 if(! U_FAILURE(status))
1344 errln(UnicodeString("Bug 4052223 failed : can't parse string \"a\". Got ") /*+ num*/);
1345 /*} catch (ParseException foo) {
1346 logln("Caught expected ParseException : " + foo.getMessage() + " at index : " + foo.getErrorOffset());
1347 }*/
1348 delete fmt;
1349 }
1350 /* @bug 4061302
1351 * API tests for API addition request A9.
1352 */
Test4061302(void)1353 void NumberFormatRegressionTest::Test4061302(void)
1354 {
1355 UErrorCode status = U_ZERO_ERROR;
1356 DecimalFormatSymbols *fmt = new DecimalFormatSymbols(status);
1357 if (U_FAILURE(status)) {
1358 dataerrln("Error creating DecimalFormatSymbols - %s", u_errorName(status));
1359 return;
1360 }
1361 UnicodeString currency(fmt->getSymbol(DecimalFormatSymbols::kCurrencySymbol));
1362 UnicodeString intlCurrency(fmt->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol));
1363 UnicodeString monDecSeparator(fmt->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol));
1364 if (currency == UnicodeString("") ||
1365 intlCurrency == UnicodeString("") ||
1366 monDecSeparator == UnicodeString(""))
1367 {
1368 errln("getCurrencySymbols failed, got empty string.");
1369 }
1370 UnicodeString monDecSeparatorStr;
1371 monDecSeparatorStr.append(monDecSeparator);
1372 logln((UnicodeString)"Before set ==> Currency : " + currency +(UnicodeString)" Intl Currency : " + intlCurrency + (UnicodeString)" Monetary Decimal Separator : " + monDecSeparatorStr);
1373 fmt->setSymbol(DecimalFormatSymbols::kCurrencySymbol, UnicodeString("XYZ"));
1374 fmt->setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol, UnicodeString("ABC"));
1375 fmt->setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol, UnicodeString((UChar)0x002A/*'*'*/));
1376 currency = fmt->getSymbol(DecimalFormatSymbols::kCurrencySymbol);
1377 intlCurrency = fmt->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol);
1378 monDecSeparator = fmt->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol);
1379 if (currency != UnicodeString("XYZ") ||
1380 intlCurrency != UnicodeString("ABC") ||
1381 monDecSeparator != UnicodeString((UChar)0x002A/*'*'*/)) {
1382 errln("setCurrencySymbols failed.");
1383 }
1384 monDecSeparatorStr.remove();
1385 monDecSeparatorStr.append(monDecSeparator);
1386 logln("After set ==> Currency : " + currency + " Intl Currency : " + intlCurrency + " Monetary Decimal Separator : " + monDecSeparatorStr);
1387
1388 delete fmt;
1389 }
1390 /* @bug 4062486
1391 * API tests for API addition request A23. FieldPosition.getBeginIndex and
1392 * FieldPosition.getEndIndex.
1393 */
Test4062486(void)1394 void NumberFormatRegressionTest::Test4062486(void)
1395 {
1396 UErrorCode status = U_ZERO_ERROR;
1397 DecimalFormat *fmt = new DecimalFormat(UnicodeString("#,##0.00"), status);
1398 if (U_FAILURE(status)) {
1399 dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
1400 return;
1401 }
1402 UnicodeString formatted;
1403 FieldPosition field(FieldPosition::DONT_CARE);
1404 double num = 1234.5;
1405 fmt->format(num, formatted, field);
1406 if (field.getBeginIndex() != 0 && field.getEndIndex() != 5)
1407 errln(UnicodeString("Format 1234.5 failed. Begin index: ") /*+ field.getBeginIndex() + " End index: " + field.getEndIndex()*/);
1408 field.setBeginIndex(7);
1409 field.setEndIndex(4);
1410 if (field.getBeginIndex() != 7 && field.getEndIndex() != 4)
1411 errln("Set begin/end field indexes failed. Begin index: " /*+ field.getBeginIndex() + " End index: " + field.getEndIndex()*/);
1412
1413 delete fmt;
1414 }
1415
1416 /* @bug 4108738
1417 * DecimalFormat.parse incorrectly works with a group separator.
1418 */
Test4108738(void)1419 void NumberFormatRegressionTest::Test4108738(void)
1420 {
1421 UErrorCode status = U_ZERO_ERROR;
1422 DecimalFormatSymbols *syms = new DecimalFormatSymbols(Locale::getUS(), status);
1423 failure(status, "new DecimalFormatSymbols");
1424 DecimalFormat *df = new DecimalFormat("#,##0.###", syms, status);
1425 if(U_FAILURE(status)) {
1426 errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
1427 delete df;
1428 return;
1429 }
1430 failure(status, "new DecimalFormat");
1431 UnicodeString text("1.222,111");
1432 Formattable num;
1433 ParsePosition pp(0);
1434 df->parse(text, num, pp);
1435
1436 // {sfb} how to do this (again) ?
1437 // shouldn't just be another round-trip test, should it?
1438 UnicodeString temp;
1439 FieldPosition pos(FieldPosition::DONT_CARE);
1440 temp = df->format(num.getDouble(), temp, pos);
1441 //if (!num.toString().equals("1.222"))
1442 if (temp != UnicodeString("1.222"))
1443 //errln("\"" + text + "\" is parsed as " + num);
1444 errln("\"" + text + "\" is parsed as " + temp);
1445 text = UnicodeString("1.222x111");
1446 pp = ParsePosition(0);
1447 df->parse(text, num, pp);
1448 temp.remove();
1449 temp = df->format(num.getDouble(), temp, pos);
1450 //if (!num.toString().equals("1.222"))
1451 if (temp != UnicodeString("1.222"))
1452 errln("\"" + text + "\" is parsed as " + temp);
1453
1454 delete df;
1455 }
1456
1457 /* @bug 4106658
1458 * DecimalFormat.format() incorrectly formats negative doubles.
1459 */
Test4106658(void)1460 void NumberFormatRegressionTest::Test4106658(void)
1461 {
1462 UErrorCode status = U_ZERO_ERROR;
1463 DecimalFormat *df = new DecimalFormat(status); // Corrected; see 4147706
1464 if(U_FAILURE(status)) {
1465 errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
1466 delete df;
1467 return;
1468 }
1469 failure(status, "new DecimalFormat");
1470 volatile double d1 = 0.0; // volatile to prevent code optimization
1471 double d2 = -0.0001;
1472 UnicodeString buffer;
1473 UnicodeString temp;
1474 FieldPosition pos(FieldPosition::DONT_CARE);
1475
1476 #if U_PLATFORM == U_PF_HPUX
1477 d1 = 0.0 * -1.0; // old HPUX compiler ignores volatile keyword
1478 #else
1479 d1 *= -1.0; // Some compilers have a problem with defining -0.0
1480 #endif
1481 logln("pattern: \"" + df->toPattern(temp) + "\"");
1482 df->format(d1, buffer, pos);
1483 if (buffer != UnicodeString("-0")) // Corrected; see 4147706
1484 errln(UnicodeString("") + d1 + " is formatted as " + buffer);
1485 buffer.remove();
1486 df->format(d2, buffer, pos);
1487 if (buffer != UnicodeString("-0")) // Corrected; see 4147706
1488 errln(UnicodeString("") + d2 + " is formatted as " + buffer);
1489
1490 delete df;
1491 }
1492
1493 /* @bug 4106662
1494 * DecimalFormat.parse returns 0 if string parameter is incorrect.
1495 */
Test4106662(void)1496 void NumberFormatRegressionTest::Test4106662(void)
1497 {
1498 UErrorCode status = U_ZERO_ERROR;
1499 DecimalFormat *df = new DecimalFormat(status);
1500 if(U_FAILURE(status)) {
1501 errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
1502 delete df;
1503 return;
1504 }
1505 failure(status, "new DecimalFormat");
1506 UnicodeString text("x");
1507 ParsePosition pos1(0), pos2(0);
1508
1509 UnicodeString temp;
1510 logln("pattern: \"" + df->toPattern(temp) + "\"");
1511 Formattable num;
1512 df->parse(text, num, pos1);
1513 if (pos1 == ParsePosition(0)/*num != null*/) {
1514 errln(UnicodeString("Test Failed: \"") + text + "\" is parsed as " /*+ num*/);
1515 }
1516 delete df;
1517 df = new DecimalFormat(UnicodeString("$###.00"), status);
1518 failure(status, "new DecimalFormat");
1519 df->parse(UnicodeString("$"), num, pos2);
1520 if (pos2 == ParsePosition(0) /*num != null*/){
1521 errln(UnicodeString("Test Failed: \"$\" is parsed as ") /*+ num*/);
1522 }
1523
1524 delete df;
1525 }
1526
1527 /* @bug 4114639 (duplicate of 4106662)
1528 * NumberFormat.parse doesn't return null
1529 */
Test4114639(void)1530 void NumberFormatRegressionTest::Test4114639(void)
1531 {
1532 UErrorCode status = U_ZERO_ERROR;
1533 NumberFormat *format = NumberFormat::createInstance(status);
1534 if(U_FAILURE(status)) {
1535 dataerrln("Error creating DecimalFormat: %s", u_errorName(status));
1536 delete format;
1537 return;
1538 }
1539 failure(status, "NumberFormat::createInstance");
1540 UnicodeString text("time 10:x");
1541 ParsePosition pos(8);
1542 Formattable result;
1543 format->parse(text, result, pos);
1544 if (/*result != null*/pos.getErrorIndex() != 8)
1545 errln(UnicodeString("Should return null but got : ") /*+ result*/); // Should be null; it isn't
1546
1547 delete format;
1548 }
1549
1550 /* @bug 4106664
1551 * TODO: this test does not work because we need to use a 64 bit number and a
1552 * a double only MAY only have 52 bits of precision.
1553 * DecimalFormat.format(long n) fails if n * multiplier > MAX_LONG.
1554 */
Test4106664(void)1555 void NumberFormatRegressionTest::Test4106664(void)
1556 {
1557 UErrorCode status = U_ZERO_ERROR;
1558 DecimalFormat *df = new DecimalFormat(status);
1559 if(U_FAILURE(status)) {
1560 errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
1561 delete df;
1562 return;
1563 }
1564 failure(status, "new DecimalFormat");
1565 // {sfb} long in java is 64 bits
1566 /*long*/double n = 1234567890123456.0;
1567 /*int*/int32_t m = 12345678;
1568 // {sfb} will this work?
1569 //BigInteger bigN = BigInteger.valueOf(n);
1570 //bigN = bigN.multiply(BigInteger.valueOf(m));
1571 double bigN = n * m;
1572 df->setMultiplier(m);
1573 df->setGroupingUsed(FALSE);
1574 UnicodeString temp;
1575 FieldPosition pos(FieldPosition::DONT_CARE);
1576 logln("formated: " +
1577 df->format(n, temp, pos));
1578
1579 char buf [128];
1580 sprintf(buf, "%g", bigN);
1581 //logln("expected: " + bigN.toString());
1582 logln(UnicodeString("expected: ") + buf);
1583
1584 delete df;
1585 }
1586 /* @bug 4106667 (duplicate of 4106658)
1587 * DecimalFormat.format incorrectly formats -0.0.
1588 */
Test4106667(void)1589 void NumberFormatRegressionTest::Test4106667(void)
1590 {
1591 UErrorCode status = U_ZERO_ERROR;
1592 DecimalFormat *df = new DecimalFormat(status);
1593 if(U_FAILURE(status)) {
1594 errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
1595 delete df;
1596 return;
1597 }
1598 failure(status, "new DecimalFormat");
1599 UChar foo [] = { 0x002B };
1600 UnicodeString bar(foo, 1, 1);
1601 volatile double d = 0.0; // volatile to prevent code optimization
1602 UnicodeString temp;
1603 UnicodeString buffer;
1604 FieldPosition pos(FieldPosition::DONT_CARE);
1605
1606 logln("pattern: \"" + df->toPattern(temp) + "\"");
1607 #if U_PLATFORM == U_PF_HPUX
1608 d = 0.0 * -1.0; // old HPUX compiler ignores volatile keyword
1609 #else
1610 d *= -1.0; // Some compilers have a problem with defining -0.0
1611 #endif
1612 df->setPositivePrefix(/*"+"*/bar);
1613 df->format(d, buffer, pos);
1614 if (buffer != UnicodeString("-0")) // Corrected; see 4147706
1615 errln(/*d + */UnicodeString(" is formatted as ") + buffer);
1616
1617 delete df;
1618 }
1619
1620 /* @bug 4110936
1621 * DecimalFormat.setMaximumIntegerDigits() works incorrectly.
1622 */
1623 #if U_PLATFORM == U_PF_OS390
1624 # define MAX_INT_DIGITS 70
1625 #else
1626 # define MAX_INT_DIGITS 128
1627 #endif
1628
Test4110936(void)1629 void NumberFormatRegressionTest::Test4110936(void)
1630 {
1631 UErrorCode status = U_ZERO_ERROR;
1632 NumberFormat *nf = NumberFormat::createInstance(status);
1633 if(U_FAILURE(status)) {
1634 dataerrln("Error creating DecimalFormat: %s", u_errorName(status));
1635 delete nf;
1636 return;
1637 }
1638 failure(status, "NumberFormat::createInstance");
1639 nf->setMaximumIntegerDigits(MAX_INT_DIGITS);
1640 logln("setMaximumIntegerDigits(MAX_INT_DIGITS)");
1641 if (nf->getMaximumIntegerDigits() != MAX_INT_DIGITS)
1642 errln(UnicodeString("getMaximumIntegerDigits() returns ") +
1643 nf->getMaximumIntegerDigits());
1644
1645 delete nf;
1646 }
1647
1648 /* @bug 4122840
1649 * Locale data should use generic currency symbol
1650 *
1651 * 1) Make sure that all currency formats use the generic currency symbol.
1652 * 2) Make sure we get the same results using the generic symbol or a
1653 * hard-coded one.
1654 */
Test4122840(void)1655 void NumberFormatRegressionTest::Test4122840(void)
1656 {
1657 int32_t count = 0;
1658 const Locale *locales = Locale::getAvailableLocales(count);
1659
1660 for (int i = 0; i < count; i++) {
1661 UErrorCode status = U_ZERO_ERROR;
1662 ResourceBundle *rb = new ResourceBundle(
1663 NULL/*"java.text.resources.LocaleElements"*/,
1664 locales[i], status);
1665 failure(status, "new ResourceBundle");
1666 ResourceBundle numPat = rb->getWithFallback("NumberElements", status);
1667 failure(status, "rb.get(NumberElements)");
1668 numPat = numPat.getWithFallback("latn",status);
1669 failure(status, "rb.get(latn)");
1670 numPat = numPat.getWithFallback("patterns",status);
1671 failure(status, "rb.get(patterns)");
1672 numPat = numPat.getWithFallback("currencyFormat",status);
1673 failure(status, "rb.get(currencyFormat)");
1674 //
1675 // Get the currency pattern for this locale. We have to fish it
1676 // out of the ResourceBundle directly, since DecimalFormat.toPattern
1677 // will return the localized symbol, not \00a4
1678 //
1679 UnicodeString pattern = numPat.getString(status);
1680 failure(status, "rb->getString()");
1681
1682 UChar fo[] = { 0x00A4 };
1683 UnicodeString foo(fo, 1, 1);
1684
1685 //if (pattern.indexOf("\u00A4") == -1 ) {
1686 if (pattern.indexOf(foo) == -1 ) {
1687 errln(UnicodeString("Currency format for ") + UnicodeString(locales[i].getName()) +
1688 " does not contain generic currency symbol:" +
1689 pattern );
1690 }
1691
1692 // Create a DecimalFormat using the pattern we got and format a number
1693 DecimalFormatSymbols *symbols = new DecimalFormatSymbols(locales[i], status);
1694 failure(status, "new DecimalFormatSymbols");
1695
1696 // Disable currency spacing for the purposes of this test.
1697 // To do this, set the spacing insert to the empty string both before and after the symbol.
1698 symbols->setPatternForCurrencySpacing(UNUM_CURRENCY_INSERT, FALSE, u"");
1699 symbols->setPatternForCurrencySpacing(UNUM_CURRENCY_INSERT, TRUE, u"");
1700
1701 DecimalFormat *fmt1 = new DecimalFormat(pattern, *symbols, status);
1702 failure(status, "new DecimalFormat");
1703
1704 UnicodeString result1;
1705 FieldPosition pos(FieldPosition::DONT_CARE);
1706 result1 = fmt1->format(1.111, result1, pos);
1707
1708 //
1709 // Now substitute in the locale's currency symbol and create another
1710 // pattern. We have to skip locales where the currency symbol
1711 // contains decimal separators, because that confuses things
1712 //
1713 UChar ba[] = { 0x002E/*'.'*/ };
1714 UnicodeString bar(ba, 1, 1);
1715
1716 if (symbols->getSymbol(DecimalFormatSymbols::kCurrencySymbol).indexOf(bar) == -1) {
1717 // {sfb} Also, switch the decimal separator to the monetary decimal
1718 // separator to mimic the behavior of a currency format
1719 symbols->setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol,
1720 symbols->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol));
1721
1722 UnicodeString buf(pattern);
1723 for (int j = 0; j < buf.length(); j++) {
1724 if (buf[j] == 0x00a4 ) {
1725 if(buf[j + 1] == 0x00a4) {
1726 // {sfb} added to support double currency marker (intl currency sign)
1727 buf.replace(j, /*j+*/2, symbols->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol));
1728 j += symbols->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol).length();
1729 }
1730 else {
1731 buf.replace(j, /*j+*/1, symbols->getSymbol(DecimalFormatSymbols::kCurrencySymbol));
1732 j += symbols->getSymbol(DecimalFormatSymbols::kCurrencySymbol).length() - 1;
1733 }
1734 }
1735 }
1736
1737 DecimalFormat *fmt2 = new DecimalFormat(buf, *symbols, status);
1738 failure(status, "new DecimalFormat");
1739
1740 // Get the currency (if there is one) so we can set the rounding and fraction
1741 const UChar *currency = fmt1->getCurrency();
1742 if (*currency != 0) {
1743 double rounding = ucurr_getRoundingIncrement(currency, &status);
1744 int32_t frac = ucurr_getDefaultFractionDigits(currency, &status);
1745 if (U_SUCCESS(status)) {
1746 fmt2->setRoundingIncrement(rounding);
1747 fmt2->setMinimumFractionDigits(frac);
1748 fmt2->setMaximumFractionDigits(frac);
1749 }
1750 else {
1751 failure(status, "Fetching currency rounding/fractions");
1752 }
1753 }
1754
1755 UnicodeString result2;
1756 fmt2->format(1.111, result2, pos);
1757
1758 if (result1 != result2) {
1759 errln("Results for " + (UnicodeString)(locales[i].getName()) + " differ: " +
1760 result1 + " vs " + result2);
1761 }
1762
1763 delete fmt2;
1764 }
1765
1766 delete rb;
1767 delete fmt1;
1768 delete symbols;
1769 }
1770 }
1771
1772 /* @bug 4125885
1773 * DecimalFormat.format() delivers wrong string.
1774 */
Test4125885(void)1775 void NumberFormatRegressionTest::Test4125885(void)
1776 {
1777 UErrorCode status = U_ZERO_ERROR;
1778 double rate = 12.34;
1779 DecimalFormat *formatDec = new DecimalFormat ("000.00", status);
1780 if(U_FAILURE(status)) {
1781 errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status));
1782 delete formatDec;
1783 return;
1784 }
1785 failure(status, "new DecimalFormat");
1786 UnicodeString temp;
1787 logln("toPattern: " + formatDec->toPattern(temp));
1788 UnicodeString rateString;
1789 FieldPosition pos(FieldPosition::DONT_CARE);
1790 rateString = formatDec->format(rate, rateString, pos);
1791 if (rateString != UnicodeString("012.34"))
1792 errln("result : " + rateString + " expected : 012.34");
1793 rate = 0.1234;
1794 delete formatDec;// = null;
1795 formatDec = new DecimalFormat ("+000.00%;-000.00%", status);
1796 failure(status, "new DecimalFormat");
1797 logln("toPattern: " + formatDec->toPattern(temp));
1798 rateString.remove();
1799 rateString = formatDec->format(rate, rateString, pos);
1800 if (rateString != UnicodeString("+012.34%"))
1801 errln("result : " + rateString + " expected : +012.34%");
1802
1803 delete formatDec;
1804 }
1805
1806 /**
1807 * @bug 4134034
1808 * DecimalFormat produces extra zeros when formatting numbers.
1809 */
Test4134034(void)1810 void NumberFormatRegressionTest::Test4134034(void)
1811 {
1812 UErrorCode status = U_ZERO_ERROR;
1813 DecimalFormat *nf = new DecimalFormat("##,###,###.00", status);
1814 if (!failure(status, "new DecimalFormat")) {
1815 UnicodeString f;
1816 FieldPosition pos(FieldPosition::DONT_CARE);
1817 f = nf->format(9.02, f, pos);
1818 if (f == UnicodeString("9.02"))
1819 logln(f + " ok");
1820 else
1821 errln("9.02 -> " + f + "; want 9.02");
1822
1823 f.remove();
1824 f = nf->format((int32_t)0, f, pos);
1825 if (f == UnicodeString(".00"))
1826 logln(f + " ok");
1827 else
1828 errln("0 -> " + f + "; want .00");
1829 }
1830
1831 delete nf;
1832 }
1833
1834 /**
1835 * @bug 4134300
1836 * CANNOT REPRODUCE - This bug could not be reproduced. It may be
1837 * a duplicate of 4134034.
1838 *
1839 * JDK 1.1.6 Bug, did NOT occur in 1.1.5
1840 * Possibly related to bug 4125885.
1841 *
1842 * This class demonstrates a regression in version 1.1.6
1843 * of DecimalFormat class.
1844 *
1845 * 1.1.6 Results
1846 * Value 1.2 Format #.00 Result '01.20' !!!wrong
1847 * Value 1.2 Format 0.00 Result '001.20' !!!wrong
1848 * Value 1.2 Format 00.00 Result '0001.20' !!!wrong
1849 * Value 1.2 Format #0.0# Result '1.2'
1850 * Value 1.2 Format #0.00 Result '001.20' !!!wrong
1851 *
1852 * 1.1.5 Results
1853 * Value 1.2 Format #.00 Result '1.20'
1854 * Value 1.2 Format 0.00 Result '1.20'
1855 * Value 1.2 Format 00.00 Result '01.20'
1856 * Value 1.2 Format #0.0# Result '1.2'
1857 * Value 1.2 Format #0.00 Result '1.20'
1858 */
Test4134300(void)1859 void NumberFormatRegressionTest::Test4134300(void) {
1860 UnicodeString DATA [] = {
1861 // Pattern Expected string
1862 UnicodeString("#.00"), UnicodeString("1.20"),
1863 UnicodeString("0.00"), UnicodeString("1.20"),
1864 UnicodeString("00.00"), UnicodeString("01.20"),
1865 UnicodeString("#0.0#"), UnicodeString("1.2"),
1866 UnicodeString("#0.00"), UnicodeString("1.20")
1867 };
1868
1869 for (int i=0; i< 10; i+=2) {
1870 UnicodeString result;
1871 UErrorCode status = U_ZERO_ERROR;
1872 DecimalFormat *df = new DecimalFormat(DATA[i], status);
1873 if (!failure(status, "new DecimalFormat")) {
1874 FieldPosition pos(FieldPosition::DONT_CARE);
1875 result = df->format(1.2, result, pos);
1876 if (result != DATA[i+1]) {
1877 errln("Fail: 1.2 x " + DATA[i] + " = " + result +
1878 "; want " + DATA[i+1]);
1879 }
1880 else {
1881 logln("Ok: 1.2 x " + DATA[i] + " = " + result);
1882 }
1883 }
1884
1885 delete df;
1886 }
1887 }
1888
1889 /**
1890 * @bug 4140009
1891 * Empty pattern produces double negative prefix.
1892 */
Test4140009(void)1893 void NumberFormatRegressionTest::Test4140009(void)
1894 {
1895 UErrorCode status = U_ZERO_ERROR;
1896 LocalPointer<DecimalFormatSymbols> syms(new DecimalFormatSymbols(Locale::getEnglish(), status), status);
1897 if (failure(status, "new DecimalFormatSymbols")) {
1898 return;
1899 }
1900 DecimalFormat *f = new DecimalFormat(UnicodeString(u""), syms.orphan(), status);
1901 if (!failure(status, "new DecimalFormat")) {
1902 UnicodeString s;
1903 FieldPosition pos(FieldPosition::DONT_CARE);
1904 s = f->format(123.456, s, pos);
1905 if (s != UnicodeString("123.456"))
1906 errln("Fail: Format empty pattern x 123.456 => " + s);
1907 s.remove();
1908 s = f->format(-123.456, s, pos);
1909 if (s != UnicodeString("-123.456"))
1910 errln("Fail: Format empty pattern x -123.456 => " + s);
1911 }
1912 delete f;
1913 }
1914
1915 /**
1916 * @bug 4141750
1917 * BigDecimal numbers get their fractions truncated by NumberFormat.
1918 */
1919 // {sfb} not pertinent in C++ ??
Test4141750(void)1920 void NumberFormatRegressionTest::Test4141750(void) {
1921 /*try {
1922 UnicodeString str("12345.67");
1923 BigDecimal bd = new BigDecimal(str);
1924 String sd = NumberFormat.getInstance(Locale.US).format(bd);
1925 if (!sd.endsWith("67")) errln("Fail: " + str + " x format -> " + sd);
1926 }
1927 catch (Exception e) {
1928 errln(e.toString());
1929 e.printStackTrace();
1930 }*/
1931 }
1932
1933 /**
1934 * @bug 4145457
1935 * DecimalFormat toPattern() doesn't quote special characters or handle
1936 * single quotes.
1937 */
Test4145457()1938 void NumberFormatRegressionTest::Test4145457() {
1939 //try {
1940 UErrorCode status = U_ZERO_ERROR;
1941 NumberFormat *nff = NumberFormat::createInstance(status);
1942 if (failure(status, "NumberFormat::createInstance", TRUE)){
1943 delete nff;
1944 return;
1945 };
1946 DecimalFormat *nf = dynamic_cast<DecimalFormat *>(nff);
1947 if(nf == NULL) {
1948 errln("DecimalFormat needed to continue");
1949 return;
1950 }
1951
1952 DecimalFormatSymbols *sym = (DecimalFormatSymbols*) nf->getDecimalFormatSymbols();
1953 sym->setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, (UChar)/*'\''*/0x0027);
1954 nf->setDecimalFormatSymbols(*sym);
1955 double pi = 3.14159;
1956
1957 UnicodeString PATS [] = {
1958 UnicodeString("#.00 'num''ber'"), UnicodeString("''#.00''")
1959 };
1960
1961 for (int32_t i=0; i<2; ++i) {
1962 nf->applyPattern(PATS[i], status);
1963 failure(status, "nf->applyPattern");
1964 UnicodeString out;
1965 FieldPosition pos(FieldPosition::DONT_CARE);
1966 out = nf->format(pi, out, pos);
1967 UnicodeString pat;
1968 pat = nf->toPattern(pat);
1969 Formattable num;
1970 ParsePosition pp(0);
1971 nf->parse(out, num, pp);
1972 double val = num.getDouble();
1973
1974 nf->applyPattern(pat, status);
1975 failure(status, "nf->applyPattern");
1976 UnicodeString out2;
1977 out2 = nf->format(pi, out2, pos);
1978 UnicodeString pat2;
1979 pat2 = nf->toPattern(pat2);
1980 pp.setIndex(0);
1981 nf->parse(out2, num, pp);
1982 double val2 = num.getDouble();
1983
1984 if (pat != pat2)
1985 errln("Fail with \"" + PATS[i] + "\": Patterns should concur, \"" +
1986 pat + "\" vs. \"" + pat2 + "\"");
1987 else
1988 logln("Ok \"" + PATS[i] + "\" toPattern() -> \"" + pat + '"');
1989
1990 if (val == val2 && out == out2) {
1991 logln(UnicodeString("Ok ") + pi + " x \"" + PATS[i] + "\" -> \"" +
1992 out + "\" -> " + val + " -> \"" +
1993 out2 + "\" -> " + val2);
1994 }
1995 else {
1996 errln(UnicodeString("Fail ") + pi + " x \"" + PATS[i] + "\" -> \"" +
1997 out + "\" -> " + val + " -> \"" +
1998 out2 + "\" -> " + val2);
1999 }
2000 }
2001 /*}
2002 catch (ParseException e) {
2003 errln("Fail: " + e);
2004 e.printStackTrace();
2005 }*/
2006
2007 delete nff;
2008 }
2009
2010 /**
2011 * @bug 4147295
2012 * DecimalFormat.applyPattern() sets minimum integer digits incorrectly.
2013 * CANNOT REPRODUCE
2014 * This bug is a duplicate of 4139344, which is a duplicate of 4134300
2015 *
2016 * ICU 62: minInt is always at least one, and the getter should reflect that!
2017 */
Test4147295(void)2018 void NumberFormatRegressionTest::Test4147295(void)
2019 {
2020 UErrorCode status = U_ZERO_ERROR;
2021 DecimalFormat *sdf = new DecimalFormat(status);
2022 UnicodeString pattern("#,###");
2023 logln("Applying pattern \"" + pattern + "\"");
2024 sdf->applyPattern(pattern, status);
2025 if (!failure(status, "sdf->applyPattern")) {
2026 int minIntDig = sdf->getMinimumIntegerDigits();
2027 if (minIntDig != 1) {
2028 errln("Test failed");
2029 errln(UnicodeString(" Minimum integer digits : ") + minIntDig);
2030 UnicodeString temp;
2031 errln(UnicodeString(" new pattern: ") + sdf->toPattern(temp));
2032 } else {
2033 logln("Test passed");
2034 logln(UnicodeString(" Minimum integer digits : ") + minIntDig);
2035 }
2036 }
2037 delete sdf;
2038 }
2039
2040 /**
2041 * @bug 4147706
2042 * DecimalFormat formats -0.0 as +0.0
2043 * See also older related bug 4106658, 4106667
2044 */
Test4147706(void)2045 void NumberFormatRegressionTest::Test4147706(void)
2046 {
2047 UErrorCode status = U_ZERO_ERROR;
2048 DecimalFormat *df = new DecimalFormat("#,##0.0##", status);
2049 failure(status, "new DecimalFormat");
2050 DecimalFormatSymbols *syms = new DecimalFormatSymbols(Locale::getEnglish(), status);
2051 if (!failure(status, "new DecimalFormatSymbols")) {
2052 UnicodeString f1;
2053 UnicodeString f2, temp;
2054 FieldPosition pos(FieldPosition::DONT_CARE);
2055 volatile double d1 = 0.0; // volatile to prevent code optimization
2056 double d2 = -0.0001;
2057
2058 #if U_PLATFORM == U_PF_HPUX
2059 d1 = 0.0 * -1.0; // old HPUX compiler ignores volatile keyword
2060 #else
2061 d1 *= -1.0; // Some compilers have a problem with defining -0.0
2062 #endif
2063 df->adoptDecimalFormatSymbols(syms);
2064 f1 = df->format(d1, f1, pos);
2065 f2 = df->format(d2, f2, pos);
2066 if (f1 != UnicodeString("-0.0")) {
2067 errln(UnicodeString("") + d1 + UnicodeString(" x \"") + df->toPattern(temp) + "\" is formatted as \"" + f1 + '"');
2068 }
2069 if (f2 != UnicodeString("-0.0")) {
2070 errln(UnicodeString("") + d2 + UnicodeString(" x \"") + df->toPattern(temp) + "\" is formatted as \"" + f2 + '"');
2071 }
2072 }
2073
2074 delete df;
2075 }
2076
2077
2078 // Not applicable, since no serialization in C++
2079 /*class myformat implements Serializable
2080 {
2081 DateFormat _dateFormat = DateFormat.getDateInstance();
2082
2083 public String Now()
2084 {
2085 GregorianCalendar calendar = new GregorianCalendar();
2086 Date t = calendar.getTime();
2087 String nowStr = _dateFormat.format(t);
2088 return nowStr;
2089 }
2090 }*/
2091
2092 /**
2093 * @bug 4162198
2094 * NumberFormat cannot format Double.MAX_VALUE
2095 */
2096 // TODO: make this test actually test something
2097 void
Test4162198(void)2098 NumberFormatRegressionTest::Test4162198(void)
2099 {
2100 // for some reason, DBL_MAX will not round trip. (bug in sprintf/atof)
2101 double dbl = INT32_MAX * 1000.0;
2102 UErrorCode status = U_ZERO_ERROR;
2103 NumberFormat *f = NumberFormat::createInstance(status);
2104 if(U_FAILURE(status)) {
2105 dataerrln("Couldn't create number format - %s", u_errorName(status));
2106 return;
2107 }
2108 f->setMaximumFractionDigits(INT32_MAX);
2109 f->setMaximumIntegerDigits(INT32_MAX);
2110 UnicodeString s;
2111 f->format(dbl,s);
2112 logln(UnicodeString("The number ") + dbl + " formatted to " + s);
2113 Formattable n;
2114 //try {
2115 f->parse(s, n, status);
2116 if(U_FAILURE(status))
2117 errln("Couldn't parse!");
2118 //} catch (java.text.ParseException e) {
2119 // errln("Caught a ParseException:");
2120 // e.printStackTrace();
2121 //}
2122
2123 //logln("The string " + s + " parsed as " + n);
2124
2125 // {dlf} The old code assumes n is a double, but it isn't any more...
2126 // Formattable apparently does not and never did interconvert... too bad.
2127 //if(n.getDouble() != dbl) {
2128 // errln("Round trip failure");
2129 //}
2130 if (n.getInt64() != dbl) {
2131 errln("Round trip failure");
2132 }
2133
2134 delete f;
2135 }
2136
2137 /**
2138 * @bug 4162852
2139 * NumberFormat does not parse negative zero.
2140 */
2141 void
Test4162852(void)2142 NumberFormatRegressionTest::Test4162852(void)
2143 {
2144 UErrorCode status = U_ZERO_ERROR;
2145 for(int32_t i=0; i < 2; ++i) {
2146 LocalPointer<NumberFormat> f(
2147 ((i == 0) ? NumberFormat::createInstance(status) : NumberFormat::createPercentInstance(status)),
2148 status);
2149 if(U_FAILURE(status)) {
2150 dataerrln("Couldn't create number format - %s", u_errorName(status));
2151 return;
2152 }
2153 double d = 0.0;
2154 d *= -1.0;
2155 UnicodeString s;
2156 f->format(d, s);
2157 Formattable n;
2158 f->parse(s, n, status);
2159 if(U_FAILURE(status)) {
2160 errln("Couldn't parse!");
2161 return;
2162 }
2163 double e = n.getDouble();
2164 logln("%f -> \"%s\" -> %f", d, CStr(s)(), e);
2165 #if (U_PLATFORM == U_PF_OS390 && !defined(IEEE_754)) || U_PLATFORM == U_PF_OS400
2166 if (e != 0.0) {
2167 #else
2168 if (e != 0.0 || (std::signbit(e) == false)) {
2169 #endif
2170 errln("Failed to parse negative zero");
2171 }
2172 }
2173 }
2174
2175 static double _u_abs(double a) { return a<0?-a:a; }
2176
2177 /**
2178 * May 17 1999 sync up - liu
2179 * @bug 4167494
2180 * NumberFormat truncates data
2181 */
2182 void NumberFormatRegressionTest::Test4167494(void) {
2183 UErrorCode status = U_ZERO_ERROR;
2184 NumberFormat *fmt = NumberFormat::createInstance(Locale::getUS(), status);
2185 if (failure(status, "NumberFormat::createInstance", TRUE)){
2186 delete fmt;
2187 return;
2188 };
2189
2190 double a = DBL_MAX * 0.99; // DBL_MAX itself overflows to +Inf
2191 UnicodeString s;
2192 fmt->format(a, s);
2193 Formattable num;
2194 fmt->parse(s, num, status);
2195 failure(status, "Parse");
2196 if (num.getType() == Formattable::kDouble &&
2197 _u_abs(num.getDouble() - a) / a < 0.01) { // RT within 1%
2198 logln(UnicodeString("") + a + " -> \"" + s + "\" -> " +
2199 toString(num) + " ok");
2200 } else {
2201 errln(UnicodeString("") + a + " -> \"" + s + "\" -> " +
2202 toString(num) + " FAIL");
2203 }
2204
2205 // We don't test Double.MIN_VALUE because the locale data for the US
2206 // currently doesn't specify enough digits to display Double.MIN_VALUE.
2207 // This is correct for now; however, we leave this here as a reminder
2208 // in case we want to address this later.
2209
2210 delete fmt;
2211 }
2212
2213 /**
2214 * May 17 1999 sync up - liu
2215 * @bug 4170798
2216 * DecimalFormat.parse() fails when ParseIntegerOnly set to true
2217 */
2218 void NumberFormatRegressionTest::Test4170798(void) {
2219 IcuTestErrorCode status(*this, "Test4170798");
2220 LocalPointer<DecimalFormat> df(dynamic_cast<DecimalFormat*>(
2221 NumberFormat::createInstance(Locale::getUS(), status)), status);
2222 if (!assertSuccess("", status, true, __FILE__, __LINE__)) {
2223 return;
2224 }
2225 {
2226 Formattable n;
2227 ParsePosition pos(0);
2228 df->parse("-0.0", n, pos);
2229 if (n.getType() != Formattable::kDouble
2230 || n.getDouble() != -0.0) {
2231 errln(UnicodeString("FAIL: default parse(\"-0.0\") returns ") + toString(n));
2232 }
2233 }
2234 df->setParseIntegerOnly(TRUE);
2235 {
2236 Formattable n;
2237 ParsePosition pos(0);
2238 df->parse("-0.0", n, pos);
2239 if (n.getType() != Formattable::kLong
2240 || n.getLong() != 0) {
2241 errln(UnicodeString("FAIL: integer parse(\"-0.0\") returns ") + toString(n));
2242 }
2243 }
2244 }
2245
2246 /**
2247 * May 17 1999 sync up - liu
2248 * toPattern only puts the first grouping separator in.
2249 */
2250 void NumberFormatRegressionTest::Test4176114(void) {
2251 const char* DATA[] = {
2252 "00", "00",
2253 "000", "000", // No grouping
2254 "#000", "000", // No grouping
2255 "#,##0", "#,##0",
2256 "#,000", "#,000",
2257 "0,000", "0,000",
2258 "00,000", "00,000",
2259 "000,000", "000,000",
2260 "0,000,000,000,000.0000", "0,000,000,000,000.0000", // Reported
2261 };
2262 int DATA_length = UPRV_LENGTHOF(DATA);
2263 UErrorCode status = U_ZERO_ERROR;
2264 UnicodeString s;
2265 for (int i=0; i<DATA_length; i+=2) {
2266 DecimalFormat df(DATA[i], status);
2267 if (!failure(status, "DecimalFormat constructor")) {
2268 df.toPattern(s);
2269 UnicodeString exp(DATA[i+1]);
2270 if (s != exp) {
2271 errln(UnicodeString("FAIL: ") + DATA[i] + " -> " +
2272 s + ", want " + exp);
2273 }
2274 }
2275 }
2276 }
2277
2278 /**
2279 * May 17 1999 sync up - liu
2280 * @bug 4179818
2281 * DecimalFormat is incorrectly rounding numbers like 1.2501 to 1.2
2282 */
2283 void NumberFormatRegressionTest::Test4179818(void) {
2284 const char* DATA[] = {
2285 // Input Pattern Expected output
2286 "1.2511", "#.#", "1.3",
2287 "1.2501", "#.#", "1.3",
2288 "0.9999", "#", "1",
2289 };
2290 int DATA_length = UPRV_LENGTHOF(DATA);
2291 double DOUBLE[] = {
2292 1.2511,
2293 1.2501,
2294 0.9999,
2295 };
2296 UErrorCode status = U_ZERO_ERROR;
2297 DecimalFormatSymbols sym(Locale::getUS(), status);
2298 failure(status, "Construct DecimalFormatSymbols");
2299 DecimalFormat fmt("#", sym, status);
2300 if (!failure(status, "Construct DecimalFormat")) {
2301 for (int i=0; i<DATA_length; i+=3) {
2302 double in = DOUBLE[i/3];
2303 UnicodeString pat(DATA[i+1]);
2304 UnicodeString exp(DATA[i+2]);
2305 fmt.applyPattern(pat, status);
2306 failure(status, "applyPattern");
2307 UnicodeString out;
2308 FieldPosition pos;
2309 fmt.format(in, out, pos);
2310 if (out == exp) {
2311 logln(UnicodeString("Ok: ") + in + " x " + pat + " = " + out);
2312 } else {
2313 errln(UnicodeString("FAIL: ") + in + " x " + pat + " = " + out +
2314 ", expected " + exp);
2315 }
2316 }
2317 }
2318 }
2319
2320 /**
2321 * May 17 1999 sync up - liu
2322 * Some DecimalFormatSymbols changes are not picked up by DecimalFormat.
2323 * This includes the minus sign, currency symbol, international currency
2324 * symbol, percent, and permille. This is filed as bugs 4212072 and
2325 * 4212073.
2326 */
2327 void NumberFormatRegressionTest::Test4212072(void) {
2328 UErrorCode status = U_ZERO_ERROR;
2329 DecimalFormatSymbols sym(Locale::getUS(), status);
2330
2331 failure(status, "DecimalFormatSymbols ct", Locale::getUS());
2332 DecimalFormat fmt(UnicodeString("#"), sym, status);
2333 if(failure(status, "DecimalFormat ct", Locale::getUS())) {
2334 return;
2335 }
2336
2337 UnicodeString s;
2338 FieldPosition pos;
2339
2340 sym.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, (UChar)0x5e);
2341 fmt.setDecimalFormatSymbols(sym);
2342 s.remove();
2343 if (fmt.format((int32_t)-1, s, pos) != UNICODE_STRING("^1", 2)) {
2344 errln(UnicodeString("FAIL: -1 x (minus=^) -> ") + s +
2345 ", exp ^1");
2346 }
2347 s.remove();
2348 if (fmt.getNegativePrefix(s) != UnicodeString((UChar)0x5e)) {
2349 errln(UnicodeString("FAIL: (minus=^).getNegativePrefix -> ") +
2350 s + ", exp ^");
2351 }
2352 sym.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, (UChar)0x2d);
2353
2354 fmt.applyPattern(UnicodeString("#%"), status);
2355 failure(status, "applyPattern percent");
2356 sym.setSymbol(DecimalFormatSymbols::kPercentSymbol, (UChar)0x5e);
2357 fmt.setDecimalFormatSymbols(sym);
2358 s.remove();
2359 if (fmt.format(0.25, s, pos) != UNICODE_STRING("25^", 3)) {
2360 errln(UnicodeString("FAIL: 0.25 x (percent=^) -> ") + s +
2361 ", exp 25^");
2362 }
2363 s.remove();
2364 if (fmt.getPositiveSuffix(s) != UnicodeString((UChar)0x5e)) {
2365 errln(UnicodeString("FAIL: (percent=^).getPositiveSuffix -> ") +
2366 s + ", exp ^");
2367 }
2368 sym.setSymbol(DecimalFormatSymbols::kPercentSymbol, (UChar)0x25);
2369
2370 fmt.applyPattern(str("#\\u2030"), status);
2371 failure(status, "applyPattern permill");
2372 sym.setSymbol(DecimalFormatSymbols::kPerMillSymbol, (UChar)0x5e);
2373 fmt.setDecimalFormatSymbols(sym);
2374 s.remove();
2375 if (fmt.format(0.25, s, pos) != UNICODE_STRING("250^", 4)) {
2376 errln(UnicodeString("FAIL: 0.25 x (permill=^) -> ") + s +
2377 ", exp 250^");
2378 }
2379 s.remove();
2380 if (fmt.getPositiveSuffix(s) != UnicodeString((UChar)0x5e)) {
2381 errln(UnicodeString("FAIL: (permill=^).getPositiveSuffix -> ") +
2382 s + ", exp ^");
2383 }
2384 sym.setSymbol(DecimalFormatSymbols::kPerMillSymbol, (UChar)0x2030);
2385
2386 fmt.applyPattern(str("\\u00A4#.00"), status);
2387 failure(status, "applyPattern currency");
2388 sym.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "usd");
2389 fmt.setDecimalFormatSymbols(sym);
2390 s.remove();
2391 if (fmt.format(12.5, s, pos) != UnicodeString(u"usd\u00A012.50")) {
2392 errln(UnicodeString("FAIL: 12.5 x (currency=usd) -> ") + s +
2393 u", exp usd\u00A012.50");
2394 }
2395 s.remove();
2396 if (fmt.getPositivePrefix(s) != UnicodeString("usd")) {
2397 errln(UnicodeString("FAIL: (currency=usd).getPositivePrefix -> ") +
2398 s + ", exp usd");
2399 }
2400 sym.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "$");
2401
2402 fmt.applyPattern(str("\\u00A4\\u00A4#.00"), status);
2403 failure(status, "applyPattern intl currency");
2404 sym.setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol, "DOL");
2405 fmt.setDecimalFormatSymbols(sym);
2406 s.remove();
2407 if (fmt.format(12.5, s, pos) != UnicodeString(u"DOL\u00A012.50")) {
2408 errln(UnicodeString("FAIL: 12.5 x (intlcurrency=DOL) -> ") + s +
2409 u", exp DOL\u00A012.50");
2410 }
2411 s.remove();
2412 if (fmt.getPositivePrefix(s) != UnicodeString("DOL")) {
2413 errln(UnicodeString("FAIL: (intlcurrency=DOL).getPositivePrefix -> ") +
2414 s + ", exp DOL");
2415 }
2416 sym.setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol, "USD");
2417
2418 // Since the pattern logic has changed, make sure that patterns round
2419 // trip properly. Test stream in/out integrity too.
2420 int32_t n;
2421 const Locale* avail = NumberFormat::getAvailableLocales(n);
2422 static const char* type[] = {
2423 "",
2424 "$ ",
2425 "% ",
2426 };
2427 for (int i=0; i<n; ++i) {
2428 for (int j=0; j<3; ++j) {
2429 status = U_ZERO_ERROR;
2430 NumberFormat *nf;
2431 switch (j) {
2432 case 0:
2433 nf = NumberFormat::createInstance(avail[i], status);
2434 failure(status, "createInstance", avail[i]);
2435 break;
2436 case 1:
2437 nf = NumberFormat::createCurrencyInstance(avail[i], status);
2438 failure(status, "createCurrencyInstance", avail[i]);
2439 break;
2440 default:
2441 nf = NumberFormat::createPercentInstance(avail[i], status);
2442 failure(status, "createPercentInstance", avail[i]);
2443 break;
2444 }
2445 if (U_FAILURE(status)) {
2446 continue;
2447 }
2448 DecimalFormat *df = (DecimalFormat*) nf;
2449
2450 // Test toPattern/applyPattern round trip
2451 UnicodeString pat;
2452 df->toPattern(pat);
2453 DecimalFormatSymbols symb(avail[i], status);
2454 failure(status, "Construct DecimalFormatSymbols", avail[i]);
2455 DecimalFormat f2(pat, symb, status);
2456 if (failure(status,
2457 UnicodeString("Construct DecimalFormat(") + pat + ")")) {
2458 continue;
2459 }
2460 if (*df != f2) {
2461 UnicodeString l, p;
2462 errln(UnicodeString("FAIL: ") + type[j] + avail[i].getDisplayName(l) +
2463 " -> \"" + pat +
2464 "\" -> \"" + f2.toPattern(p) + "\"");
2465 } else {
2466 UnicodeString l, p;
2467 logln(UnicodeString("PASS: ") + type[j] + avail[i].getDisplayName(l) +
2468 " -> \"" + pat +
2469 "\"");
2470 }
2471
2472 // Test toLocalizedPattern/applyLocalizedPattern round trip
2473 // TODO(refactor): don't worry about localized patterns for now.
2474 // df->toLocalizedPattern(pat);
2475 // f2.applyLocalizedPattern(pat, status);
2476 failure(status,
2477 UnicodeString("applyLocalizedPattern(") + pat + ")", avail[i]);
2478 if (U_FAILURE(status)) {
2479 continue;
2480 }
2481
2482 // TODO(refactor): don't worry about localized patterns for now.
2483 // Make sure we set the currency attributes appropriately
2484 // if (j == 1) { // Currency format
2485 // f2.setCurrency(f2.getCurrency(), status);
2486 // }
2487 failure(status,
2488 UnicodeString("setCurrency() for (") + pat + ")", avail[i]);
2489 if (U_FAILURE(status)) {
2490 continue;
2491 }
2492
2493 if (*df != f2) {
2494 UnicodeString l, p;
2495 errln(UnicodeString("FAIL: ") + type[j] + avail[i].getDisplayName(l) +
2496 " -> localized \"" + pat +
2497 "\" -> \"" + f2.toPattern(p) + "\"");
2498 }
2499
2500 delete nf;
2501
2502 // Test writeObject/readObject round trip
2503 // NOT ON ICU -- Java only
2504 }
2505 }
2506 }
2507
2508 /**
2509 * May 17 1999 sync up - liu
2510 * DecimalFormat.parse() fails for mulipliers 2^n.
2511 */
2512 void NumberFormatRegressionTest::Test4216742(void) {
2513 UErrorCode status = U_ZERO_ERROR;
2514 DecimalFormat *fmt = (DecimalFormat*) NumberFormat::createInstance(Locale::getUS(), status);
2515 if (failure(status, "createInstance", Locale::getUS(), TRUE)){
2516 delete fmt;
2517 return;
2518 };
2519 int32_t DATA[] = { INT32_MIN, INT32_MAX, -100000000, 100000000 };
2520 int DATA_length = UPRV_LENGTHOF(DATA);
2521 for (int i=0; i<DATA_length; ++i) {
2522 UnicodeString str((UnicodeString)"" + DATA[i]);
2523 for (int m = 1; m <= 100; m++) {
2524 fmt->setMultiplier(m);
2525 Formattable num;
2526 fmt->parse(str, num, status);
2527 failure(status, "parse", Locale::getUS());
2528 if (num.getType() != Formattable::kLong &&
2529 num.getType() != Formattable::kDouble) {
2530 errln(UnicodeString("FAIL: Wanted number, got ") +
2531 toString(num));
2532 } else {
2533 double d = num.getType() == Formattable::kDouble ?
2534 num.getDouble() : (double) num.getLong();
2535 if ((d > 0) != (DATA[i] > 0)) {
2536 errln(UnicodeString("\"") + str + "\" parse(x " +
2537 fmt->getMultiplier() +
2538 ") => " + toString(num));
2539 }
2540 }
2541 }
2542 }
2543 delete fmt;
2544 }
2545
2546 /**
2547 * May 17 1999 sync up - liu
2548 * DecimalFormat formats 1.001 to "1.00" instead of "1" with 2 fraction
2549 * digits.
2550 */
2551 void NumberFormatRegressionTest::Test4217661(void) {
2552 const double D[] = { 0.001, 1.001, 0.006, 1.006 };
2553 const char* S[] = { "0", "1", "0.01", "1.01" };
2554 int D_length = UPRV_LENGTHOF(D);
2555 UErrorCode status = U_ZERO_ERROR;
2556 NumberFormat *fmt = NumberFormat::createInstance(Locale::getUS(), status);
2557 if (failure(status, "createInstance", Locale::getUS(), TRUE)){
2558 delete fmt;
2559 return;
2560 };
2561 fmt->setMaximumFractionDigits(2);
2562 for (int i=0; i<D_length; i++) {
2563 UnicodeString s;
2564 fmt->format(D[i], s);
2565 if (s != UnicodeString(S[i])) {
2566 errln(UnicodeString("FAIL: Got ") + s + ", exp " + S[i]);
2567 }
2568 }
2569 delete fmt;
2570 }
2571
2572 /**
2573 * alphaWorks upgrade
2574 */
2575 void NumberFormatRegressionTest::Test4161100(void) {
2576 UErrorCode status = U_ZERO_ERROR;
2577 NumberFormat *nf = NumberFormat::createInstance(Locale::getUS(), status);
2578 if (failure(status, "createInstance", Locale::getUS(), TRUE)){
2579 delete nf;
2580 return;
2581 };
2582 nf->setMinimumFractionDigits(1);
2583 nf->setMaximumFractionDigits(1);
2584 double a = -0.09;
2585 UnicodeString s;
2586 nf->format(a, s);
2587 UnicodeString pat;
2588 logln(UnicodeString() + a + " x " +
2589 ((DecimalFormat*) nf)->toPattern(pat) + " = " + s);
2590 if (s != UnicodeString("-0.1")) {
2591 errln("FAIL");
2592 }
2593 delete nf;
2594 }
2595
2596 /**
2597 * June 16 1999 sync up - liu
2598 * Formatting .5 rounds to "1" instead of "0". (Regression in 1.2.2 RC1)
2599 */
2600 void NumberFormatRegressionTest::Test4243011(void) {
2601 UErrorCode status = U_ZERO_ERROR;
2602 DecimalFormatSymbols sym(Locale::getUS(), status);
2603 failure(status, "DecimalFormatSymbols ct", Locale::getUS());
2604 DecimalFormat fmt(UnicodeString("0."), sym, status);
2605
2606 if (!failure(status, "DecimalFormat ct", Locale::getUS())) {
2607 const double NUM[] = { -2.5, -1.5, -0.5, 0.5, 1.5, 2.5, 3.5, 4.5 };
2608 const char* STR[] = { "-2.", "-2.", "-0.", "0.", "2.", "2.", "4.", "4." };
2609 int32_t N = UPRV_LENGTHOF(NUM);
2610
2611 for (int32_t i=0; i<N; ++i) {
2612 UnicodeString str;
2613 UnicodeString exp(STR[i]);
2614 FieldPosition pos;
2615 fmt.format(NUM[i], str, pos);
2616 if (str == exp) {
2617 logln(UnicodeString("Ok ") + NUM[i] + " x 0. = " + str);
2618 } else {
2619 errln(UnicodeString("FAIL ") + NUM[i] + " x 0. = " + str +
2620 ", want " + exp);
2621 }
2622 }
2623 }
2624 }
2625
2626 /**
2627 * June 16 1999 sync up - liu
2628 * format(0.0) gives "0.1" if preceded by parse("99.99").
2629 * (Regression in 1.2.2 RC1)
2630 */
2631 void NumberFormatRegressionTest::Test4243108(void) {
2632 UErrorCode status = U_ZERO_ERROR;
2633 DecimalFormatSymbols sym(Locale::getUS(), status);
2634 failure(status, "DecimalFormatSymbols ct", Locale::getUS());
2635 DecimalFormat fmt(UnicodeString("#.#"), sym, status);
2636 if (failure(status, "DecimalFormat ct", Locale::getUS())) {
2637 return;
2638 }
2639
2640 UnicodeString str;
2641 FieldPosition pos;
2642
2643 fmt.format(0.0, str, pos);
2644 UnicodeString exp("0");
2645 if (str == exp) {
2646 logln(UnicodeString("Ok 0.0 x #.# = ") + str);
2647 } else {
2648 errln(UnicodeString("FAIL 0.0 x #.# = ") + str +
2649 ", want " + exp);
2650 }
2651
2652 str = "99.99";
2653 Formattable val;
2654 fmt.parse(str, val, status);
2655 failure(status, "DecimalFormat.parse(99.99)", Locale::getUS());
2656 if (val.getType() == Formattable::kDouble &&
2657 val.getDouble() == 99.99) {
2658 logln(UnicodeString("Ok 99.99 / #.# = ") + toString(val));
2659 } else {
2660 errln(UnicodeString("FAIL 99.99 / #.# = ") + toString(val) +
2661 ", want " + 99.99);
2662 }
2663
2664 str.remove();
2665 fmt.format(0.0, str, pos);
2666 if (str == exp) {
2667 logln(UnicodeString("Ok 0.0 x #.# = ") + str);
2668 } else {
2669 errln(UnicodeString("FAIL 0.0 x #.# = ") + str +
2670 ", want " + exp);
2671 }
2672 }
2673
2674
2675 /**
2676 * DateFormat should call setIntegerParseOnly(TRUE) on adopted
2677 * NumberFormat objects.
2678 */
2679 void NumberFormatRegressionTest::TestJ691(void) {
2680 UErrorCode status = U_ZERO_ERROR;
2681 Locale loc("fr", "CH");
2682
2683 // set up the input date string & expected output
2684 UnicodeString udt("11.10.2000", "");
2685 UnicodeString exp("11.10.00", "");
2686
2687 // create a Calendar for this locale
2688 Calendar *cal = Calendar::createInstance(loc, status);
2689 if (U_FAILURE(status)) {
2690 dataerrln("FAIL: Calendar::createInstance() returned " + (UnicodeString)u_errorName(status));
2691 return;
2692 }
2693
2694 // create a NumberFormat for this locale
2695 NumberFormat *nf = NumberFormat::createInstance(loc, status);
2696 if (U_FAILURE(status)) {
2697 dataerrln("FAIL: NumberFormat::createInstance() returned " + (UnicodeString)u_errorName(status));
2698 return;
2699 }
2700
2701 // *** Here's the key: We don't want to have to do THIS:
2702 // nf->setParseIntegerOnly(TRUE);
2703 // or this (with changes to fr_CH per cldrbug:9370):
2704 // nf->setGroupingUsed(FALSE);
2705 // so they are done in DateFormat::adoptNumberFormat
2706
2707 // create the DateFormat
2708 DateFormat *df = DateFormat::createDateInstance(DateFormat::kShort, loc);
2709 if (U_FAILURE(status)) {
2710 errln("FAIL: DateFormat::createInstance() returned " + (UnicodeString)u_errorName(status));
2711 return;
2712 }
2713
2714 df->adoptCalendar(cal);
2715 df->adoptNumberFormat(nf);
2716
2717 // set parsing to lenient & parse
2718 df->setLenient(TRUE);
2719 UDate ulocdat = df->parse(udt, status);
2720
2721 // format back to a string
2722 UnicodeString outString;
2723 df->format(ulocdat, outString);
2724
2725 if (outString != exp) {
2726 errln("FAIL: " + udt + " => " + outString);
2727 }
2728
2729 delete df;
2730 }
2731
2732 //---------------------------------------------------------------------------
2733 //
2734 // Error Checking / Reporting macros
2735 //
2736 //---------------------------------------------------------------------------
2737 #define TEST_CHECK_STATUS(status) { \
2738 if (U_FAILURE(status)) { \
2739 if (status == U_MISSING_RESOURCE_ERROR) { \
2740 dataerrln("File %s, Line %d: status=%s", __FILE__, __LINE__, u_errorName(status)); \
2741 } else { \
2742 errln("File %s, Line %d: status=%s", __FILE__, __LINE__, u_errorName(status)); \
2743 } return; \
2744 }}
2745
2746 #define TEST_ASSERT(expr) \
2747 if ((expr)==FALSE) {\
2748 errln("File %s, line %d: Assertion Failed: " #expr "\n", __FILE__, __LINE__);\
2749 }
2750 #define TEST_ASSERT_EQUALS(x,y) \
2751 { \
2752 char _msg[1000]; \
2753 int32_t len = sprintf (_msg,"File %s, line %d: " #x "==" #y, __FILE__, __LINE__); \
2754 (void)len; \
2755 U_ASSERT(len < (int32_t) sizeof(_msg)); \
2756 assertEquals((const char*) _msg, x,y); \
2757 }
2758
2759
2760 // Ticket 8199: Parse failure for numbers in the range of 1E10 - 1E18
2761
2762 void NumberFormatRegressionTest::Test8199(void) {
2763 UErrorCode status = U_ZERO_ERROR;
2764 NumberFormat *nf = NumberFormat::createInstance(Locale::getEnglish(), status);
2765 if (nf == NULL) {
2766 dataerrln("Fail: NumberFormat::createInstance(Locale::getEnglish(), status)");
2767 return;
2768 }
2769 TEST_CHECK_STATUS(status);
2770
2771 // Note: Retrieving parsed values from a Formattable as a reduced-precision type
2772 // should always truncate, no other rounding scheme.
2773
2774 UnicodeString numStr = "1000000000.6"; // 9 zeroes
2775 Formattable val;
2776 nf->parse(numStr, val, status);
2777 TEST_CHECK_STATUS(status);
2778 TEST_ASSERT_EQUALS(Formattable::kDouble, val.getType());
2779 TEST_ASSERT_EQUALS(1000000000LL, val.getInt64(status));
2780 TEST_CHECK_STATUS(status);
2781 TEST_ASSERT_EQUALS(1000000000.6, val.getDouble(status));
2782 TEST_CHECK_STATUS(status);
2783
2784 numStr = "100000000000000001.1"; // approx 1E17, parses as a double rather
2785 // than int64 because of the fraction
2786 // even though int64 is more precise.
2787 nf->parse(numStr, val, status);
2788 TEST_CHECK_STATUS(status);
2789 TEST_ASSERT_EQUALS(Formattable::kDouble, val.getType());
2790 TEST_ASSERT_EQUALS(100000000000000001LL, val.getInt64(status));
2791 TEST_CHECK_STATUS(status);
2792 TEST_ASSERT_EQUALS(100000000000000000.0, val.getDouble(status));
2793 TEST_CHECK_STATUS(status);
2794
2795 numStr = "1E17"; // Parses with the internal decimal number having non-zero exponent
2796 nf->parse(numStr, val, status);
2797 TEST_CHECK_STATUS(status);
2798 TEST_ASSERT_EQUALS(Formattable::kInt64, val.getType());
2799 TEST_ASSERT_EQUALS(100000000000000000LL, val.getInt64());
2800 TEST_ASSERT_EQUALS(1.0E17, val.getDouble(status));
2801 TEST_CHECK_STATUS(status);
2802
2803 numStr = "9223372036854775807"; // largest int64_t
2804 nf->parse(numStr, val, status);
2805 TEST_CHECK_STATUS(status);
2806 TEST_ASSERT_EQUALS(Formattable::kInt64, val.getType());
2807 TEST_ASSERT_EQUALS(9223372036854775807LL, val.getInt64());
2808 // In the following check, note that a substantial range of integers will
2809 // convert to the same double value. There are also platform variations
2810 // in the rounding at compile time of double constants.
2811 TEST_ASSERT(9223372036854775808.0 >= val.getDouble(status));
2812 TEST_ASSERT(9223372036854774700.0 <= val.getDouble(status));
2813 TEST_CHECK_STATUS(status);
2814
2815 numStr = "-9223372036854775808"; // smallest int64_t
2816 nf->parse(numStr, val, status);
2817 TEST_CHECK_STATUS(status);
2818 TEST_ASSERT_EQUALS(Formattable::kInt64, val.getType());
2819 // TEST_ASSERT_EQUALS(-9223372036854775808LL, val.getInt64()); // Compiler chokes on constant.
2820 TEST_ASSERT_EQUALS((int64_t)0x8000000000000000LL, val.getInt64());
2821 TEST_ASSERT_EQUALS(-9223372036854775808.0, val.getDouble(status));
2822 TEST_CHECK_STATUS(status);
2823
2824 numStr = "9223372036854775808"; // largest int64_t + 1
2825 nf->parse(numStr, val, status);
2826 TEST_CHECK_STATUS(status);
2827 TEST_ASSERT_EQUALS(Formattable::kDouble, val.getType());
2828 TEST_ASSERT_EQUALS(9223372036854775807LL, val.getInt64(status));
2829 TEST_ASSERT_EQUALS(status, U_INVALID_FORMAT_ERROR);
2830 status = U_ZERO_ERROR;
2831 TEST_ASSERT_EQUALS(9223372036854775810.0, val.getDouble(status));
2832 TEST_CHECK_STATUS(status);
2833
2834 numStr = "-9223372036854775809"; // smallest int64_t - 1
2835 nf->parse(numStr, val, status);
2836 TEST_CHECK_STATUS(status);
2837 TEST_ASSERT_EQUALS(Formattable::kDouble, val.getType());
2838 // TEST_ASSERT_EQUALS(-9223372036854775808LL, val.getInt64(status)); // spurious compiler warnings
2839 TEST_ASSERT_EQUALS((int64_t)0x8000000000000000LL, val.getInt64(status));
2840 TEST_ASSERT_EQUALS(status, U_INVALID_FORMAT_ERROR);
2841 status = U_ZERO_ERROR;
2842 TEST_ASSERT_EQUALS(-9223372036854775810.0, val.getDouble(status));
2843 TEST_CHECK_STATUS(status);
2844
2845 // Test values near the limit of where doubles can represent all integers.
2846 // The implementation strategy of getInt64() changes at this boundary.
2847 // Strings to be parsed include a decimal fraction to force them to be
2848 // parsed as doubles rather than ints. The fraction is discarded
2849 // from the parsed double value because it is beyond what can be represented.
2850
2851 status = U_ZERO_ERROR;
2852 numStr = "9007199254740991.1"; // largest 53 bit int
2853 nf->parse(numStr, val, status);
2854 TEST_CHECK_STATUS(status);
2855 // printf("getInt64() returns %lld\n", val.getInt64(status));
2856 TEST_ASSERT_EQUALS(Formattable::kDouble, val.getType());
2857 TEST_ASSERT_EQUALS(9007199254740991LL, val.getInt64(status));
2858 TEST_ASSERT_EQUALS(9007199254740991.0, val.getDouble(status));
2859 TEST_CHECK_STATUS(status);
2860
2861 status = U_ZERO_ERROR;
2862 numStr = "9007199254740992.1"; // 54 bits for the int part.
2863 nf->parse(numStr, val, status);
2864 TEST_CHECK_STATUS(status);
2865 TEST_ASSERT_EQUALS(Formattable::kDouble, val.getType());
2866 TEST_ASSERT_EQUALS(9007199254740992LL, val.getInt64(status));
2867 TEST_ASSERT_EQUALS(9007199254740992.0, val.getDouble(status));
2868 TEST_CHECK_STATUS(status);
2869
2870 status = U_ZERO_ERROR;
2871 numStr = "9007199254740993.1"; // 54 bits for the int part. Double will round
2872 nf->parse(numStr, val, status); // the ones digit, putting it up to ...994
2873 TEST_CHECK_STATUS(status);
2874 TEST_ASSERT_EQUALS(Formattable::kDouble, val.getType());
2875 TEST_ASSERT_EQUALS((int64_t)9007199254740993LL,val.getInt64(status));
2876 TEST_ASSERT_EQUALS((double)9007199254740994.0,(double)val.getDouble(status));
2877 TEST_CHECK_STATUS(status);
2878
2879 delete nf;
2880 }
2881
2882 void NumberFormatRegressionTest::Test9109(void) {
2883 UErrorCode status = U_ZERO_ERROR;
2884 Formattable val;
2885 ParsePosition pos;
2886 DecimalFormat fmt("+##", status);
2887 if (U_FAILURE(status)) {
2888 dataerrln("Failed to create DecimalFormat with pattern '+##' - %s", u_errorName(status));
2889 return;
2890 }
2891
2892 fmt.setLenient(TRUE);
2893 UnicodeString text("123");
2894 int32_t expected = 123;
2895 int32_t expos = 3;
2896
2897 fmt.parse(text, val, pos);
2898 if (pos.getErrorIndex() >= 0) {
2899 errln(UnicodeString("Parse failure at ") + pos.getErrorIndex());
2900 } else if (val.getLong() != 123) {
2901 errln(UnicodeString("Incorrect parse result: ") + val.getLong() + " expected: " + expected);
2902 } else if (pos.getIndex() != 3) {
2903 errln(UnicodeString("Incorrect parse position: ") + pos.getIndex() + " expected: " + expos);
2904 }
2905 }
2906
2907
2908 void NumberFormatRegressionTest::Test9780(void) {
2909 UErrorCode status = U_ZERO_ERROR;
2910 NumberFormat *nf = NumberFormat::createInstance(Locale::getUS(), status);
2911 if (failure(status, "NumberFormat::createInstance", TRUE)){
2912 delete nf;
2913 return;
2914 };
2915 DecimalFormat *df = dynamic_cast<DecimalFormat *>(nf);
2916 if(df == NULL) {
2917 errln("DecimalFormat needed to continue");
2918 return;
2919 }
2920 df->setParseIntegerOnly(TRUE);
2921
2922 {
2923 Formattable n;
2924 ParsePosition pos(0);
2925 UnicodeString toParse("1,234","");
2926 df->parse(toParse, n, pos);
2927 if (n.getType() != Formattable::kLong
2928 || n.getLong() != 1234) {
2929 errln(UnicodeString("FAIL: parse(\"") + toParse + UnicodeString("\") returns ") + toString(n));
2930 }
2931 }
2932 // should still work in lenient mode, just won't get fastpath
2933 df->setLenient(TRUE);
2934 {
2935 Formattable n;
2936 ParsePosition pos(0);
2937 UnicodeString toParse("1,234","");
2938 df->parse(toParse, n, pos);
2939 if (n.getType() != Formattable::kLong
2940 || n.getLong() != 1234) {
2941 errln(UnicodeString("FAIL: parse(\"") + toParse + UnicodeString("\") returns ") + toString(n));
2942 }
2943 }
2944 delete nf;
2945 }
2946
2947
2948 void NumberFormatRegressionTest::Test9677(void) {
2949 static const UChar pattern[] = { 0x23,0x23,0x23,0x23,0x2E,0x23,0x23,0x23,0x23,0 }; // "####.####"
2950 static const UChar positivePrefix[] = { 0x40,0 }; // "@"
2951 static const UChar negativePrefix[] = { 0x6E,0 }; // "n"
2952 static const UChar text[] = { 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0 }; // 123456789
2953 static const UChar text2[] = { 0x6E, 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0 }; // n123456789
2954
2955 UErrorCode status = U_ZERO_ERROR;
2956 LocalUNumberFormatPointer f(unum_open(UNUM_DEFAULT, NULL, 0, "en_US", NULL, &status));
2957 if (U_FAILURE(status)) {
2958 dataerrln("Failure opening unum_open");
2959 return;
2960 }
2961
2962 if (U_SUCCESS(status)) {
2963 unum_applyPattern(f.getAlias(), FALSE, pattern, -1, NULL, &status);
2964 unum_setTextAttribute(f.getAlias(), UNUM_POSITIVE_PREFIX, positivePrefix, -1, &status);
2965 assertSuccess("setting attributes", status);
2966 }
2967
2968 if(U_SUCCESS(status)) {
2969 int32_t n = unum_parse(f.getAlias(), text, -1, NULL, &status);
2970 logln("unum_parse status %s, result %d\n", u_errorName(status), n);
2971
2972 if(U_FAILURE(status)) {
2973 logln("Got expected parse error %s\n", u_errorName(status));
2974 status = U_ZERO_ERROR;
2975 } else {
2976 errln("FAIL: unum_parse status %s, result %d - expected failure\n", u_errorName(status), n);
2977 }
2978 }
2979
2980 if (U_SUCCESS(status)) {
2981 unum_setTextAttribute(f.getAlias(), UNUM_POSITIVE_PREFIX, NULL, 0, &status);
2982 assertSuccess("setting attributes", status);
2983 logln("removed positive prefix");
2984 }
2985
2986 if(U_SUCCESS(status)) {
2987 int32_t n = unum_parse(f.getAlias(), text, -1, NULL, &status);
2988 logln("unum_parse status %s, result %d\n", u_errorName(status), n);
2989
2990 if(U_FAILURE(status)) {
2991 errln("FAIL: with pos prefix removed, parse error %s\n", u_errorName(status));
2992 status = U_ZERO_ERROR;
2993 } else {
2994 if(n!=123456789) {
2995 errln("FAIL: with pos prefix removed , unum_parse status %s, result %d expected 123456789\n", u_errorName(status), n);
2996 } else {
2997 logln("PASS: with pos prefix removed , unum_parse status %s, result %d expected 123456789\n", u_errorName(status),n);
2998 }
2999 }
3000 }
3001
3002 if(U_SUCCESS(status)) {
3003 int32_t n = unum_parse(f.getAlias(), text2, -1, NULL, &status);
3004 logln("unum_parse status %s, result %d\n", u_errorName(status), n);
3005
3006 if(U_FAILURE(status)) {
3007 logln("text2: Got expected parse error %s\n", u_errorName(status));
3008 status = U_ZERO_ERROR;
3009 } else {
3010 errln("FAIL: text2: unum_parse status %s, result %d - expected failure\n", u_errorName(status), n);
3011 }
3012 }
3013
3014 if (U_SUCCESS(status)) {
3015 unum_setTextAttribute(f.getAlias(), UNUM_NEGATIVE_PREFIX, negativePrefix, -1, &status);
3016 assertSuccess("setting attributes", status);
3017 logln("Set a different neg prefix prefix");
3018 }
3019
3020 if(U_SUCCESS(status)) {
3021 int32_t n = unum_parse(f.getAlias(), text2, -1, NULL, &status);
3022 logln("unum_parse status %s, result %d\n", u_errorName(status), n);
3023
3024 if(U_FAILURE(status)) {
3025 errln("FAIL: with different neg prefix , parse error %s\n", u_errorName(status));
3026 status = U_ZERO_ERROR;
3027 } else {
3028 ;
3029 if(n!=-123456789) {
3030 errln("FAIL: with different neg prefix , unum_parse status %s, result %d expected -123456789\n", u_errorName(status), n);
3031 } else {
3032 logln("PASS: with different neg prefix , unum_parse status %s, result %d expected -123456789\n", u_errorName(status), n);
3033 }
3034 }
3035 }
3036 }
3037
3038 void NumberFormatRegressionTest::Test10361(void) {
3039 // DecimalFormat/NumberFormat were artificially limiting the number of digits,
3040 // preventing formatting of big decimals.
3041 UErrorCode status = U_ZERO_ERROR;
3042 DecimalFormatSymbols symbols(Locale::getEnglish(), status);
3043 LocalPointer<DecimalFormat> df(new DecimalFormat("###.##", symbols, status), status);
3044 TEST_CHECK_STATUS(status);
3045
3046 // Create a decimal number with a million digits.
3047 const int32_t NUMSIZE=1000000;
3048 char *num = new char[NUMSIZE];
3049 for (int32_t i=0; i<NUMSIZE; i++) {
3050 num[i] = '0' + (i+1) % 10;
3051 }
3052 num[NUMSIZE-3] = '.';
3053 num[NUMSIZE-1] = 0;
3054
3055 UnicodeString s;
3056 Formattable fmtable;
3057 fmtable.setDecimalNumber(num, status);
3058 TEST_CHECK_STATUS(status);
3059
3060 FieldPosition pos(UNUM_DECIMAL_SEPARATOR_FIELD);
3061 df->format(fmtable, s, pos, status);
3062 TEST_CHECK_STATUS(status);
3063 TEST_ASSERT(999999 == s.length());
3064 TEST_ASSERT(999997 == pos.getBeginIndex());
3065 TEST_ASSERT(999998 == pos.getEndIndex());
3066
3067 UnicodeString expected(num, -1, US_INV);
3068 TEST_ASSERT(expected == s);
3069 delete [] num;
3070 }
3071
3072 #endif /* #if !UCONFIG_NO_FORMATTING */
3073