]>
Commit | Line | Data |
---|---|---|
f3c0d7a5 A |
1 | // © 2016 and later: Unicode, Inc. and others. |
2 | // License & terms of use: http://www.unicode.org/copyright.html | |
b75a7d8f | 3 | /******************************************************************** |
57a6839d | 4 | * COPYRIGHT: |
2ca993e8 | 5 | * Copyright (c) 1997-2015, International Business Machines Corporation and |
b75a7d8f A |
6 | * others. All Rights Reserved. |
7 | ********************************************************************/ | |
8 | ||
9 | #include "unicode/utypes.h" | |
10 | ||
11 | #if !UCONFIG_NO_FORMATTING | |
12 | ||
13 | #include "dcfmapts.h" | |
14 | ||
57a6839d | 15 | #include "unicode/currpinf.h" |
b75a7d8f | 16 | #include "unicode/dcfmtsym.h" |
57a6839d A |
17 | #include "unicode/decimfmt.h" |
18 | #include "unicode/fmtable.h" | |
19 | #include "unicode/localpointer.h" | |
b75a7d8f | 20 | #include "unicode/parseerr.h" |
57a6839d A |
21 | #include "unicode/stringpiece.h" |
22 | ||
23 | #include "putilimp.h" | |
24 | #include "plurrule_impl.h" | |
0f5d89e8 A |
25 | #include "number_decimalquantity.h" |
26 | ||
57a6839d A |
27 | #include <stdio.h> |
28 | ||
b75a7d8f A |
29 | // This is an API test, not a unit test. It doesn't test very many cases, and doesn't |
30 | // try to test the full functionality. It just calls each function in the class and | |
31 | // verifies that it works on a basic level. | |
32 | ||
33 | void IntlTestDecimalFormatAPI::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ ) | |
34 | { | |
35 | if (exec) logln((UnicodeString)"TestSuite DecimalFormatAPI"); | |
36 | switch (index) { | |
57a6839d | 37 | case 0: name = "DecimalFormat API test"; |
b75a7d8f A |
38 | if (exec) { |
39 | logln((UnicodeString)"DecimalFormat API test---"); logln((UnicodeString)""); | |
40 | UErrorCode status = U_ZERO_ERROR; | |
73c04bcf | 41 | Locale saveLocale; |
b75a7d8f A |
42 | Locale::setDefault(Locale::getEnglish(), status); |
43 | if(U_FAILURE(status)) { | |
44 | errln((UnicodeString)"ERROR: Could not set default locale, test may not give correct results"); | |
45 | } | |
46 | testAPI(/*par*/); | |
73c04bcf | 47 | Locale::setDefault(saveLocale, status); |
b75a7d8f A |
48 | } |
49 | break; | |
50 | case 1: name = "Rounding test"; | |
51 | if(exec) { | |
52 | logln((UnicodeString)"DecimalFormat Rounding test---"); | |
53 | testRounding(/*par*/); | |
54 | } | |
55 | break; | |
729e4ab9 A |
56 | case 2: name = "Test6354"; |
57 | if(exec) { | |
58 | logln((UnicodeString)"DecimalFormat Rounding Increment test---"); | |
59 | testRoundingInc(/*par*/); | |
60 | } | |
61 | break; | |
62 | case 3: name = "TestCurrencyPluralInfo"; | |
63 | if(exec) { | |
64 | logln((UnicodeString)"CurrencyPluralInfo API test---"); | |
65 | TestCurrencyPluralInfo(); | |
66 | } | |
67 | break; | |
51004dcb A |
68 | case 4: name = "TestScale"; |
69 | if(exec) { | |
70 | logln((UnicodeString)"Scale test---"); | |
71 | TestScale(); | |
72 | } | |
73 | break; | |
57a6839d A |
74 | case 5: name = "TestFixedDecimal"; |
75 | if(exec) { | |
76 | logln((UnicodeString)"TestFixedDecimal ---"); | |
77 | TestFixedDecimal(); | |
78 | } | |
79 | break; | |
80 | case 6: name = "TestBadFastpath"; | |
81 | if(exec) { | |
82 | logln((UnicodeString)"TestBadFastpath ---"); | |
83 | TestBadFastpath(); | |
84 | } | |
85 | break; | |
b331163b A |
86 | case 7: name = "TestRequiredDecimalPoint"; |
87 | if(exec) { | |
88 | logln((UnicodeString)"TestRequiredDecimalPoint ---"); | |
89 | TestRequiredDecimalPoint(); | |
90 | } | |
91 | break; | |
0f5d89e8 A |
92 | case 8: name = "testErrorCode"; |
93 | if(exec) { | |
94 | logln((UnicodeString)"testErrorCode ---"); | |
95 | testErrorCode(); | |
96 | } | |
97 | break; | |
3d1f044b A |
98 | case 9: name = "testInvalidObject"; |
99 | if(exec) { | |
100 | logln((UnicodeString) "testInvalidObject ---"); | |
101 | testInvalidObject(); | |
102 | } | |
103 | break; | |
57a6839d | 104 | default: name = ""; break; |
b75a7d8f A |
105 | } |
106 | } | |
107 | ||
108 | /** | |
109 | * This test checks various generic API methods in DecimalFormat to achieve 100% | |
110 | * API coverage. | |
111 | */ | |
112 | void IntlTestDecimalFormatAPI::testAPI(/*char *par*/) | |
113 | { | |
114 | UErrorCode status = U_ZERO_ERROR; | |
115 | ||
116 | // ======= Test constructors | |
117 | ||
118 | logln((UnicodeString)"Testing DecimalFormat constructors"); | |
119 | ||
120 | DecimalFormat def(status); | |
121 | if(U_FAILURE(status)) { | |
729e4ab9 | 122 | errcheckln(status, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status)); |
b75a7d8f A |
123 | return; |
124 | } | |
125 | ||
08b89b0a A |
126 | // bug 10864 |
127 | status = U_ZERO_ERROR; | |
128 | DecimalFormat noGrouping("###0.##", status); | |
0f5d89e8 | 129 | assertEquals("Grouping size should be 0 for no grouping.", 0, noGrouping.getGroupingSize()); |
2ca993e8 | 130 | noGrouping.setGroupingUsed(TRUE); |
0f5d89e8 | 131 | assertEquals("Grouping size should still be 0.", 0, noGrouping.getGroupingSize()); |
08b89b0a A |
132 | // end bug 10864 |
133 | ||
0f5d89e8 A |
134 | // bug 13442 comment 14 |
135 | status = U_ZERO_ERROR; | |
136 | { | |
137 | DecimalFormat df("0", {"en", status}, status); | |
138 | UnicodeString result; | |
139 | assertEquals("pat 0: ", 0, df.getGroupingSize()); | |
140 | assertEquals("pat 0: ", (UBool) FALSE, (UBool) df.isGroupingUsed()); | |
141 | df.setGroupingUsed(false); | |
142 | assertEquals("pat 0 then disabled: ", 0, df.getGroupingSize()); | |
143 | assertEquals("pat 0 then disabled: ", u"1111", df.format(1111, result.remove())); | |
144 | df.setGroupingUsed(true); | |
145 | assertEquals("pat 0 then enabled: ", 0, df.getGroupingSize()); | |
146 | assertEquals("pat 0 then enabled: ", u"1111", df.format(1111, result.remove())); | |
147 | } | |
148 | { | |
149 | DecimalFormat df("#,##0", {"en", status}, status); | |
150 | UnicodeString result; | |
151 | assertEquals("pat #,##0: ", 3, df.getGroupingSize()); | |
152 | assertEquals("pat #,##0: ", (UBool) TRUE, (UBool) df.isGroupingUsed()); | |
153 | df.setGroupingUsed(false); | |
154 | assertEquals("pat #,##0 then disabled: ", 3, df.getGroupingSize()); | |
155 | assertEquals("pat #,##0 then disabled: ", u"1111", df.format(1111, result.remove())); | |
156 | df.setGroupingUsed(true); | |
157 | assertEquals("pat #,##0 then enabled: ", 3, df.getGroupingSize()); | |
158 | assertEquals("pat #,##0 then enabled: ", u"1,111", df.format(1111, result.remove())); | |
159 | } | |
160 | // end bug 13442 comment 14 | |
161 | ||
b75a7d8f A |
162 | status = U_ZERO_ERROR; |
163 | const UnicodeString pattern("#,##0.# FF"); | |
164 | DecimalFormat pat(pattern, status); | |
165 | if(U_FAILURE(status)) { | |
166 | errln((UnicodeString)"ERROR: Could not create DecimalFormat (pattern)"); | |
167 | return; | |
168 | } | |
169 | ||
170 | status = U_ZERO_ERROR; | |
171 | DecimalFormatSymbols *symbols = new DecimalFormatSymbols(Locale::getFrench(), status); | |
172 | if(U_FAILURE(status)) { | |
173 | errln((UnicodeString)"ERROR: Could not create DecimalFormatSymbols (French)"); | |
174 | return; | |
175 | } | |
176 | ||
177 | status = U_ZERO_ERROR; | |
178 | DecimalFormat cust1(pattern, symbols, status); | |
179 | if(U_FAILURE(status)) { | |
180 | errln((UnicodeString)"ERROR: Could not create DecimalFormat (pattern, symbols*)"); | |
181 | } | |
182 | ||
183 | status = U_ZERO_ERROR; | |
184 | DecimalFormat cust2(pattern, *symbols, status); | |
185 | if(U_FAILURE(status)) { | |
186 | errln((UnicodeString)"ERROR: Could not create DecimalFormat (pattern, symbols)"); | |
187 | } | |
188 | ||
189 | DecimalFormat copy(pat); | |
190 | ||
191 | // ======= Test clone(), assignment, and equality | |
192 | ||
193 | logln((UnicodeString)"Testing clone(), assignment and equality operators"); | |
194 | ||
195 | if( ! (copy == pat) || copy != pat) { | |
196 | errln((UnicodeString)"ERROR: Copy constructor or == failed"); | |
197 | } | |
198 | ||
199 | copy = cust1; | |
200 | if(copy != cust1) { | |
201 | errln((UnicodeString)"ERROR: Assignment (or !=) failed"); | |
202 | } | |
203 | ||
204 | Format *clone = def.clone(); | |
205 | if( ! (*clone == def) ) { | |
206 | errln((UnicodeString)"ERROR: Clone() failed"); | |
207 | } | |
208 | delete clone; | |
209 | ||
210 | // ======= Test various format() methods | |
211 | ||
212 | logln((UnicodeString)"Testing various format() methods"); | |
213 | ||
214 | double d = -10456.0037; | |
215 | int32_t l = 100000000; | |
216 | Formattable fD(d); | |
217 | Formattable fL(l); | |
218 | ||
219 | UnicodeString res1, res2, res3, res4; | |
f3c0d7a5 | 220 | FieldPosition pos1(FieldPosition::DONT_CARE), pos2(FieldPosition::DONT_CARE), pos3(FieldPosition::DONT_CARE), pos4(FieldPosition::DONT_CARE); |
57a6839d | 221 | |
b75a7d8f A |
222 | res1 = def.format(d, res1, pos1); |
223 | logln( (UnicodeString) "" + (int32_t) d + " formatted to " + res1); | |
224 | ||
225 | res2 = pat.format(l, res2, pos2); | |
226 | logln((UnicodeString) "" + (int32_t) l + " formatted to " + res2); | |
227 | ||
228 | status = U_ZERO_ERROR; | |
229 | res3 = cust1.format(fD, res3, pos3, status); | |
230 | if(U_FAILURE(status)) { | |
231 | errln((UnicodeString)"ERROR: format(Formattable [double]) failed"); | |
232 | } | |
233 | logln((UnicodeString) "" + (int32_t) fD.getDouble() + " formatted to " + res3); | |
234 | ||
235 | status = U_ZERO_ERROR; | |
236 | res4 = cust2.format(fL, res4, pos4, status); | |
237 | if(U_FAILURE(status)) { | |
238 | errln((UnicodeString)"ERROR: format(Formattable [long]) failed"); | |
239 | } | |
240 | logln((UnicodeString) "" + fL.getLong() + " formatted to " + res4); | |
241 | ||
242 | // ======= Test parse() | |
243 | ||
244 | logln((UnicodeString)"Testing parse()"); | |
245 | ||
246 | UnicodeString text("-10,456.0037"); | |
247 | Formattable result1, result2; | |
248 | ParsePosition pos(0); | |
249 | UnicodeString patt("#,##0.#"); | |
250 | status = U_ZERO_ERROR; | |
251 | pat.applyPattern(patt, status); | |
252 | if(U_FAILURE(status)) { | |
253 | errln((UnicodeString)"ERROR: applyPattern() failed"); | |
254 | } | |
255 | pat.parse(text, result1, pos); | |
256 | if(result1.getType() != Formattable::kDouble && result1.getDouble() != d) { | |
257 | errln((UnicodeString)"ERROR: Roundtrip failed (via parse()) for " + text); | |
258 | } | |
259 | logln(text + " parsed into " + (int32_t) result1.getDouble()); | |
260 | ||
261 | status = U_ZERO_ERROR; | |
262 | pat.parse(text, result2, status); | |
263 | if(U_FAILURE(status)) { | |
264 | errln((UnicodeString)"ERROR: parse() failed"); | |
265 | } | |
266 | if(result2.getType() != Formattable::kDouble && result2.getDouble() != d) { | |
267 | errln((UnicodeString)"ERROR: Roundtrip failed (via parse()) for " + text); | |
268 | } | |
269 | logln(text + " parsed into " + (int32_t) result2.getDouble()); | |
270 | ||
271 | // ======= Test getters and setters | |
272 | ||
273 | logln((UnicodeString)"Testing getters and setters"); | |
274 | ||
275 | const DecimalFormatSymbols *syms = pat.getDecimalFormatSymbols(); | |
276 | DecimalFormatSymbols *newSyms = new DecimalFormatSymbols(*syms); | |
277 | def.setDecimalFormatSymbols(*newSyms); | |
278 | def.adoptDecimalFormatSymbols(newSyms); // don't use newSyms after this | |
279 | if( *(pat.getDecimalFormatSymbols()) != *(def.getDecimalFormatSymbols())) { | |
280 | errln((UnicodeString)"ERROR: adopt or set DecimalFormatSymbols() failed"); | |
281 | } | |
282 | ||
283 | UnicodeString posPrefix; | |
284 | pat.setPositivePrefix("+"); | |
285 | posPrefix = pat.getPositivePrefix(posPrefix); | |
286 | logln((UnicodeString)"Positive prefix (should be +): " + posPrefix); | |
287 | if(posPrefix != "+") { | |
288 | errln((UnicodeString)"ERROR: setPositivePrefix() failed"); | |
289 | } | |
290 | ||
291 | UnicodeString negPrefix; | |
292 | pat.setNegativePrefix("-"); | |
293 | negPrefix = pat.getNegativePrefix(negPrefix); | |
294 | logln((UnicodeString)"Negative prefix (should be -): " + negPrefix); | |
295 | if(negPrefix != "-") { | |
296 | errln((UnicodeString)"ERROR: setNegativePrefix() failed"); | |
297 | } | |
298 | ||
299 | UnicodeString posSuffix; | |
300 | pat.setPositiveSuffix("_"); | |
301 | posSuffix = pat.getPositiveSuffix(posSuffix); | |
302 | logln((UnicodeString)"Positive suffix (should be _): " + posSuffix); | |
303 | if(posSuffix != "_") { | |
304 | errln((UnicodeString)"ERROR: setPositiveSuffix() failed"); | |
305 | } | |
306 | ||
307 | UnicodeString negSuffix; | |
308 | pat.setNegativeSuffix("~"); | |
309 | negSuffix = pat.getNegativeSuffix(negSuffix); | |
310 | logln((UnicodeString)"Negative suffix (should be ~): " + negSuffix); | |
311 | if(negSuffix != "~") { | |
312 | errln((UnicodeString)"ERROR: setNegativeSuffix() failed"); | |
313 | } | |
314 | ||
315 | int32_t multiplier = 0; | |
316 | pat.setMultiplier(8); | |
317 | multiplier = pat.getMultiplier(); | |
318 | logln((UnicodeString)"Multiplier (should be 8): " + multiplier); | |
319 | if(multiplier != 8) { | |
320 | errln((UnicodeString)"ERROR: setMultiplier() failed"); | |
321 | } | |
322 | ||
323 | int32_t groupingSize = 0; | |
324 | pat.setGroupingSize(2); | |
325 | groupingSize = pat.getGroupingSize(); | |
326 | logln((UnicodeString)"Grouping size (should be 2): " + (int32_t) groupingSize); | |
327 | if(groupingSize != 2) { | |
328 | errln((UnicodeString)"ERROR: setGroupingSize() failed"); | |
329 | } | |
330 | ||
331 | pat.setDecimalSeparatorAlwaysShown(TRUE); | |
332 | UBool tf = pat.isDecimalSeparatorAlwaysShown(); | |
333 | logln((UnicodeString)"DecimalSeparatorIsAlwaysShown (should be TRUE) is " + (UnicodeString) (tf ? "TRUE" : "FALSE")); | |
334 | if(tf != TRUE) { | |
335 | errln((UnicodeString)"ERROR: setDecimalSeparatorAlwaysShown() failed"); | |
336 | } | |
337 | // Added by Ken Liu testing set/isExponentSignAlwaysShown | |
338 | pat.setExponentSignAlwaysShown(TRUE); | |
339 | UBool esas = pat.isExponentSignAlwaysShown(); | |
340 | logln((UnicodeString)"ExponentSignAlwaysShown (should be TRUE) is " + (UnicodeString) (esas ? "TRUE" : "FALSE")); | |
341 | if(esas != TRUE) { | |
342 | errln((UnicodeString)"ERROR: ExponentSignAlwaysShown() failed"); | |
343 | } | |
344 | ||
345 | // Added by Ken Liu testing set/isScientificNotation | |
346 | pat.setScientificNotation(TRUE); | |
347 | UBool sn = pat.isScientificNotation(); | |
348 | logln((UnicodeString)"isScientificNotation (should be TRUE) is " + (UnicodeString) (sn ? "TRUE" : "FALSE")); | |
349 | if(sn != TRUE) { | |
350 | errln((UnicodeString)"ERROR: setScientificNotation() failed"); | |
351 | } | |
57a6839d | 352 | |
b75a7d8f A |
353 | // Added by Ken Liu testing set/getMinimumExponentDigits |
354 | int8_t MinimumExponentDigits = 0; | |
355 | pat.setMinimumExponentDigits(2); | |
356 | MinimumExponentDigits = pat.getMinimumExponentDigits(); | |
357 | logln((UnicodeString)"MinimumExponentDigits (should be 2) is " + (int8_t) MinimumExponentDigits); | |
358 | if(MinimumExponentDigits != 2) { | |
359 | errln((UnicodeString)"ERROR: setMinimumExponentDigits() failed"); | |
360 | } | |
361 | ||
362 | // Added by Ken Liu testing set/getRoundingIncrement | |
363 | double RoundingIncrement = 0.0; | |
364 | pat.setRoundingIncrement(2.0); | |
365 | RoundingIncrement = pat.getRoundingIncrement(); | |
366 | logln((UnicodeString)"RoundingIncrement (should be 2.0) is " + (double) RoundingIncrement); | |
367 | if(RoundingIncrement != 2.0) { | |
368 | errln((UnicodeString)"ERROR: setRoundingIncrement() failed"); | |
369 | } | |
370 | //end of Ken's Adding | |
371 | ||
372 | UnicodeString funkyPat; | |
373 | funkyPat = pat.toPattern(funkyPat); | |
374 | logln((UnicodeString)"Pattern is " + funkyPat); | |
375 | ||
376 | UnicodeString locPat; | |
377 | locPat = pat.toLocalizedPattern(locPat); | |
378 | logln((UnicodeString)"Localized pattern is " + locPat); | |
379 | ||
380 | // ======= Test applyPattern() | |
381 | ||
382 | logln((UnicodeString)"Testing applyPattern()"); | |
0f5d89e8 | 383 | pat = DecimalFormat(status); // reset |
b75a7d8f A |
384 | |
385 | UnicodeString p1("#,##0.0#;(#,##0.0#)"); | |
386 | logln((UnicodeString)"Applying pattern " + p1); | |
387 | status = U_ZERO_ERROR; | |
388 | pat.applyPattern(p1, status); | |
389 | if(U_FAILURE(status)) { | |
390 | errln((UnicodeString)"ERROR: applyPattern() failed with " + (int32_t) status); | |
391 | } | |
392 | UnicodeString s2; | |
393 | s2 = pat.toPattern(s2); | |
394 | logln((UnicodeString)"Extracted pattern is " + s2); | |
0f5d89e8 | 395 | assertEquals("toPattern() result did not match pattern applied", p1, s2); |
b75a7d8f A |
396 | |
397 | if(pat.getSecondaryGroupingSize() != 0) { | |
398 | errln("FAIL: Secondary Grouping Size should be 0, not %d\n", pat.getSecondaryGroupingSize()); | |
399 | } | |
400 | ||
401 | if(pat.getGroupingSize() != 3) { | |
402 | errln("FAIL: Primary Grouping Size should be 3, not %d\n", pat.getGroupingSize()); | |
403 | } | |
404 | ||
405 | UnicodeString p2("#,##,##0.0# FF;(#,##,##0.0# FF)"); | |
406 | logln((UnicodeString)"Applying pattern " + p2); | |
407 | status = U_ZERO_ERROR; | |
408 | pat.applyLocalizedPattern(p2, status); | |
409 | if(U_FAILURE(status)) { | |
410 | errln((UnicodeString)"ERROR: applyPattern() failed with " + (int32_t) status); | |
411 | } | |
412 | UnicodeString s3; | |
413 | s3 = pat.toLocalizedPattern(s3); | |
414 | logln((UnicodeString)"Extracted pattern is " + s3); | |
0f5d89e8 | 415 | assertEquals("toLocalizedPattern() result did not match pattern applied", p2, s3); |
b75a7d8f A |
416 | |
417 | status = U_ZERO_ERROR; | |
418 | UParseError pe; | |
419 | pat.applyLocalizedPattern(p2, pe, status); | |
420 | if(U_FAILURE(status)) { | |
421 | errln((UnicodeString)"ERROR: applyPattern((with ParseError)) failed with " + (int32_t) status); | |
422 | } | |
423 | UnicodeString s4; | |
424 | s4 = pat.toLocalizedPattern(s3); | |
425 | logln((UnicodeString)"Extracted pattern is " + s4); | |
0f5d89e8 | 426 | assertEquals("toLocalizedPattern(with ParseErr) result did not match pattern applied", p2, s4); |
b75a7d8f A |
427 | |
428 | if(pat.getSecondaryGroupingSize() != 2) { | |
429 | errln("FAIL: Secondary Grouping Size should be 2, not %d\n", pat.getSecondaryGroupingSize()); | |
430 | } | |
431 | ||
432 | if(pat.getGroupingSize() != 3) { | |
433 | errln("FAIL: Primary Grouping Size should be 3, not %d\n", pat.getGroupingSize()); | |
434 | } | |
435 | ||
436 | // ======= Test getStaticClassID() | |
437 | ||
438 | logln((UnicodeString)"Testing getStaticClassID()"); | |
439 | ||
440 | status = U_ZERO_ERROR; | |
441 | NumberFormat *test = new DecimalFormat(status); | |
442 | if(U_FAILURE(status)) { | |
443 | errln((UnicodeString)"ERROR: Couldn't create a DecimalFormat"); | |
444 | } | |
445 | ||
446 | if(test->getDynamicClassID() != DecimalFormat::getStaticClassID()) { | |
447 | errln((UnicodeString)"ERROR: getDynamicClassID() didn't return the expected value"); | |
448 | } | |
449 | ||
450 | delete test; | |
451 | } | |
452 | ||
729e4ab9 A |
453 | void IntlTestDecimalFormatAPI::TestCurrencyPluralInfo(){ |
454 | UErrorCode status = U_ZERO_ERROR; | |
455 | ||
456 | CurrencyPluralInfo *cpi = new CurrencyPluralInfo(status); | |
457 | if(U_FAILURE(status)) { | |
458 | errln((UnicodeString)"ERROR: CurrencyPluralInfo(UErrorCode) could not be created"); | |
459 | } | |
460 | ||
461 | CurrencyPluralInfo cpi1 = *cpi; | |
462 | ||
463 | if(cpi->getDynamicClassID() != CurrencyPluralInfo::getStaticClassID()){ | |
464 | errln((UnicodeString)"ERROR: CurrencyPluralInfo::getDynamicClassID() didn't return the expected value"); | |
465 | } | |
466 | ||
467 | cpi->setCurrencyPluralPattern("","",status); | |
468 | if(U_FAILURE(status)) { | |
469 | errln((UnicodeString)"ERROR: CurrencyPluralInfo::setCurrencyPluralPattern"); | |
470 | } | |
471 | ||
472 | cpi->setLocale(Locale::getCanada(), status); | |
473 | if(U_FAILURE(status)) { | |
474 | errln((UnicodeString)"ERROR: CurrencyPluralInfo::setLocale"); | |
475 | } | |
57a6839d | 476 | |
729e4ab9 A |
477 | cpi->setPluralRules("",status); |
478 | if(U_FAILURE(status)) { | |
479 | errln((UnicodeString)"ERROR: CurrencyPluralInfo::setPluralRules"); | |
480 | } | |
481 | ||
482 | DecimalFormat *df = new DecimalFormat(status); | |
483 | if(U_FAILURE(status)) { | |
484 | errcheckln(status, "ERROR: Could not create DecimalFormat - %s", u_errorName(status)); | |
2ca993e8 | 485 | return; |
729e4ab9 A |
486 | } |
487 | ||
488 | df->adoptCurrencyPluralInfo(cpi); | |
489 | ||
490 | df->getCurrencyPluralInfo(); | |
491 | ||
492 | df->setCurrencyPluralInfo(cpi1); | |
493 | ||
494 | delete df; | |
495 | } | |
496 | ||
b75a7d8f A |
497 | void IntlTestDecimalFormatAPI::testRounding(/*char *par*/) |
498 | { | |
499 | UErrorCode status = U_ZERO_ERROR; | |
500 | double Roundingnumber = 2.55; | |
501 | double Roundingnumber1 = -2.55; | |
502 | //+2.55 results -2.55 results | |
503 | double result[]={ 3.0, -2.0, // kRoundCeiling 0, | |
504 | 2.0, -3.0, // kRoundFloor 1, | |
505 | 2.0, -2.0, // kRoundDown 2, | |
506 | 3.0, -3.0, // kRoundUp 3, | |
507 | 3.0, -3.0, // kRoundHalfEven 4, | |
508 | 3.0, -3.0, // kRoundHalfDown 5, | |
57a6839d | 509 | 3.0, -3.0 // kRoundHalfUp 6 |
b75a7d8f A |
510 | }; |
511 | DecimalFormat pat(status); | |
512 | if(U_FAILURE(status)) { | |
729e4ab9 | 513 | errcheckln(status, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status)); |
b75a7d8f A |
514 | return; |
515 | } | |
516 | uint16_t mode; | |
517 | uint16_t i=0; | |
518 | UnicodeString message; | |
519 | UnicodeString resultStr; | |
520 | for(mode=0;mode < 7;mode++){ | |
521 | pat.setRoundingMode((DecimalFormat::ERoundingMode)mode); | |
522 | if(pat.getRoundingMode() != (DecimalFormat::ERoundingMode)mode){ | |
523 | errln((UnicodeString)"SetRoundingMode or GetRoundingMode failed for mode=" + mode); | |
524 | } | |
525 | ||
526 | ||
527 | //for +2.55 with RoundingIncrement=1.0 | |
528 | pat.setRoundingIncrement(1.0); | |
529 | pat.format(Roundingnumber, resultStr); | |
0f5d89e8 | 530 | message= (UnicodeString)"round(" + (double)Roundingnumber + UnicodeString(",") + mode + UnicodeString(",FALSE) with RoundingIncrement=1.0==>"); |
b75a7d8f A |
531 | verify(message, resultStr, result[i++]); |
532 | message.remove(); | |
533 | resultStr.remove(); | |
534 | ||
535 | //for -2.55 with RoundingIncrement=1.0 | |
536 | pat.format(Roundingnumber1, resultStr); | |
0f5d89e8 | 537 | message= (UnicodeString)"round(" + (double)Roundingnumber1 + UnicodeString(",") + mode + UnicodeString(",FALSE) with RoundingIncrement=1.0==>"); |
b75a7d8f A |
538 | verify(message, resultStr, result[i++]); |
539 | message.remove(); | |
540 | resultStr.remove(); | |
541 | } | |
542 | ||
543 | } | |
544 | void IntlTestDecimalFormatAPI::verify(const UnicodeString& message, const UnicodeString& got, double expected){ | |
545 | logln((UnicodeString)message + got + (UnicodeString)" Expected : " + expected); | |
546 | UnicodeString expectedStr(""); | |
547 | expectedStr=expectedStr + expected; | |
548 | if(got != expectedStr ) { | |
51004dcb A |
549 | errln((UnicodeString)"ERROR: " + message + got + (UnicodeString)" Expected : " + expectedStr); |
550 | } | |
551 | } | |
552 | ||
553 | void IntlTestDecimalFormatAPI::verifyString(const UnicodeString& message, const UnicodeString& got, UnicodeString& expected){ | |
554 | logln((UnicodeString)message + got + (UnicodeString)" Expected : " + expected); | |
555 | if(got != expected ) { | |
556 | errln((UnicodeString)"ERROR: " + message + got + (UnicodeString)" Expected : " + expected); | |
b75a7d8f A |
557 | } |
558 | } | |
559 | ||
729e4ab9 A |
560 | void IntlTestDecimalFormatAPI::testRoundingInc(/*char *par*/) |
561 | { | |
562 | UErrorCode status = U_ZERO_ERROR; | |
563 | DecimalFormat pat(UnicodeString("#,##0.00"),status); | |
564 | if(U_FAILURE(status)) { | |
565 | errcheckln(status, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status)); | |
566 | return; | |
567 | } | |
568 | ||
569 | // get default rounding increment | |
570 | double roundingInc = pat.getRoundingIncrement(); | |
571 | if (roundingInc != 0.0) { | |
572 | errln((UnicodeString)"ERROR: Rounding increment not zero"); | |
573 | return; | |
574 | } | |
575 | ||
57a6839d | 576 | // With rounding now being handled by decNumber, we no longer |
729e4ab9 A |
577 | // set a rounding increment to enable non-default mode rounding, |
578 | // checking of which was the original point of this test. | |
579 | ||
57a6839d | 580 | // set rounding mode with zero increment. Rounding |
729e4ab9 A |
581 | // increment should not be set by this operation |
582 | pat.setRoundingMode((DecimalFormat::ERoundingMode)0); | |
583 | roundingInc = pat.getRoundingIncrement(); | |
584 | if (roundingInc != 0.0) { | |
585 | errln((UnicodeString)"ERROR: Rounding increment not zero after setRoundingMode"); | |
586 | return; | |
587 | } | |
588 | } | |
589 | ||
51004dcb A |
590 | void IntlTestDecimalFormatAPI::TestScale() |
591 | { | |
592 | typedef struct TestData { | |
593 | double inputValue; | |
594 | int inputScale; | |
57a6839d | 595 | const char *expectedOutput; |
51004dcb A |
596 | } TestData; |
597 | ||
598 | static TestData testData[] = { | |
599 | { 100.0, 3, "100,000" }, | |
600 | { 10034.0, -2, "100.34" }, | |
601 | { 0.86, -3, "0.0009" }, | |
602 | { -0.000455, 1, "-0%" }, | |
603 | { -0.000555, 1, "-1%" }, | |
604 | { 0.000455, 1, "0%" }, | |
605 | { 0.000555, 1, "1%" }, | |
606 | }; | |
607 | ||
608 | UErrorCode status = U_ZERO_ERROR; | |
609 | DecimalFormat pat(status); | |
610 | if(U_FAILURE(status)) { | |
611 | errcheckln(status, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status)); | |
612 | return; | |
613 | } | |
614 | ||
615 | UnicodeString message; | |
616 | UnicodeString resultStr; | |
617 | UnicodeString exp; | |
618 | UnicodeString percentPattern("#,##0%"); | |
619 | pat.setMaximumFractionDigits(4); | |
620 | ||
b331163b | 621 | for(int32_t i=0; i < UPRV_LENGTHOF(testData); i++) { |
51004dcb A |
622 | if ( i > 2 ) { |
623 | pat.applyPattern(percentPattern,status); | |
624 | } | |
3d1f044b A |
625 | // Test both the attribute and the setter |
626 | if (i % 2 == 0) { | |
627 | pat.setAttribute(UNUM_SCALE, testData[i].inputScale,status); | |
628 | assertEquals("", testData[i].inputScale, pat.getMultiplierScale()); | |
629 | } else { | |
630 | pat.setMultiplierScale(testData[i].inputScale); | |
631 | assertEquals("", testData[i].inputScale, pat.getAttribute(UNUM_SCALE, status)); | |
632 | } | |
51004dcb | 633 | pat.format(testData[i].inputValue, resultStr); |
57a6839d A |
634 | message = UnicodeString("Unexpected output for ") + testData[i].inputValue + UnicodeString(" and scale ") + |
635 | testData[i].inputScale + UnicodeString(". Got: "); | |
51004dcb A |
636 | exp = testData[i].expectedOutput; |
637 | verifyString(message, resultStr, exp); | |
638 | message.remove(); | |
639 | resultStr.remove(); | |
640 | exp.remove(); | |
641 | } | |
642 | } | |
57a6839d A |
643 | |
644 | ||
3d1f044b A |
645 | #define ASSERT_EQUAL(expect, actual) { \ |
646 | /* ICU-20080: Use temporary variables to avoid strange compiler behaviour \ | |
647 | (with the nice side-effect of avoiding repeated function calls too). */ \ | |
648 | auto lhs = (expect); \ | |
649 | auto rhs = (actual); \ | |
650 | char tmp[200]; \ | |
651 | sprintf(tmp, "(%g==%g)", (double)lhs, (double)rhs); \ | |
652 | assertTrue(tmp, (lhs==rhs), FALSE, TRUE, __FILE__, __LINE__); } | |
653 | ||
654 | #if defined(_MSC_VER) | |
655 | // Ignore the noisy warning 4805 (comparisons between int and bool) in the function below as we use the ICU TRUE/FALSE macros | |
656 | // which are int values, whereas some of the DecimalQuantity methods return C++ bools. | |
657 | #pragma warning(push) | |
658 | #pragma warning(disable: 4805) | |
659 | #endif | |
57a6839d A |
660 | void IntlTestDecimalFormatAPI::TestFixedDecimal() { |
661 | UErrorCode status = U_ZERO_ERROR; | |
662 | ||
b331163b | 663 | LocalPointer<DecimalFormat> df(new DecimalFormat("###", status), status); |
3d1f044b | 664 | assertSuccess(WHERE, status); |
2ca993e8 A |
665 | if (status == U_MISSING_RESOURCE_ERROR) { |
666 | return; | |
667 | } | |
3d1f044b A |
668 | number::impl::DecimalQuantity fd; |
669 | df->formatToDecimalQuantity(44, fd, status); | |
670 | assertSuccess(WHERE, status); | |
671 | ASSERT_EQUAL(44, fd.getPluralOperand(PLURAL_OPERAND_N)); | |
672 | ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_V)); | |
673 | ASSERT_EQUAL(FALSE, fd.isNegative()); | |
2ca993e8 | 674 | |
3d1f044b A |
675 | df->formatToDecimalQuantity(-44, fd, status); |
676 | assertSuccess(WHERE, status); | |
677 | ASSERT_EQUAL(44, fd.getPluralOperand(PLURAL_OPERAND_N)); | |
678 | ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_V)); | |
679 | ASSERT_EQUAL(TRUE, fd.isNegative()); | |
57a6839d | 680 | |
b331163b | 681 | df.adoptInsteadAndCheckErrorCode(new DecimalFormat("###.00##", status), status); |
3d1f044b A |
682 | assertSuccess(WHERE, status); |
683 | df->formatToDecimalQuantity(123.456, fd, status); | |
684 | assertSuccess(WHERE, status); | |
685 | ASSERT_EQUAL(3, fd.getPluralOperand(PLURAL_OPERAND_V)); // v | |
686 | ASSERT_EQUAL(456, fd.getPluralOperand(PLURAL_OPERAND_F)); // f | |
687 | ASSERT_EQUAL(456, fd.getPluralOperand(PLURAL_OPERAND_T)); // t | |
688 | ASSERT_EQUAL(123, fd.getPluralOperand(PLURAL_OPERAND_I)); // i | |
689 | ASSERT_EQUAL(123.456, fd.getPluralOperand(PLURAL_OPERAND_N)); // n | |
0f5d89e8 | 690 | ASSERT_EQUAL(FALSE, fd.hasIntegerValue()); |
3d1f044b A |
691 | ASSERT_EQUAL(FALSE, fd.isNegative()); |
692 | ||
693 | df->formatToDecimalQuantity(-123.456, fd, status); | |
694 | assertSuccess(WHERE, status); | |
695 | ASSERT_EQUAL(3, fd.getPluralOperand(PLURAL_OPERAND_V)); // v | |
696 | ASSERT_EQUAL(456, fd.getPluralOperand(PLURAL_OPERAND_F)); // f | |
697 | ASSERT_EQUAL(456, fd.getPluralOperand(PLURAL_OPERAND_T)); // t | |
698 | ASSERT_EQUAL(123, fd.getPluralOperand(PLURAL_OPERAND_I)); // i | |
699 | ASSERT_EQUAL(123.456, fd.getPluralOperand(PLURAL_OPERAND_N)); // n | |
0f5d89e8 | 700 | ASSERT_EQUAL(FALSE, fd.hasIntegerValue()); |
3d1f044b | 701 | ASSERT_EQUAL(TRUE, fd.isNegative()); |
2ca993e8 A |
702 | |
703 | // test max int digits | |
704 | df->setMaximumIntegerDigits(2); | |
3d1f044b A |
705 | df->formatToDecimalQuantity(123.456, fd, status); |
706 | assertSuccess(WHERE, status); | |
707 | ASSERT_EQUAL(3, fd.getPluralOperand(PLURAL_OPERAND_V)); // v | |
708 | ASSERT_EQUAL(456, fd.getPluralOperand(PLURAL_OPERAND_F)); // f | |
709 | ASSERT_EQUAL(456, fd.getPluralOperand(PLURAL_OPERAND_T)); // t | |
710 | ASSERT_EQUAL(23, fd.getPluralOperand(PLURAL_OPERAND_I)); // i | |
711 | ASSERT_EQUAL(23.456, fd.getPluralOperand(PLURAL_OPERAND_N)); // n | |
0f5d89e8 | 712 | ASSERT_EQUAL(FALSE, fd.hasIntegerValue()); |
3d1f044b A |
713 | ASSERT_EQUAL(FALSE, fd.isNegative()); |
714 | ||
715 | df->formatToDecimalQuantity(-123.456, fd, status); | |
716 | assertSuccess(WHERE, status); | |
717 | ASSERT_EQUAL(3, fd.getPluralOperand(PLURAL_OPERAND_V)); // v | |
718 | ASSERT_EQUAL(456, fd.getPluralOperand(PLURAL_OPERAND_F)); // f | |
719 | ASSERT_EQUAL(456, fd.getPluralOperand(PLURAL_OPERAND_T)); // t | |
720 | ASSERT_EQUAL(23, fd.getPluralOperand(PLURAL_OPERAND_I)); // i | |
721 | ASSERT_EQUAL(23.456, fd.getPluralOperand(PLURAL_OPERAND_N)); // n | |
0f5d89e8 | 722 | ASSERT_EQUAL(FALSE, fd.hasIntegerValue()); |
3d1f044b | 723 | ASSERT_EQUAL(TRUE, fd.isNegative()); |
2ca993e8 A |
724 | |
725 | // test max fraction digits | |
726 | df->setMaximumIntegerDigits(2000000000); | |
727 | df->setMaximumFractionDigits(2); | |
3d1f044b A |
728 | df->formatToDecimalQuantity(123.456, fd, status); |
729 | assertSuccess(WHERE, status); | |
730 | ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_V)); // v | |
731 | ASSERT_EQUAL(46, fd.getPluralOperand(PLURAL_OPERAND_F)); // f | |
732 | ASSERT_EQUAL(46, fd.getPluralOperand(PLURAL_OPERAND_T)); // t | |
733 | ASSERT_EQUAL(123, fd.getPluralOperand(PLURAL_OPERAND_I)); // i | |
734 | ASSERT_EQUAL(123.46, fd.getPluralOperand(PLURAL_OPERAND_N)); // n | |
0f5d89e8 | 735 | ASSERT_EQUAL(FALSE, fd.hasIntegerValue()); |
3d1f044b A |
736 | ASSERT_EQUAL(FALSE, fd.isNegative()); |
737 | ||
738 | df->formatToDecimalQuantity(-123.456, fd, status); | |
739 | assertSuccess(WHERE, status); | |
740 | ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_V)); // v | |
741 | ASSERT_EQUAL(46, fd.getPluralOperand(PLURAL_OPERAND_F)); // f | |
742 | ASSERT_EQUAL(46, fd.getPluralOperand(PLURAL_OPERAND_T)); // t | |
743 | ASSERT_EQUAL(123, fd.getPluralOperand(PLURAL_OPERAND_I)); // i | |
744 | ASSERT_EQUAL(123.46, fd.getPluralOperand(PLURAL_OPERAND_N)); // n | |
0f5d89e8 | 745 | ASSERT_EQUAL(FALSE, fd.hasIntegerValue()); |
3d1f044b | 746 | ASSERT_EQUAL(TRUE, fd.isNegative()); |
2ca993e8 A |
747 | |
748 | // test esoteric rounding | |
749 | df->setMaximumFractionDigits(6); | |
750 | df->setRoundingIncrement(7.3); | |
751 | ||
3d1f044b A |
752 | df->formatToDecimalQuantity(30.0, fd, status); |
753 | assertSuccess(WHERE, status); | |
754 | ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_V)); // v | |
755 | ASSERT_EQUAL(20, fd.getPluralOperand(PLURAL_OPERAND_F)); // f | |
756 | ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_T)); // t | |
757 | ASSERT_EQUAL(29, fd.getPluralOperand(PLURAL_OPERAND_I)); // i | |
758 | ASSERT_EQUAL(29.2, fd.getPluralOperand(PLURAL_OPERAND_N)); // n | |
0f5d89e8 | 759 | ASSERT_EQUAL(FALSE, fd.hasIntegerValue()); |
3d1f044b A |
760 | ASSERT_EQUAL(FALSE, fd.isNegative()); |
761 | ||
762 | df->formatToDecimalQuantity(-30.0, fd, status); | |
763 | assertSuccess(WHERE, status); | |
764 | ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_V)); // v | |
765 | ASSERT_EQUAL(20, fd.getPluralOperand(PLURAL_OPERAND_F)); // f | |
766 | ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_T)); // t | |
767 | ASSERT_EQUAL(29, fd.getPluralOperand(PLURAL_OPERAND_I)); // i | |
768 | ASSERT_EQUAL(29.2, fd.getPluralOperand(PLURAL_OPERAND_N)); // n | |
0f5d89e8 | 769 | ASSERT_EQUAL(FALSE, fd.hasIntegerValue()); |
3d1f044b | 770 | ASSERT_EQUAL(TRUE, fd.isNegative()); |
2ca993e8 | 771 | |
b331163b | 772 | df.adoptInsteadAndCheckErrorCode(new DecimalFormat("###", status), status); |
3d1f044b A |
773 | assertSuccess(WHERE, status); |
774 | df->formatToDecimalQuantity(123.456, fd, status); | |
775 | assertSuccess(WHERE, status); | |
776 | ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_V)); | |
777 | ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_F)); | |
778 | ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_T)); | |
779 | ASSERT_EQUAL(123, fd.getPluralOperand(PLURAL_OPERAND_I)); | |
0f5d89e8 | 780 | ASSERT_EQUAL(TRUE, fd.hasIntegerValue()); |
3d1f044b | 781 | ASSERT_EQUAL(FALSE, fd.isNegative()); |
57a6839d | 782 | |
b331163b | 783 | df.adoptInsteadAndCheckErrorCode(new DecimalFormat("###.0", status), status); |
3d1f044b A |
784 | assertSuccess(WHERE, status); |
785 | df->formatToDecimalQuantity(123.01, fd, status); | |
786 | assertSuccess(WHERE, status); | |
787 | ASSERT_EQUAL(1, fd.getPluralOperand(PLURAL_OPERAND_V)); | |
788 | ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_F)); | |
789 | ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_T)); | |
790 | ASSERT_EQUAL(123, fd.getPluralOperand(PLURAL_OPERAND_I)); | |
0f5d89e8 | 791 | ASSERT_EQUAL(TRUE, fd.hasIntegerValue()); |
3d1f044b | 792 | ASSERT_EQUAL(FALSE, fd.isNegative()); |
57a6839d | 793 | |
b331163b | 794 | df.adoptInsteadAndCheckErrorCode(new DecimalFormat("###.0", status), status); |
3d1f044b A |
795 | assertSuccess(WHERE, status); |
796 | df->formatToDecimalQuantity(123.06, fd, status); | |
797 | assertSuccess(WHERE, status); | |
798 | ASSERT_EQUAL(1, fd.getPluralOperand(PLURAL_OPERAND_V)); | |
799 | ASSERT_EQUAL(1, fd.getPluralOperand(PLURAL_OPERAND_F)); | |
800 | ASSERT_EQUAL(1, fd.getPluralOperand(PLURAL_OPERAND_T)); | |
801 | ASSERT_EQUAL(123, fd.getPluralOperand(PLURAL_OPERAND_I)); | |
0f5d89e8 | 802 | ASSERT_EQUAL(FALSE, fd.hasIntegerValue()); |
3d1f044b | 803 | ASSERT_EQUAL(FALSE, fd.isNegative()); |
57a6839d | 804 | |
b331163b | 805 | df.adoptInsteadAndCheckErrorCode(new DecimalFormat("@@@@@", status), status); // Significant Digits |
3d1f044b A |
806 | assertSuccess(WHERE, status); |
807 | df->formatToDecimalQuantity(123, fd, status); | |
808 | assertSuccess(WHERE, status); | |
809 | ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_V)); | |
810 | ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_F)); | |
811 | ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_T)); | |
812 | ASSERT_EQUAL(123, fd.getPluralOperand(PLURAL_OPERAND_I)); | |
0f5d89e8 | 813 | ASSERT_EQUAL(TRUE, fd.hasIntegerValue()); |
3d1f044b | 814 | ASSERT_EQUAL(FALSE, fd.isNegative()); |
57a6839d | 815 | |
b331163b | 816 | df.adoptInsteadAndCheckErrorCode(new DecimalFormat("@@@@@", status), status); // Significant Digits |
3d1f044b A |
817 | assertSuccess(WHERE, status); |
818 | df->formatToDecimalQuantity(1.23, fd, status); | |
819 | assertSuccess(WHERE, status); | |
820 | ASSERT_EQUAL(4, fd.getPluralOperand(PLURAL_OPERAND_V)); | |
821 | ASSERT_EQUAL(2300, fd.getPluralOperand(PLURAL_OPERAND_F)); | |
822 | ASSERT_EQUAL(23, fd.getPluralOperand(PLURAL_OPERAND_T)); | |
823 | ASSERT_EQUAL(1, fd.getPluralOperand(PLURAL_OPERAND_I)); | |
0f5d89e8 | 824 | ASSERT_EQUAL(FALSE, fd.hasIntegerValue()); |
3d1f044b | 825 | ASSERT_EQUAL(FALSE, fd.isNegative()); |
57a6839d | 826 | |
3d1f044b A |
827 | df->formatToDecimalQuantity(uprv_getInfinity(), fd, status); |
828 | assertSuccess(WHERE, status); | |
829 | ASSERT_EQUAL(TRUE, fd.isNaN() || fd.isInfinite()); | |
830 | df->formatToDecimalQuantity(0.0, fd, status); | |
831 | ASSERT_EQUAL(FALSE, fd.isNaN() || fd.isInfinite()); | |
832 | df->formatToDecimalQuantity(uprv_getNaN(), fd, status); | |
833 | ASSERT_EQUAL(TRUE, fd.isNaN() || fd.isInfinite()); | |
834 | assertSuccess(WHERE, status); | |
57a6839d A |
835 | |
836 | // Test Big Decimal input. | |
837 | // 22 digits before and after decimal, will exceed the precision of a double | |
838 | // and force DecimalFormat::getFixedDecimal() to work with a digit list. | |
b331163b A |
839 | df.adoptInsteadAndCheckErrorCode( |
840 | new DecimalFormat("#####################0.00####################", status), status); | |
3d1f044b | 841 | assertSuccess(WHERE, status); |
57a6839d | 842 | Formattable fable("12.34", status); |
3d1f044b A |
843 | assertSuccess(WHERE, status); |
844 | df->formatToDecimalQuantity(fable, fd, status); | |
845 | assertSuccess(WHERE, status); | |
846 | ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_V)); | |
847 | ASSERT_EQUAL(34, fd.getPluralOperand(PLURAL_OPERAND_F)); | |
848 | ASSERT_EQUAL(34, fd.getPluralOperand(PLURAL_OPERAND_T)); | |
849 | ASSERT_EQUAL(12, fd.getPluralOperand(PLURAL_OPERAND_I)); | |
0f5d89e8 | 850 | ASSERT_EQUAL(FALSE, fd.hasIntegerValue()); |
3d1f044b A |
851 | ASSERT_EQUAL(FALSE, fd.isNegative()); |
852 | ||
853 | fable.setDecimalNumber("12.3456789012345678900123456789", status); | |
854 | assertSuccess(WHERE, status); | |
855 | df->formatToDecimalQuantity(fable, fd, status); | |
856 | assertSuccess(WHERE, status); | |
857 | ASSERT_EQUAL(22, fd.getPluralOperand(PLURAL_OPERAND_V)); | |
858 | ASSERT_EQUAL(3456789012345678900LL, fd.getPluralOperand(PLURAL_OPERAND_F)); | |
859 | ASSERT_EQUAL(34567890123456789LL, fd.getPluralOperand(PLURAL_OPERAND_T)); | |
860 | ASSERT_EQUAL(12, fd.getPluralOperand(PLURAL_OPERAND_I)); | |
0f5d89e8 | 861 | ASSERT_EQUAL(FALSE, fd.hasIntegerValue()); |
3d1f044b | 862 | ASSERT_EQUAL(FALSE, fd.isNegative()); |
57a6839d A |
863 | |
864 | // On field overflow, Integer part is truncated on the left, fraction part on the right. | |
865 | fable.setDecimalNumber("123456789012345678901234567890.123456789012345678901234567890", status); | |
3d1f044b A |
866 | assertSuccess(WHERE, status); |
867 | df->formatToDecimalQuantity(fable, fd, status); | |
868 | assertSuccess(WHERE, status); | |
869 | ASSERT_EQUAL(22, fd.getPluralOperand(PLURAL_OPERAND_V)); | |
870 | ASSERT_EQUAL(1234567890123456789LL, fd.getPluralOperand(PLURAL_OPERAND_F)); | |
871 | ASSERT_EQUAL(1234567890123456789LL, fd.getPluralOperand(PLURAL_OPERAND_T)); | |
872 | ASSERT_EQUAL(345678901234567890LL, fd.getPluralOperand(PLURAL_OPERAND_I)); | |
0f5d89e8 | 873 | ASSERT_EQUAL(FALSE, fd.hasIntegerValue()); |
3d1f044b | 874 | ASSERT_EQUAL(FALSE, fd.isNegative()); |
57a6839d A |
875 | |
876 | // Digits way to the right of the decimal but within the format's precision aren't truncated | |
877 | fable.setDecimalNumber("1.0000000000000000000012", status); | |
3d1f044b A |
878 | assertSuccess(WHERE, status); |
879 | df->formatToDecimalQuantity(fable, fd, status); | |
880 | assertSuccess(WHERE, status); | |
881 | ASSERT_EQUAL(22, fd.getPluralOperand(PLURAL_OPERAND_V)); | |
882 | ASSERT_EQUAL(12, fd.getPluralOperand(PLURAL_OPERAND_F)); | |
883 | ASSERT_EQUAL(12, fd.getPluralOperand(PLURAL_OPERAND_T)); | |
884 | ASSERT_EQUAL(1, fd.getPluralOperand(PLURAL_OPERAND_I)); | |
0f5d89e8 | 885 | ASSERT_EQUAL(FALSE, fd.hasIntegerValue()); |
3d1f044b | 886 | ASSERT_EQUAL(FALSE, fd.isNegative()); |
57a6839d A |
887 | |
888 | // Digits beyond the precision of the format are rounded away | |
889 | fable.setDecimalNumber("1.000000000000000000000012", status); | |
3d1f044b A |
890 | assertSuccess(WHERE, status); |
891 | df->formatToDecimalQuantity(fable, fd, status); | |
892 | assertSuccess(WHERE, status); | |
893 | ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_V)); | |
894 | ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_F)); | |
895 | ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_T)); | |
896 | ASSERT_EQUAL(1, fd.getPluralOperand(PLURAL_OPERAND_I)); | |
0f5d89e8 | 897 | ASSERT_EQUAL(TRUE, fd.hasIntegerValue()); |
3d1f044b | 898 | ASSERT_EQUAL(FALSE, fd.isNegative()); |
57a6839d A |
899 | |
900 | // Negative numbers come through | |
901 | fable.setDecimalNumber("-1.0000000000000000000012", status); | |
3d1f044b A |
902 | assertSuccess(WHERE, status); |
903 | df->formatToDecimalQuantity(fable, fd, status); | |
904 | assertSuccess(WHERE, status); | |
905 | ASSERT_EQUAL(22, fd.getPluralOperand(PLURAL_OPERAND_V)); | |
906 | ASSERT_EQUAL(12, fd.getPluralOperand(PLURAL_OPERAND_F)); | |
907 | ASSERT_EQUAL(12, fd.getPluralOperand(PLURAL_OPERAND_T)); | |
908 | ASSERT_EQUAL(1, fd.getPluralOperand(PLURAL_OPERAND_I)); | |
0f5d89e8 | 909 | ASSERT_EQUAL(FALSE, fd.hasIntegerValue()); |
3d1f044b | 910 | ASSERT_EQUAL(TRUE, fd.isNegative()); |
57a6839d A |
911 | |
912 | // MinFractionDigits from format larger than from number. | |
913 | fable.setDecimalNumber("1000000000000000000000.3", status); | |
3d1f044b A |
914 | assertSuccess(WHERE, status); |
915 | df->formatToDecimalQuantity(fable, fd, status); | |
916 | assertSuccess(WHERE, status); | |
917 | ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_V)); | |
918 | ASSERT_EQUAL(30, fd.getPluralOperand(PLURAL_OPERAND_F)); | |
919 | ASSERT_EQUAL(3, fd.getPluralOperand(PLURAL_OPERAND_T)); | |
920 | ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_I)); | |
0f5d89e8 | 921 | ASSERT_EQUAL(FALSE, fd.hasIntegerValue()); |
3d1f044b | 922 | ASSERT_EQUAL(FALSE, fd.isNegative()); |
57a6839d | 923 | |
2ca993e8 | 924 | fable.setDecimalNumber("1000000000000000050000.3", status); |
3d1f044b A |
925 | assertSuccess(WHERE, status); |
926 | df->formatToDecimalQuantity(fable, fd, status); | |
927 | assertSuccess(WHERE, status); | |
928 | ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_V)); | |
929 | ASSERT_EQUAL(30, fd.getPluralOperand(PLURAL_OPERAND_F)); | |
930 | ASSERT_EQUAL(3, fd.getPluralOperand(PLURAL_OPERAND_T)); | |
931 | ASSERT_EQUAL(50000LL, fd.getPluralOperand(PLURAL_OPERAND_I)); | |
0f5d89e8 | 932 | ASSERT_EQUAL(FALSE, fd.hasIntegerValue()); |
3d1f044b | 933 | ASSERT_EQUAL(FALSE, fd.isNegative()); |
2ca993e8 | 934 | |
57a6839d A |
935 | // Test some int64_t values that are out of the range of a double |
936 | fable.setInt64(4503599627370496LL); | |
3d1f044b A |
937 | assertSuccess(WHERE, status); |
938 | df->formatToDecimalQuantity(fable, fd, status); | |
939 | assertSuccess(WHERE, status); | |
940 | ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_V)); | |
941 | ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_F)); | |
942 | ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_T)); | |
943 | ASSERT_EQUAL(4503599627370496LL, fd.getPluralOperand(PLURAL_OPERAND_I)); | |
0f5d89e8 | 944 | ASSERT_EQUAL(TRUE, fd.hasIntegerValue()); |
3d1f044b | 945 | ASSERT_EQUAL(FALSE, fd.isNegative()); |
57a6839d A |
946 | |
947 | fable.setInt64(4503599627370497LL); | |
3d1f044b A |
948 | assertSuccess(WHERE, status); |
949 | df->formatToDecimalQuantity(fable, fd, status); | |
950 | assertSuccess(WHERE, status); | |
951 | ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_V)); | |
952 | ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_F)); | |
953 | ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_T)); | |
954 | ASSERT_EQUAL(4503599627370497LL, fd.getPluralOperand(PLURAL_OPERAND_I)); | |
0f5d89e8 | 955 | ASSERT_EQUAL(TRUE, fd.hasIntegerValue()); |
3d1f044b | 956 | ASSERT_EQUAL(FALSE, fd.isNegative()); |
57a6839d A |
957 | |
958 | fable.setInt64(9223372036854775807LL); | |
3d1f044b A |
959 | assertSuccess(WHERE, status); |
960 | df->formatToDecimalQuantity(fable, fd, status); | |
961 | assertSuccess(WHERE, status); | |
962 | ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_V)); | |
963 | ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_F)); | |
964 | ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_T)); | |
57a6839d A |
965 | // note: going through DigitList path to FixedDecimal, which is trimming |
966 | // int64_t fields to 18 digits. See ticket Ticket #10374 | |
3d1f044b | 967 | ASSERT_EQUAL(223372036854775807LL, fd.getPluralOperand(PLURAL_OPERAND_I)); |
0f5d89e8 | 968 | ASSERT_EQUAL(TRUE, fd.hasIntegerValue()); |
3d1f044b | 969 | ASSERT_EQUAL(FALSE, fd.isNegative()); |
57a6839d A |
970 | |
971 | } | |
3d1f044b A |
972 | #if defined(_MSC_VER) |
973 | // Re-enable 4805 warnings (comparisons between int and bool). | |
974 | #pragma warning(pop) | |
975 | #endif | |
57a6839d A |
976 | |
977 | void IntlTestDecimalFormatAPI::TestBadFastpath() { | |
978 | UErrorCode status = U_ZERO_ERROR; | |
979 | ||
b331163b | 980 | LocalPointer<DecimalFormat> df(new DecimalFormat("###", status), status); |
57a6839d A |
981 | if (U_FAILURE(status)) { |
982 | dataerrln("Error creating new DecimalFormat - %s", u_errorName(status)); | |
983 | return; | |
984 | } | |
985 | ||
986 | UnicodeString fmt; | |
987 | fmt.remove(); | |
f3c0d7a5 | 988 | assertEquals("Format 1234", "1234", df->format((int32_t)1234, fmt)); |
57a6839d A |
989 | df->setGroupingUsed(FALSE); |
990 | fmt.remove(); | |
f3c0d7a5 | 991 | assertEquals("Format 1234", "1234", df->format((int32_t)1234, fmt)); |
57a6839d | 992 | df->setGroupingUsed(TRUE); |
2ca993e8 | 993 | df->setGroupingSize(3); |
57a6839d | 994 | fmt.remove(); |
f3c0d7a5 | 995 | assertEquals("Format 1234 w/ grouping", "1,234", df->format((int32_t)1234, fmt)); |
57a6839d A |
996 | } |
997 | ||
b331163b A |
998 | void IntlTestDecimalFormatAPI::TestRequiredDecimalPoint() { |
999 | UErrorCode status = U_ZERO_ERROR; | |
1000 | UnicodeString text("99"); | |
1001 | Formattable result1; | |
1002 | UnicodeString pat1("##.0000"); | |
1003 | UnicodeString pat2("00.0"); | |
1004 | ||
1005 | LocalPointer<DecimalFormat> df(new DecimalFormat(pat1, status), status); | |
1006 | if (U_FAILURE(status)) { | |
1007 | dataerrln("Error creating new DecimalFormat - %s", u_errorName(status)); | |
1008 | return; | |
1009 | } | |
1010 | ||
1011 | status = U_ZERO_ERROR; | |
1012 | df->applyPattern(pat1, status); | |
1013 | if(U_FAILURE(status)) { | |
1014 | errln((UnicodeString)"ERROR: applyPattern() failed"); | |
1015 | } | |
1016 | df->parse(text, result1, status); | |
1017 | if(U_FAILURE(status)) { | |
1018 | errln((UnicodeString)"ERROR: parse() failed"); | |
1019 | } | |
1020 | df->setDecimalPatternMatchRequired(TRUE); | |
1021 | df->parse(text, result1, status); | |
1022 | if(U_SUCCESS(status)) { | |
1023 | errln((UnicodeString)"ERROR: unexpected parse()"); | |
1024 | } | |
1025 | ||
1026 | ||
1027 | status = U_ZERO_ERROR; | |
1028 | df->applyPattern(pat2, status); | |
1029 | df->setDecimalPatternMatchRequired(FALSE); | |
1030 | if(U_FAILURE(status)) { | |
1031 | errln((UnicodeString)"ERROR: applyPattern(2) failed"); | |
1032 | } | |
1033 | df->parse(text, result1, status); | |
1034 | if(U_FAILURE(status)) { | |
1035 | errln((UnicodeString)"ERROR: parse(2) failed - " + u_errorName(status)); | |
1036 | } | |
1037 | df->setDecimalPatternMatchRequired(TRUE); | |
1038 | df->parse(text, result1, status); | |
1039 | if(U_SUCCESS(status)) { | |
1040 | errln((UnicodeString)"ERROR: unexpected parse(2)"); | |
1041 | } | |
1042 | } | |
1043 | ||
0f5d89e8 A |
1044 | void IntlTestDecimalFormatAPI::testErrorCode() { |
1045 | // Try each DecimalFormat constructor with an errorCode set on input, | |
1046 | // Verify no crashes or leaks, and that the errorCode is not altered. | |
1047 | ||
1048 | UErrorCode status = U_ZERO_ERROR; | |
1049 | const UnicodeString pattern(u"0.###E0"); | |
1050 | UParseError pe; | |
1051 | DecimalFormatSymbols symbols(Locale::getUS(), status); | |
1052 | assertSuccess(WHERE, status); | |
1053 | ||
1054 | { | |
1055 | status = U_INTERNAL_PROGRAM_ERROR; | |
1056 | DecimalFormat df(status); | |
1057 | assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status); | |
1058 | } | |
1059 | { | |
1060 | status = U_INTERNAL_PROGRAM_ERROR; | |
1061 | DecimalFormat df(pattern, status); | |
1062 | assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status); | |
1063 | } | |
1064 | { | |
1065 | status = U_INTERNAL_PROGRAM_ERROR; | |
1066 | DecimalFormat df(pattern, new DecimalFormatSymbols(symbols), status); | |
1067 | assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status); | |
1068 | } | |
1069 | { | |
1070 | status = U_INTERNAL_PROGRAM_ERROR; | |
1071 | DecimalFormat df(pattern, new DecimalFormatSymbols(symbols), UNUM_DECIMAL_COMPACT_LONG, status); | |
1072 | assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status); | |
1073 | } | |
1074 | { | |
1075 | status = U_INTERNAL_PROGRAM_ERROR; | |
1076 | DecimalFormat df(pattern, new DecimalFormatSymbols(symbols), pe, status); | |
1077 | assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status); | |
1078 | } | |
1079 | { | |
1080 | status = U_INTERNAL_PROGRAM_ERROR; | |
1081 | DecimalFormat df(pattern, symbols ,status); | |
1082 | assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status); | |
1083 | } | |
1084 | ||
1085 | // Try each DecimalFormat method with an error code parameter, verifying that | |
3d1f044b | 1086 | // an input error is not altered, and that no segmentation faults occur. |
0f5d89e8 A |
1087 | |
1088 | status = U_INTERNAL_PROGRAM_ERROR; | |
1089 | DecimalFormat dfBogus(status); | |
1090 | assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status); | |
1091 | ||
1092 | status = U_ZERO_ERROR; | |
1093 | DecimalFormat dfGood(pattern, new DecimalFormatSymbols(symbols), status); | |
1094 | assertSuccess(WHERE, status); | |
1095 | ||
1096 | for (DecimalFormat *df: {&dfBogus, &dfGood}) { | |
1097 | status = U_INTERNAL_PROGRAM_ERROR; | |
1098 | df->setAttribute(UNUM_PARSE_INT_ONLY, 0, status); | |
1099 | assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status); | |
1100 | ||
1101 | status = U_INTERNAL_PROGRAM_ERROR; | |
1102 | df->getAttribute(UNUM_MAX_FRACTION_DIGITS, status); | |
1103 | assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status); | |
1104 | ||
3d1f044b | 1105 | status = U_INTERNAL_PROGRAM_ERROR; |
0f5d89e8 A |
1106 | UnicodeString dest; |
1107 | FieldPosition fp; | |
3d1f044b A |
1108 | df->format(1.2, dest, fp, status); |
1109 | assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status); | |
1110 | ||
1111 | status = U_INTERNAL_PROGRAM_ERROR; | |
1112 | df->format(1.2, dest, nullptr, status); | |
1113 | assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status); | |
1114 | ||
1115 | status = U_INTERNAL_PROGRAM_ERROR; | |
1116 | df->format((int32_t)666, dest, nullptr, status); | |
1117 | assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status); | |
1118 | ||
1119 | status = U_INTERNAL_PROGRAM_ERROR; | |
1120 | df->format((int64_t)666, dest, nullptr, status); | |
1121 | assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status); | |
1122 | ||
1123 | status = U_INTERNAL_PROGRAM_ERROR; | |
1124 | df->format(StringPiece("3.1415926535897932384626"), dest, nullptr, status); | |
1125 | assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status); | |
1126 | ||
1127 | status = U_INTERNAL_PROGRAM_ERROR; | |
1128 | df->applyPattern(pattern, status); | |
1129 | assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status); | |
1130 | ||
1131 | status = U_INTERNAL_PROGRAM_ERROR; | |
1132 | df->applyLocalizedPattern(pattern, pe, status); | |
1133 | assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status); | |
0f5d89e8 A |
1134 | |
1135 | status = U_INTERNAL_PROGRAM_ERROR; | |
1136 | df->applyLocalizedPattern(pattern, status); | |
1137 | assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status); | |
1138 | ||
1139 | status = U_INTERNAL_PROGRAM_ERROR; | |
1140 | df->setCurrency(u"USD", status); | |
1141 | assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status); | |
1142 | ||
1143 | status = U_INTERNAL_PROGRAM_ERROR; | |
1144 | df->setCurrencyUsage(UCURR_USAGE_CASH, &status); | |
1145 | assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status); | |
1146 | } | |
1147 | } | |
1148 | ||
3d1f044b A |
1149 | void IntlTestDecimalFormatAPI::testInvalidObject() { |
1150 | { | |
1151 | UErrorCode status = U_INTERNAL_PROGRAM_ERROR; | |
1152 | DecimalFormat dfBogus(status); | |
1153 | assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status); | |
1154 | ||
1155 | status = U_ZERO_ERROR; | |
1156 | DecimalFormat dfGood(status); | |
1157 | assertSuccess(WHERE, status); | |
1158 | ||
1159 | // An invalid object should not be equal to a valid object. | |
1160 | // This also tests that no segmentation fault occurs in the comparison operator due | |
1161 | // to any dangling/nullptr pointers. (ICU-20381). | |
1162 | assertTrue(WHERE, dfGood != dfBogus); | |
1163 | ||
1164 | status = U_MEMORY_ALLOCATION_ERROR; | |
1165 | DecimalFormat dfBogus2(status); | |
1166 | assertEquals(WHERE, U_MEMORY_ALLOCATION_ERROR, status); | |
1167 | ||
1168 | // Two invalid objects should not be equal. | |
1169 | // (Also verify that nullptr isn't t dereferenced in the comparision operator.) | |
1170 | assertTrue(WHERE, dfBogus != dfBogus2); | |
1171 | ||
1172 | // Verify the comparison operator works for two valid objects. | |
1173 | status = U_ZERO_ERROR; | |
1174 | DecimalFormat dfGood2(status); | |
1175 | assertSuccess(WHERE, status); | |
1176 | assertTrue(WHERE, dfGood == dfGood2); | |
1177 | ||
1178 | // Verify that the assignment operator sets the object to an invalid state, and | |
1179 | // that no segmentation fault occurs due to any dangling/nullptr pointers. | |
1180 | status = U_INTERNAL_PROGRAM_ERROR; | |
1181 | DecimalFormat dfAssignmentBogus = DecimalFormat(status); | |
1182 | // Verify comparison for the assigned object. | |
1183 | assertTrue(WHERE, dfAssignmentBogus != dfGood); | |
1184 | assertTrue(WHERE, dfAssignmentBogus != dfGood2); | |
1185 | assertTrue(WHERE, dfAssignmentBogus != dfBogus); | |
1186 | ||
1187 | // Verify that cloning our original invalid object gives nullptr. | |
1188 | auto dfBogusClone = dfBogus.clone(); | |
1189 | assertTrue(WHERE, dfBogusClone == nullptr); | |
1190 | // Verify that cloning our assigned invalid object gives nullptr. | |
1191 | auto dfBogusClone2 = dfAssignmentBogus.clone(); | |
1192 | assertTrue(WHERE, dfBogusClone2 == nullptr); | |
1193 | ||
1194 | // Verify copy constructing from an invalid object is also invalid. | |
1195 | DecimalFormat dfCopy(dfBogus); | |
1196 | assertTrue(WHERE, dfCopy != dfGood); | |
1197 | assertTrue(WHERE, dfCopy != dfGood2); | |
1198 | assertTrue(WHERE, dfCopy != dfBogus); | |
1199 | DecimalFormat dfCopyAssign = dfBogus; | |
1200 | assertTrue(WHERE, dfCopyAssign != dfGood); | |
1201 | assertTrue(WHERE, dfCopyAssign != dfGood2); | |
1202 | assertTrue(WHERE, dfCopyAssign != dfBogus); | |
1203 | auto dfBogusCopyClone1 = dfCopy.clone(); | |
1204 | auto dfBogusCopyClone2 = dfCopyAssign.clone(); | |
1205 | assertTrue(WHERE, dfBogusCopyClone1 == nullptr); | |
1206 | assertTrue(WHERE, dfBogusCopyClone2 == nullptr); | |
1207 | } | |
1208 | ||
1209 | { | |
1210 | // Try each DecimalFormat class method that lacks an error code parameter, verifying | |
1211 | // we don't crash (segmentation fault) on invalid objects. | |
1212 | ||
1213 | UErrorCode status = U_ZERO_ERROR; | |
1214 | const UnicodeString pattern(u"0.###E0"); | |
1215 | UParseError pe; | |
1216 | DecimalFormatSymbols symbols(Locale::getUS(), status); | |
1217 | assertSuccess(WHERE, status); | |
1218 | CurrencyPluralInfo currencyPI(status); | |
1219 | assertSuccess(WHERE, status); | |
1220 | ||
1221 | status = U_INTERNAL_PROGRAM_ERROR; | |
1222 | DecimalFormat dfBogus1(status); | |
1223 | assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status); | |
1224 | ||
1225 | status = U_INTERNAL_PROGRAM_ERROR; | |
1226 | DecimalFormat dfBogus2(pattern, status); | |
1227 | assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status); | |
1228 | ||
1229 | status = U_INTERNAL_PROGRAM_ERROR; | |
1230 | DecimalFormat dfBogus3(pattern, new DecimalFormatSymbols(symbols), status); | |
1231 | assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status); | |
1232 | ||
1233 | status = U_INTERNAL_PROGRAM_ERROR; | |
1234 | DecimalFormat dfBogus4(pattern, new DecimalFormatSymbols(symbols), UNumberFormatStyle::UNUM_CURRENCY, status); | |
1235 | assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status); | |
1236 | ||
1237 | status = U_INTERNAL_PROGRAM_ERROR; | |
1238 | DecimalFormat dfBogus5(pattern, new DecimalFormatSymbols(symbols), pe, status); | |
1239 | assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status); | |
1240 | ||
1241 | for (DecimalFormat *df : {&dfBogus1, &dfBogus2, &dfBogus3, &dfBogus4, &dfBogus5}) | |
1242 | { | |
1243 | df->setGroupingUsed(true); | |
1244 | ||
1245 | df->setParseIntegerOnly(false); | |
1246 | ||
1247 | df->setLenient(true); | |
1248 | ||
1249 | auto dfClone = df->clone(); | |
1250 | assertTrue(WHERE, dfClone == nullptr); | |
1251 | ||
1252 | UnicodeString dest; | |
1253 | FieldPosition fp; | |
1254 | df->format(1.2, dest, fp); | |
1255 | df->format(static_cast<int32_t>(1234), dest, fp); | |
1256 | df->format(static_cast<int64_t>(1234), dest, fp); | |
1257 | ||
1258 | UnicodeString text("-1,234.00"); | |
1259 | Formattable result; | |
1260 | ParsePosition pos(0); | |
1261 | df->parse(text, result, pos); | |
1262 | ||
1263 | CurrencyAmount* ca = df->parseCurrency(text, pos); | |
1264 | assertTrue(WHERE, ca == nullptr); | |
1265 | ||
1266 | const DecimalFormatSymbols* dfs = df->getDecimalFormatSymbols(); | |
1267 | assertTrue(WHERE, dfs == nullptr); | |
1268 | ||
1269 | df->adoptDecimalFormatSymbols(nullptr); | |
1270 | ||
1271 | df->setDecimalFormatSymbols(symbols); | |
1272 | ||
1273 | const CurrencyPluralInfo* cpi = df->getCurrencyPluralInfo(); | |
1274 | assertTrue(WHERE, cpi == nullptr); | |
1275 | ||
1276 | df->adoptCurrencyPluralInfo(nullptr); | |
1277 | ||
1278 | df->setCurrencyPluralInfo(currencyPI); | |
1279 | ||
1280 | UnicodeString prefix("-123"); | |
1281 | df->getPositivePrefix(dest); | |
1282 | df->setPositivePrefix(prefix); | |
1283 | df->getNegativePrefix(dest); | |
1284 | df->setNegativePrefix(prefix); | |
1285 | df->getPositiveSuffix(dest); | |
1286 | df->setPositiveSuffix(prefix); | |
1287 | df->getNegativeSuffix(dest); | |
1288 | df->setNegativeSuffix(prefix); | |
1289 | ||
1290 | df->isSignAlwaysShown(); | |
1291 | ||
1292 | df->setSignAlwaysShown(true); | |
1293 | ||
1294 | df->getMultiplier(); | |
1295 | df->setMultiplier(10); | |
1296 | ||
1297 | df->getMultiplierScale(); | |
1298 | df->setMultiplierScale(2); | |
1299 | ||
1300 | df->getRoundingIncrement(); | |
1301 | df->setRoundingIncrement(1.2); | |
1302 | ||
1303 | df->getRoundingMode(); | |
1304 | df->setRoundingMode(DecimalFormat::ERoundingMode::kRoundDown); | |
1305 | ||
1306 | df->getFormatWidth(); | |
1307 | df->setFormatWidth(0); | |
1308 | ||
1309 | UnicodeString pad(" "); | |
1310 | df->getPadCharacterString(); | |
1311 | df->setPadCharacter(pad); | |
1312 | ||
1313 | df->getPadPosition(); | |
1314 | df->setPadPosition(DecimalFormat::EPadPosition::kPadBeforePrefix); | |
1315 | ||
1316 | df->isScientificNotation(); | |
1317 | df->setScientificNotation(false); | |
1318 | ||
1319 | df->getMinimumExponentDigits(); | |
1320 | df->setMinimumExponentDigits(1); | |
1321 | ||
1322 | df->isExponentSignAlwaysShown(); | |
1323 | df->setExponentSignAlwaysShown(true); | |
1324 | ||
1325 | df->getGroupingSize(); | |
1326 | df->setGroupingSize(3); | |
1327 | ||
1328 | df->getSecondaryGroupingSize(); | |
1329 | df->setSecondaryGroupingSize(-1); | |
1330 | ||
1331 | df->getMinimumGroupingDigits(); | |
1332 | df->setMinimumGroupingDigits(-1); | |
1333 | ||
1334 | df->isDecimalSeparatorAlwaysShown(); | |
1335 | df->setDecimalSeparatorAlwaysShown(true); | |
1336 | ||
1337 | df->isDecimalPatternMatchRequired(); | |
1338 | df->setDecimalPatternMatchRequired(false); | |
1339 | ||
1340 | df->isParseNoExponent(); | |
1341 | df->setParseNoExponent(true); | |
1342 | ||
1343 | df->isParseCaseSensitive(); | |
1344 | df->setParseCaseSensitive(false); | |
1345 | ||
1346 | df->isFormatFailIfMoreThanMaxDigits(); | |
1347 | df->setFormatFailIfMoreThanMaxDigits(true); | |
1348 | ||
1349 | df->toPattern(dest); | |
1350 | df->toLocalizedPattern(dest); | |
1351 | ||
1352 | df->setMaximumIntegerDigits(10); | |
1353 | df->setMinimumIntegerDigits(0); | |
1354 | ||
1355 | df->setMaximumFractionDigits(2); | |
1356 | df->setMinimumFractionDigits(0); | |
1357 | ||
1358 | df->getMinimumSignificantDigits(); | |
1359 | df->setMinimumSignificantDigits(0); | |
1360 | ||
1361 | df->getMaximumSignificantDigits(); | |
1362 | df->setMaximumSignificantDigits(5); | |
1363 | ||
1364 | df->areSignificantDigitsUsed(); | |
1365 | df->setSignificantDigitsUsed(true); | |
1366 | ||
1367 | df->setCurrency(u"USD"); | |
1368 | ||
1369 | df->getCurrencyUsage(); | |
1370 | ||
1371 | const number::LocalizedNumberFormatter* lnf = df->toNumberFormatter(status); | |
1372 | assertEquals("toNumberFormatter should return nullptr", | |
1373 | (int64_t) nullptr, (int64_t) lnf); | |
1374 | ||
1375 | // Should not crash when chaining to error code enabled methods on the LNF | |
1376 | lnf->formatInt(1, status); | |
1377 | lnf->formatDouble(1.0, status); | |
1378 | lnf->formatDecimal("1", status); | |
1379 | lnf->toFormat(status); | |
1380 | lnf->toSkeleton(status); | |
1381 | lnf->copyErrorTo(status); | |
1382 | } | |
1383 | ||
1384 | } | |
1385 | } | |
1386 | ||
b75a7d8f | 1387 | #endif /* #if !UCONFIG_NO_FORMATTING */ |