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