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