Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 1 | // © 2016 and later: Unicode, Inc. and others. |
| 2 | // License & terms of use: http://www.unicode.org/copyright.html |
| 3 | /* |
| 4 | ******************************************************************************* |
| 5 | * Copyright (C) 2014-2015, International Business Machines Corporation and * |
| 6 | * others. All Rights Reserved. * |
| 7 | ******************************************************************************* |
| 8 | * |
| 9 | * File numfmtspectest.cpp |
| 10 | * |
| 11 | ******************************************************************************* |
| 12 | */ |
| 13 | #include <stdio.h> |
| 14 | #include <stdlib.h> |
| 15 | |
| 16 | #include "intltest.h" |
| 17 | |
| 18 | #if !UCONFIG_NO_FORMATTING |
| 19 | |
| 20 | #include "unicode/localpointer.h" |
| 21 | #include "unicode/decimfmt.h" |
| 22 | #include "unicode/dtfmtsym.h" |
| 23 | #include "uassert.h" |
| 24 | |
| 25 | static const UChar kJPY[] = {0x4A, 0x50, 0x59}; |
| 26 | |
| 27 | static void fixNonBreakingSpace(UnicodeString &str) { |
| 28 | for (int32_t i = 0; i < str.length(); ++i) { |
| 29 | if (str[i] == 0xa0) { |
| 30 | str.setCharAt(i, 0x20); |
| 31 | } |
| 32 | } |
| 33 | } |
| 34 | |
| 35 | static NumberFormat *nfWithPattern(const char *pattern) { |
| 36 | UnicodeString upattern(pattern, -1, US_INV); |
| 37 | upattern = upattern.unescape(); |
| 38 | UErrorCode status = U_ZERO_ERROR; |
| 39 | DecimalFormat *result = new DecimalFormat( |
| 40 | upattern, new DecimalFormatSymbols("fr", status), status); |
| 41 | if (U_FAILURE(status)) { |
| 42 | return NULL; |
| 43 | } |
| 44 | |
| 45 | return result; |
| 46 | } |
| 47 | |
| 48 | static UnicodeString format(double d, const NumberFormat &fmt) { |
| 49 | UnicodeString result; |
| 50 | fmt.format(d, result); |
| 51 | fixNonBreakingSpace(result); |
| 52 | return result; |
| 53 | } |
| 54 | |
| 55 | class NumberFormatSpecificationTest : public IntlTest { |
| 56 | public: |
| 57 | NumberFormatSpecificationTest() { |
| 58 | } |
| 59 | void TestBasicPatterns(); |
| 60 | void TestNfSetters(); |
| 61 | void TestRounding(); |
| 62 | void TestSignificantDigits(); |
| 63 | void TestScientificNotation(); |
| 64 | void TestPercent(); |
| 65 | void TestPerMilli(); |
| 66 | void TestPadding(); |
| 67 | void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par=0) override; |
| 68 | private: |
| 69 | void assertPatternFr( |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 70 | const char *expected, double x, const char *pattern, UBool possibleDataError=false); |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 71 | |
| 72 | }; |
| 73 | |
| 74 | void NumberFormatSpecificationTest::runIndexedTest( |
| 75 | int32_t index, UBool exec, const char *&name, char *) { |
| 76 | if (exec) { |
| 77 | logln("TestSuite NumberFormatSpecificationTest: "); |
| 78 | } |
| 79 | TESTCASE_AUTO_BEGIN; |
| 80 | TESTCASE_AUTO(TestBasicPatterns); |
| 81 | TESTCASE_AUTO(TestNfSetters); |
| 82 | TESTCASE_AUTO(TestRounding); |
| 83 | TESTCASE_AUTO(TestSignificantDigits); |
| 84 | TESTCASE_AUTO(TestScientificNotation); |
| 85 | TESTCASE_AUTO(TestPercent); |
| 86 | TESTCASE_AUTO(TestPerMilli); |
| 87 | TESTCASE_AUTO(TestPadding); |
| 88 | TESTCASE_AUTO_END; |
| 89 | } |
| 90 | |
| 91 | void NumberFormatSpecificationTest::TestBasicPatterns() { |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 92 | assertPatternFr("1\\u202F234,57", 1234.567, "#,##0.##", true); |
| 93 | assertPatternFr("1234,57", 1234.567, "0.##", true); |
| 94 | assertPatternFr("1235", 1234.567, "0", true); |
| 95 | assertPatternFr("1\\u202F234,567", 1234.567, "#,##0.###", true); |
| 96 | assertPatternFr("1234,567", 1234.567, "###0.#####", true); |
| 97 | assertPatternFr("1234,5670", 1234.567, "###0.0000#", true); |
| 98 | assertPatternFr("01234,5670", 1234.567, "00000.0000", true); |
| 99 | assertPatternFr("1\\u202F234,57 \\u20ac", 1234.567, "#,##0.00 \\u00a4", true); |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 100 | } |
| 101 | |
| 102 | void NumberFormatSpecificationTest::TestNfSetters() { |
| 103 | LocalPointer<NumberFormat> nf(nfWithPattern("#,##0.##")); |
| 104 | if (nf == NULL) { |
| 105 | dataerrln("Error creating NumberFormat"); |
| 106 | return; |
| 107 | } |
| 108 | nf->setMaximumIntegerDigits(5); |
| 109 | nf->setMinimumIntegerDigits(4); |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 110 | assertEquals("", u"34\u202F567,89", format(1234567.89, *nf), true); |
| 111 | assertEquals("", u"0\u202F034,56", format(34.56, *nf), true); |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 112 | } |
| 113 | |
| 114 | void NumberFormatSpecificationTest::TestRounding() { |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 115 | assertPatternFr("1,0", 1.25, "0.5", true); |
| 116 | assertPatternFr("2,0", 1.75, "0.5", true); |
| 117 | assertPatternFr("-1,0", -1.25, "0.5", true); |
| 118 | assertPatternFr("-02,0", -1.75, "00.5", true); |
| 119 | assertPatternFr("0", 2.0, "4", true); |
| 120 | assertPatternFr("8", 6.0, "4", true); |
| 121 | assertPatternFr("8", 10.0, "4", true); |
| 122 | assertPatternFr("99,90", 99.0, "2.70", true); |
| 123 | assertPatternFr("273,00", 272.0, "2.73", true); |
| 124 | assertPatternFr("1\\u202F03,60", 104.0, "#,#3.70", true); |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 125 | } |
| 126 | |
| 127 | void NumberFormatSpecificationTest::TestSignificantDigits() { |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 128 | assertPatternFr("1230", 1234.0, "@@@", true); |
| 129 | assertPatternFr("1\\u202F234", 1234.0, "@,@@@", true); |
| 130 | assertPatternFr("1\\u202F235\\u202F000", 1234567.0, "@,@@@", true); |
| 131 | assertPatternFr("1\\u202F234\\u202F567", 1234567.0, "@@@@,@@@", true); |
| 132 | assertPatternFr("12\\u202F34\\u202F567,00", 1234567.0, "@@@@,@@,@@@", true); |
| 133 | assertPatternFr("12\\u202F34\\u202F567,0", 1234567.0, "@@@@,@@,@@#", true); |
| 134 | assertPatternFr("12\\u202F34\\u202F567", 1234567.0, "@@@@,@@,@##", true); |
| 135 | assertPatternFr("12\\u202F34\\u202F567", 1234567.001, "@@@@,@@,@##", true); |
| 136 | assertPatternFr("12\\u202F34\\u202F567", 1234567.001, "@@@@,@@,###", true); |
| 137 | assertPatternFr("1\\u202F200", 1234.0, "#,#@@", true); |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 138 | } |
| 139 | |
| 140 | void NumberFormatSpecificationTest::TestScientificNotation() { |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 141 | assertPatternFr("1,23E4", 12345.0, "0.00E0", true); |
| 142 | assertPatternFr("123,00E2", 12300.0, "000.00E0", true); |
| 143 | assertPatternFr("123,0E2", 12300.0, "000.0#E0", true); |
| 144 | assertPatternFr("123,0E2", 12300.1, "000.0#E0", true); |
| 145 | assertPatternFr("123,01E2", 12301.0, "000.0#E0", true); |
| 146 | assertPatternFr("123,01E+02", 12301.0, "000.0#E+00", true); |
| 147 | assertPatternFr("12,3E3", 12345.0, "##0.00E0", true); |
| 148 | assertPatternFr("12,300E3", 12300.1, "##0.0000E0", true); |
| 149 | assertPatternFr("12,30E3", 12300.1, "##0.000#E0", true); |
| 150 | assertPatternFr("12,301E3", 12301.0, "##0.000#E0", true); |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 151 | assertPatternFr("1,25E4", 12301.2, "0.05E0"); |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 152 | assertPatternFr("170,0E-3", 0.17, "##0.000#E0", true); |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 153 | |
| 154 | } |
| 155 | |
| 156 | void NumberFormatSpecificationTest::TestPercent() { |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 157 | assertPatternFr("57,3%", 0.573, "0.0%", true); |
| 158 | assertPatternFr("%57,3", 0.573, "%0.0", true); |
| 159 | assertPatternFr("p%p57,3", 0.573, "p%p0.0", true); |
| 160 | assertPatternFr("p%p0,6", 0.573, "p'%'p0.0", true); |
| 161 | assertPatternFr("%3,260", 0.0326, "%@@@@", true); |
| 162 | assertPatternFr("%1\\u202F540", 15.43, "%#,@@@", true); |
| 163 | assertPatternFr("%1\\u202F656,4", 16.55, "%#,##4.1", true); |
| 164 | assertPatternFr("%16,3E3", 162.55, "%##0.00E0", true); |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 165 | } |
| 166 | |
| 167 | void NumberFormatSpecificationTest::TestPerMilli() { |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 168 | assertPatternFr("573,0\\u2030", 0.573, "0.0\\u2030", true); |
| 169 | assertPatternFr("\\u2030573,0", 0.573, "\\u20300.0", true); |
| 170 | assertPatternFr("p\\u2030p573,0", 0.573, "p\\u2030p0.0", true); |
| 171 | assertPatternFr("p\\u2030p0,6", 0.573, "p'\\u2030'p0.0", true); |
| 172 | assertPatternFr("\\u203032,60", 0.0326, "\\u2030@@@@", true); |
| 173 | assertPatternFr("\\u203015\\u202F400", 15.43, "\\u2030#,@@@", true); |
| 174 | assertPatternFr("\\u203016\\u202F551,7", 16.55, "\\u2030#,##4.1", true); |
| 175 | assertPatternFr("\\u2030163E3", 162.55, "\\u2030##0.00E0", true); |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 176 | } |
| 177 | |
| 178 | void NumberFormatSpecificationTest::TestPadding() { |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 179 | assertPatternFr("$***1\\u202F234", 1234, "$**####,##0", true); |
| 180 | assertPatternFr("xxx$1\\u202F234", 1234, "*x$####,##0", true); |
| 181 | assertPatternFr("1\\u202F234xxx$", 1234, "####,##0*x$", true); |
| 182 | assertPatternFr("1\\u202F234$xxx", 1234, "####,##0$*x", true); |
| 183 | assertPatternFr("ne1\\u202F234nx", -1234, "####,##0$*x;ne#n", true); |
| 184 | assertPatternFr("n1\\u202F234*xx", -1234, "####,##0$*x;n#'*'", true); |
| 185 | assertPatternFr("yyyy%432,6", 4.33, "*y%4.2######", true); |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 186 | assertPatternFr("EUR *433,00", 433.0, "\\u00a4\\u00a4 **####0.00"); |
| 187 | assertPatternFr("EUR *433,00", 433.0, "\\u00a4\\u00a4 **#######0"); |
| 188 | { |
| 189 | UnicodeString upattern("\\u00a4\\u00a4 **#######0", -1, US_INV); |
| 190 | upattern = upattern.unescape(); |
| 191 | UErrorCode status = U_ZERO_ERROR; |
| 192 | UnicodeString result; |
| 193 | DecimalFormat fmt( |
| 194 | upattern, new DecimalFormatSymbols("fr", status), status); |
| 195 | if (U_FAILURE(status)) { |
| 196 | dataerrln("Error creating DecimalFormat - %s", u_errorName(status)); |
| 197 | } else { |
| 198 | fmt.setCurrency(kJPY); |
| 199 | fmt.format(433.22, result); |
| 200 | assertSuccess("", status); |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 201 | assertEquals("", "JPY ****433", result, true); |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 202 | } |
| 203 | } |
| 204 | { |
| 205 | UnicodeString upattern( |
| 206 | "\\u00a4\\u00a4 **#######0;\\u00a4\\u00a4 (#)", -1, US_INV); |
| 207 | upattern = upattern.unescape(); |
| 208 | UErrorCode status = U_ZERO_ERROR; |
| 209 | UnicodeString result; |
| 210 | DecimalFormat fmt( |
| 211 | upattern, |
| 212 | new DecimalFormatSymbols("en_US", status), |
| 213 | status); |
| 214 | if (U_FAILURE(status)) { |
| 215 | dataerrln("Error creating DecimalFormat - %s", u_errorName(status)); |
| 216 | } else { |
| 217 | fmt.format(-433.22, result); |
| 218 | assertSuccess("", status); |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 219 | assertEquals("", "USD (433.22)", result, true); |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 220 | } |
| 221 | } |
| 222 | const char *paddedSciPattern = "QU**00.#####E0"; |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 223 | assertPatternFr("QU***43,3E-1", 4.33, paddedSciPattern, true); |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 224 | { |
| 225 | UErrorCode status = U_ZERO_ERROR; |
| 226 | DecimalFormatSymbols *sym = new DecimalFormatSymbols("fr", status); |
| 227 | sym->setSymbol(DecimalFormatSymbols::kExponentialSymbol, "EE"); |
| 228 | DecimalFormat fmt( |
| 229 | paddedSciPattern, |
| 230 | sym, |
| 231 | status); |
| 232 | if (U_FAILURE(status)) { |
| 233 | dataerrln("Error creating DecimalFormat - %s", u_errorName(status)); |
| 234 | } else { |
| 235 | UnicodeString result; |
| 236 | fmt.format(4.33, result); |
| 237 | assertSuccess("", status); |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 238 | assertEquals("", "QU**43,3EE-1", result, true); |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 239 | } |
| 240 | } |
| 241 | // padding cannot work as intended with scientific notation. |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 242 | assertPatternFr("QU**43,32E-1", 4.332, paddedSciPattern, true); |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 243 | } |
| 244 | |
| 245 | void NumberFormatSpecificationTest::assertPatternFr( |
| 246 | const char *expected, |
| 247 | double x, |
| 248 | const char *pattern, |
| 249 | UBool possibleDataError) { |
| 250 | UnicodeString upattern(pattern, -1, US_INV); |
| 251 | UnicodeString uexpected(expected, -1, US_INV); |
| 252 | upattern = upattern.unescape(); |
| 253 | uexpected = uexpected.unescape(); |
| 254 | UErrorCode status = U_ZERO_ERROR; |
| 255 | UnicodeString result; |
| 256 | DecimalFormat fmt( |
| 257 | upattern, new DecimalFormatSymbols("fr_FR", status), status); |
| 258 | if (U_FAILURE(status)) { |
| 259 | dataerrln("Error creating DecimalFormatSymbols - %s", u_errorName(status)); |
| 260 | return; |
| 261 | } |
| 262 | fmt.format(x, result); |
| 263 | fixNonBreakingSpace(result); |
| 264 | assertSuccess("", status); |
| 265 | assertEquals("", uexpected, result, possibleDataError); |
| 266 | } |
| 267 | |
| 268 | extern IntlTest *createNumberFormatSpecificationTest() { |
| 269 | return new NumberFormatSpecificationTest(); |
| 270 | } |
| 271 | |
| 272 | #endif |