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