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