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 25static const UChar kJPY[] = {0x4A, 0x50, 0x59}; 26 27static 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 35static 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 48static UnicodeString format(double d, const NumberFormat &fmt) { 49 UnicodeString result; 50 fmt.format(d, result); 51 fixNonBreakingSpace(result); 52 return result; 53} 54 55class NumberFormatSpecificationTest : public IntlTest { 56public: 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); 68private: 69 void assertPatternFr( 70 const char *expected, double x, const char *pattern, UBool possibleDataError=FALSE); 71 72}; 73 74void 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 91void NumberFormatSpecificationTest::TestBasicPatterns() { 92 assertPatternFr("1 234,57", 1234.567, "#,##0.##", TRUE); 93 assertPatternFr("1234,57", 1234.567, "0.##", TRUE); 94 assertPatternFr("1235", 1234.567, "0", TRUE); 95 assertPatternFr("1 234,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 234,57 \\u20ac", 1234.567, "#,##0.00 \\u00a4", TRUE); 100} 101 102void 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); 110 assertEquals("", "34 567,89", format(1234567.89, *nf), TRUE); 111 assertEquals("", "0 034,56", format(34.56, *nf), TRUE); 112} 113 114void NumberFormatSpecificationTest::TestRounding() { 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 03,60", 104.0, "#,#3.70", TRUE); 125} 126 127void NumberFormatSpecificationTest::TestSignificantDigits() { 128 assertPatternFr("1230", 1234.0, "@@@", TRUE); 129 assertPatternFr("1 234", 1234.0, "@,@@@", TRUE); 130 assertPatternFr("1 235 000", 1234567.0, "@,@@@", TRUE); 131 assertPatternFr("1 234 567", 1234567.0, "@@@@,@@@", TRUE); 132 assertPatternFr("12 34 567,00", 1234567.0, "@@@@,@@,@@@", TRUE); 133 assertPatternFr("12 34 567,0", 1234567.0, "@@@@,@@,@@#", TRUE); 134 assertPatternFr("12 34 567", 1234567.0, "@@@@,@@,@##", TRUE); 135 assertPatternFr("12 34 567", 1234567.001, "@@@@,@@,@##", TRUE); 136 assertPatternFr("12 34 567", 1234567.001, "@@@@,@@,###", TRUE); 137 assertPatternFr("1 200", 1234.0, "#,#@@", TRUE); 138} 139 140void NumberFormatSpecificationTest::TestScientificNotation() { 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); 151 if (!logKnownIssue("11020")) { 152 assertPatternFr("1,25E4", 12301.2, "0.05E0"); 153 } 154 assertPatternFr("170,0E-3", 0.17, "##0.000#E0", TRUE); 155 156} 157 158void NumberFormatSpecificationTest::TestPercent() { 159 assertPatternFr("57,3%", 0.573, "0.0%", TRUE); 160 assertPatternFr("%57,3", 0.573, "%0.0", TRUE); 161 assertPatternFr("p%p57,3", 0.573, "p%p0.0", TRUE); 162 assertPatternFr("p%p0,6", 0.573, "p'%'p0.0", TRUE); 163 assertPatternFr("%3,260", 0.0326, "%@@@@", TRUE); 164 assertPatternFr("%1 540", 15.43, "%#,@@@", TRUE); 165 assertPatternFr("%1 656,4", 16.55, "%#,##4.1", TRUE); 166 assertPatternFr("%16,3E3", 162.55, "%##0.00E0", TRUE); 167} 168 169void NumberFormatSpecificationTest::TestPerMilli() { 170 assertPatternFr("573,0\\u2030", 0.573, "0.0\\u2030", TRUE); 171 assertPatternFr("\\u2030573,0", 0.573, "\\u20300.0", TRUE); 172 assertPatternFr("p\\u2030p573,0", 0.573, "p\\u2030p0.0", TRUE); 173 assertPatternFr("p\\u2030p0,6", 0.573, "p'\\u2030'p0.0", TRUE); 174 assertPatternFr("\\u203032,60", 0.0326, "\\u2030@@@@", TRUE); 175 assertPatternFr("\\u203015 400", 15.43, "\\u2030#,@@@", TRUE); 176 assertPatternFr("\\u203016 551,7", 16.55, "\\u2030#,##4.1", TRUE); 177 assertPatternFr("\\u2030163E3", 162.55, "\\u2030##0.00E0", TRUE); 178} 179 180void NumberFormatSpecificationTest::TestPadding() { 181 assertPatternFr("$***1 234", 1234, "$**####,##0", TRUE); 182 assertPatternFr("xxx$1 234", 1234, "*x$####,##0", TRUE); 183 assertPatternFr("1 234xxx$", 1234, "####,##0*x$", TRUE); 184 assertPatternFr("1 234$xxx", 1234, "####,##0$*x", TRUE); 185 assertPatternFr("ne1 234nx", -1234, "####,##0$*x;ne#n", TRUE); 186 assertPatternFr("n1 234*xx", -1234, "####,##0$*x;n#'*'", TRUE); 187 assertPatternFr("yyyy%432,6", 4.33, "*y%4.2######", TRUE); 188 if (!logKnownIssue("11025")) { 189 assertPatternFr("EUR *433,00", 433.0, "\\u00a4\\u00a4 **####0.00"); 190 assertPatternFr("EUR *433,00", 433.0, "\\u00a4\\u00a4 **#######0"); 191 } 192 { 193 UnicodeString upattern("\\u00a4\\u00a4 **#######0", -1, US_INV); 194 upattern = upattern.unescape(); 195 UErrorCode status = U_ZERO_ERROR; 196 UnicodeString result; 197 DecimalFormat fmt( 198 upattern, new DecimalFormatSymbols("fr", status), status); 199 if (U_FAILURE(status)) { 200 dataerrln("Error creating DecimalFormat - %s", u_errorName(status)); 201 } else { 202 fmt.setCurrency(kJPY); 203 fmt.format(433.22, result); 204 assertSuccess("", status); 205 assertEquals("", "JPY ****433", result, TRUE); 206 } 207 } 208 { 209 UnicodeString upattern( 210 "\\u00a4\\u00a4 **#######0;\\u00a4\\u00a4 (#)", -1, US_INV); 211 upattern = upattern.unescape(); 212 UErrorCode status = U_ZERO_ERROR; 213 UnicodeString result; 214 DecimalFormat fmt( 215 upattern, 216 new DecimalFormatSymbols("en_US", status), 217 status); 218 if (U_FAILURE(status)) { 219 dataerrln("Error creating DecimalFormat - %s", u_errorName(status)); 220 } else { 221 fmt.format(-433.22, result); 222 assertSuccess("", status); 223 assertEquals("", "USD (433.22)", result, TRUE); 224 } 225 } 226 const char *paddedSciPattern = "QU**00.#####E0"; 227 assertPatternFr("QU***43,3E-1", 4.33, paddedSciPattern, TRUE); 228 { 229 UErrorCode status = U_ZERO_ERROR; 230 DecimalFormatSymbols *sym = new DecimalFormatSymbols("fr", status); 231 sym->setSymbol(DecimalFormatSymbols::kExponentialSymbol, "EE"); 232 DecimalFormat fmt( 233 paddedSciPattern, 234 sym, 235 status); 236 if (U_FAILURE(status)) { 237 dataerrln("Error creating DecimalFormat - %s", u_errorName(status)); 238 } else { 239 UnicodeString result; 240 fmt.format(4.33, result); 241 assertSuccess("", status); 242 assertEquals("", "QU**43,3EE-1", result, TRUE); 243 } 244 } 245 // padding cannot work as intended with scientific notation. 246 assertPatternFr("QU**43,32E-1", 4.332, paddedSciPattern, TRUE); 247} 248 249void NumberFormatSpecificationTest::assertPatternFr( 250 const char *expected, 251 double x, 252 const char *pattern, 253 UBool possibleDataError) { 254 UnicodeString upattern(pattern, -1, US_INV); 255 UnicodeString uexpected(expected, -1, US_INV); 256 upattern = upattern.unescape(); 257 uexpected = uexpected.unescape(); 258 UErrorCode status = U_ZERO_ERROR; 259 UnicodeString result; 260 DecimalFormat fmt( 261 upattern, new DecimalFormatSymbols("fr_FR", status), status); 262 if (U_FAILURE(status)) { 263 dataerrln("Error creating DecimalFormatSymbols - %s", u_errorName(status)); 264 return; 265 } 266 fmt.format(x, result); 267 fixNonBreakingSpace(result); 268 assertSuccess("", status); 269 assertEquals("", uexpected, result, possibleDataError); 270} 271 272extern IntlTest *createNumberFormatSpecificationTest() { 273 return new NumberFormatSpecificationTest(); 274} 275 276#endif 277