• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 char16_t kJPY[] = {0x4A, 0x50, 0x59};
26 
fixNonBreakingSpace(UnicodeString & str)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 
nfWithPattern(const char * pattern)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 nullptr;
43     }
44 
45     return result;
46 }
47 
format(double d,const NumberFormat & fmt)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:
NumberFormatSpecificationTest()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 = nullptr) override;
68 
69 private:
70     void assertPatternFr(
71             const char *expected, double x, const char *pattern, UBool possibleDataError=false);
72 
73 };
74 
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)75 void NumberFormatSpecificationTest::runIndexedTest(
76         int32_t index, UBool exec, const char *&name, char *) {
77     if (exec) {
78         logln("TestSuite NumberFormatSpecificationTest: ");
79     }
80     TESTCASE_AUTO_BEGIN;
81     TESTCASE_AUTO(TestBasicPatterns);
82     TESTCASE_AUTO(TestNfSetters);
83     TESTCASE_AUTO(TestRounding);
84     TESTCASE_AUTO(TestSignificantDigits);
85     TESTCASE_AUTO(TestScientificNotation);
86     TESTCASE_AUTO(TestPercent);
87     TESTCASE_AUTO(TestPerMilli);
88     TESTCASE_AUTO(TestPadding);
89     TESTCASE_AUTO_END;
90 }
91 
TestBasicPatterns()92 void NumberFormatSpecificationTest::TestBasicPatterns() {
93     assertPatternFr("1\\u202F234,57", 1234.567, "#,##0.##", true);
94     assertPatternFr("1234,57", 1234.567, "0.##", true);
95     assertPatternFr("1235", 1234.567, "0", true);
96     assertPatternFr("1\\u202F234,567", 1234.567, "#,##0.###", true);
97     assertPatternFr("1234,567", 1234.567, "###0.#####", true);
98     assertPatternFr("1234,5670", 1234.567, "###0.0000#", true);
99     assertPatternFr("01234,5670", 1234.567, "00000.0000", true);
100     assertPatternFr("1\\u202F234,57 \\u20ac", 1234.567, "#,##0.00 \\u00a4", true);
101 }
102 
TestNfSetters()103 void NumberFormatSpecificationTest::TestNfSetters() {
104     LocalPointer<NumberFormat> nf(nfWithPattern("#,##0.##"));
105     if (nf == nullptr) {
106         dataerrln("Error creating NumberFormat");
107         return;
108     }
109     nf->setMaximumIntegerDigits(5);
110     nf->setMinimumIntegerDigits(4);
111     assertEquals("", u"34\u202F567,89", format(1234567.89, *nf), true);
112     assertEquals("", u"0\u202F034,56", format(34.56, *nf), true);
113 }
114 
TestRounding()115 void NumberFormatSpecificationTest::TestRounding() {
116     assertPatternFr("1,0", 1.25, "0.5", true);
117     assertPatternFr("2,0", 1.75, "0.5", true);
118     assertPatternFr("-1,0", -1.25, "0.5", true);
119     assertPatternFr("-02,0", -1.75, "00.5", true);
120     assertPatternFr("0", 2.0, "4", true);
121     assertPatternFr("8", 6.0, "4", true);
122     assertPatternFr("8", 10.0, "4", true);
123     assertPatternFr("99,90", 99.0, "2.70", true);
124     assertPatternFr("273,00", 272.0, "2.73", true);
125     assertPatternFr("1\\u202F03,60", 104.0, "#,#3.70", true);
126 }
127 
TestSignificantDigits()128 void NumberFormatSpecificationTest::TestSignificantDigits() {
129     assertPatternFr("1230", 1234.0, "@@@", true);
130     assertPatternFr("1\\u202F234", 1234.0, "@,@@@", true);
131     assertPatternFr("1\\u202F235\\u202F000", 1234567.0, "@,@@@", true);
132     assertPatternFr("1\\u202F234\\u202F567", 1234567.0, "@@@@,@@@", true);
133     assertPatternFr("12\\u202F34\\u202F567,00", 1234567.0, "@@@@,@@,@@@", true);
134     assertPatternFr("12\\u202F34\\u202F567,0", 1234567.0, "@@@@,@@,@@#", true);
135     assertPatternFr("12\\u202F34\\u202F567", 1234567.0, "@@@@,@@,@##", true);
136     assertPatternFr("12\\u202F34\\u202F567", 1234567.001, "@@@@,@@,@##", true);
137     assertPatternFr("12\\u202F34\\u202F567", 1234567.001, "@@@@,@@,###", true);
138     assertPatternFr("1\\u202F200", 1234.0, "#,#@@", true);
139 }
140 
TestScientificNotation()141 void NumberFormatSpecificationTest::TestScientificNotation() {
142     assertPatternFr("1,23E4", 12345.0, "0.00E0", true);
143     assertPatternFr("123,00E2", 12300.0, "000.00E0", true);
144     assertPatternFr("123,0E2", 12300.0, "000.0#E0", true);
145     assertPatternFr("123,0E2", 12300.1, "000.0#E0", true);
146     assertPatternFr("123,01E2", 12301.0, "000.0#E0", true);
147     assertPatternFr("123,01E+02", 12301.0, "000.0#E+00", true);
148     assertPatternFr("12,3E3", 12345.0, "##0.00E0", true);
149     assertPatternFr("12,300E3", 12300.1, "##0.0000E0", true);
150     assertPatternFr("12,30E3", 12300.1, "##0.000#E0", true);
151     assertPatternFr("12,301E3", 12301.0, "##0.000#E0", true);
152     assertPatternFr("1,25E4", 12301.2, "0.05E0");
153     assertPatternFr("170,0E-3", 0.17, "##0.000#E0", true);
154 
155 }
156 
TestPercent()157 void NumberFormatSpecificationTest::TestPercent() {
158     assertPatternFr("57,3%", 0.573, "0.0%", true);
159     assertPatternFr("%57,3", 0.573, "%0.0", true);
160     assertPatternFr("p%p57,3", 0.573, "p%p0.0", true);
161     assertPatternFr("p%p0,6", 0.573, "p'%'p0.0", true);
162     assertPatternFr("%3,260", 0.0326, "%@@@@", true);
163     assertPatternFr("%1\\u202F540", 15.43, "%#,@@@", true);
164     assertPatternFr("%1\\u202F656,4", 16.55, "%#,##4.1", true);
165     assertPatternFr("%16,3E3", 162.55, "%##0.00E0", true);
166 }
167 
TestPerMilli()168 void NumberFormatSpecificationTest::TestPerMilli() {
169     assertPatternFr("573,0\\u2030", 0.573, "0.0\\u2030", true);
170     assertPatternFr("\\u2030573,0", 0.573, "\\u20300.0", true);
171     assertPatternFr("p\\u2030p573,0", 0.573, "p\\u2030p0.0", true);
172     assertPatternFr("p\\u2030p0,6", 0.573, "p'\\u2030'p0.0", true);
173     assertPatternFr("\\u203032,60", 0.0326, "\\u2030@@@@", true);
174     assertPatternFr("\\u203015\\u202F400", 15.43, "\\u2030#,@@@", true);
175     assertPatternFr("\\u203016\\u202F551,7", 16.55, "\\u2030#,##4.1", true);
176     assertPatternFr("\\u2030163E3", 162.55, "\\u2030##0.00E0", true);
177 }
178 
TestPadding()179 void NumberFormatSpecificationTest::TestPadding() {
180     assertPatternFr("$***1\\u202F234", 1234, "$**####,##0", true);
181     assertPatternFr("xxx$1\\u202F234", 1234, "*x$####,##0", true);
182     assertPatternFr("1\\u202F234xxx$", 1234, "####,##0*x$", true);
183     assertPatternFr("1\\u202F234$xxx", 1234, "####,##0$*x", true);
184     assertPatternFr("ne1\\u202F234nx", -1234, "####,##0$*x;ne#n", true);
185     assertPatternFr("n1\\u202F234*xx", -1234, "####,##0$*x;n#'*'", true);
186     assertPatternFr("yyyy%432,6", 4.33, "*y%4.2######",  true);
187     assertPatternFr("EUR *433,00", 433.0, "\\u00a4\\u00a4 **####0.00");
188     assertPatternFr("EUR *433,00", 433.0, "\\u00a4\\u00a4 **#######0");
189     {
190         UnicodeString upattern("\\u00a4\\u00a4 **#######0", -1, US_INV);
191         upattern = upattern.unescape();
192         UErrorCode status = U_ZERO_ERROR;
193         UnicodeString result;
194         DecimalFormat fmt(
195                 upattern, new DecimalFormatSymbols("fr", status), status);
196         if (U_FAILURE(status)) {
197             dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
198         } else {
199             fmt.setCurrency(kJPY);
200             fmt.format(433.22, result);
201             assertSuccess("", status);
202             assertEquals("", "JPY ****433", result, true);
203         }
204     }
205     {
206         UnicodeString upattern(
207             "\\u00a4\\u00a4 **#######0;\\u00a4\\u00a4 (#)", -1, US_INV);
208         upattern = upattern.unescape();
209         UErrorCode status = U_ZERO_ERROR;
210         UnicodeString result;
211         DecimalFormat fmt(
212                 upattern,
213                 new DecimalFormatSymbols("en_US", status),
214                 status);
215         if (U_FAILURE(status)) {
216             dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
217         } else {
218             fmt.format(-433.22, result);
219             assertSuccess("", status);
220             assertEquals("", "USD (433.22)", result, true);
221         }
222     }
223     const char *paddedSciPattern = "QU**00.#####E0";
224     assertPatternFr("QU***43,3E-1", 4.33, paddedSciPattern, true);
225     {
226         UErrorCode status = U_ZERO_ERROR;
227         DecimalFormatSymbols *sym = new DecimalFormatSymbols("fr", status);
228         sym->setSymbol(DecimalFormatSymbols::kExponentialSymbol, "EE");
229         DecimalFormat fmt(
230                 paddedSciPattern,
231                 sym,
232                 status);
233         if (U_FAILURE(status)) {
234             dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
235         } else {
236             UnicodeString result;
237             fmt.format(4.33, result);
238             assertSuccess("", status);
239             assertEquals("", "QU**43,3EE-1", result, true);
240         }
241     }
242     // padding cannot work as intended with scientific notation.
243     assertPatternFr("QU**43,32E-1", 4.332, paddedSciPattern, true);
244 }
245 
assertPatternFr(const char * expected,double x,const char * pattern,UBool possibleDataError)246 void NumberFormatSpecificationTest::assertPatternFr(
247         const char *expected,
248         double x,
249         const char *pattern,
250         UBool possibleDataError) {
251     UnicodeString upattern(pattern, -1, US_INV);
252     UnicodeString uexpected(expected, -1, US_INV);
253     upattern = upattern.unescape();
254     uexpected = uexpected.unescape();
255     UErrorCode status = U_ZERO_ERROR;
256     UnicodeString result;
257     DecimalFormat fmt(
258             upattern, new DecimalFormatSymbols("fr_FR", status), status);
259     if (U_FAILURE(status)) {
260         dataerrln("Error creating DecimalFormatSymbols - %s", u_errorName(status));
261         return;
262     }
263     fmt.format(x, result);
264     fixNonBreakingSpace(result);
265     assertSuccess("", status);
266     assertEquals("", uexpected, result, possibleDataError);
267 }
268 
createNumberFormatSpecificationTest()269 extern IntlTest *createNumberFormatSpecificationTest() {
270     return new NumberFormatSpecificationTest();
271 }
272 
273 #endif
274