1// Copyright (C) 2016 and later: Unicode, Inc. and others.
2// License & terms of use: http://www.unicode.org/copyright.html
3/********************************************************************
4 * COPYRIGHT:
5 * Copyright (c) 1997-2013, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 ********************************************************************/
8
9#include "unicode/utypes.h"
10
11#if !UCONFIG_NO_FORMATTING
12
13#include "unicode/dcfmtsym.h"
14#include "unicode/decimfmt.h"
15#include "unicode/unum.h"
16#include "tsdcfmsy.h"
17
18void IntlTestDecimalFormatSymbols::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
19{
20    if (exec) {
21        logln("TestSuite DecimalFormatSymbols:");
22    }
23    TESTCASE_AUTO_BEGIN;
24    TESTCASE_AUTO(testSymbols);
25    TESTCASE_AUTO(testLastResortData);
26    TESTCASE_AUTO_END;
27}
28
29/**
30 * Test the API of DecimalFormatSymbols; primarily a simple get/set set.
31 */
32void IntlTestDecimalFormatSymbols::testSymbols(/* char *par */)
33{
34    UErrorCode status = U_ZERO_ERROR;
35
36    DecimalFormatSymbols fr(Locale::getFrench(), status);
37    if(U_FAILURE(status)) {
38        errcheckln(status, "ERROR: Couldn't create French DecimalFormatSymbols - %s", u_errorName(status));
39        return;
40    }
41
42    status = U_ZERO_ERROR;
43    DecimalFormatSymbols en(Locale::getEnglish(), status);
44    if(U_FAILURE(status)) {
45        errcheckln(status, "ERROR: Couldn't create English DecimalFormatSymbols - %s", u_errorName(status));
46        return;
47    }
48
49    if(en == fr || ! (en != fr) ) {
50        errln("ERROR: English DecimalFormatSymbols equal to French");
51    }
52
53    // just do some VERY basic tests to make sure that get/set work
54
55    UnicodeString zero = en.getSymbol(DecimalFormatSymbols::kZeroDigitSymbol);
56    fr.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, zero);
57    if(fr.getSymbol(DecimalFormatSymbols::kZeroDigitSymbol) != en.getSymbol(DecimalFormatSymbols::kZeroDigitSymbol)) {
58        errln("ERROR: get/set ZeroDigit failed");
59    }
60
61    UnicodeString group = en.getSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol);
62    fr.setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol, group);
63    if(fr.getSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol) != en.getSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol)) {
64        errln("ERROR: get/set GroupingSeparator failed");
65    }
66
67    UnicodeString decimal = en.getSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol);
68    fr.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, decimal);
69    if(fr.getSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol) != en.getSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol)) {
70        errln("ERROR: get/set DecimalSeparator failed");
71    }
72
73    UnicodeString perMill = en.getSymbol(DecimalFormatSymbols::kPerMillSymbol);
74    fr.setSymbol(DecimalFormatSymbols::kPerMillSymbol, perMill);
75    if(fr.getSymbol(DecimalFormatSymbols::kPerMillSymbol) != en.getSymbol(DecimalFormatSymbols::kPerMillSymbol)) {
76        errln("ERROR: get/set PerMill failed");
77    }
78
79    UnicodeString percent = en.getSymbol(DecimalFormatSymbols::kPercentSymbol);
80    fr.setSymbol(DecimalFormatSymbols::kPercentSymbol, percent);
81    if(fr.getSymbol(DecimalFormatSymbols::kPercentSymbol) != en.getSymbol(DecimalFormatSymbols::kPercentSymbol)) {
82        errln("ERROR: get/set Percent failed");
83    }
84
85    UnicodeString digit(en.getSymbol(DecimalFormatSymbols::kDigitSymbol));
86    fr.setSymbol(DecimalFormatSymbols::kDigitSymbol, digit);
87    if(fr.getSymbol(DecimalFormatSymbols::kDigitSymbol) != en.getSymbol(DecimalFormatSymbols::kDigitSymbol)) {
88        errln("ERROR: get/set Percent failed");
89    }
90
91    UnicodeString patternSeparator = en.getSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol);
92    fr.setSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol, patternSeparator);
93    if(fr.getSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol) != en.getSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol)) {
94        errln("ERROR: get/set PatternSeparator failed");
95    }
96
97    UnicodeString infinity(en.getSymbol(DecimalFormatSymbols::kInfinitySymbol));
98    fr.setSymbol(DecimalFormatSymbols::kInfinitySymbol, infinity);
99    UnicodeString infinity2(fr.getSymbol(DecimalFormatSymbols::kInfinitySymbol));
100    if(infinity != infinity2) {
101        errln("ERROR: get/set Infinity failed");
102    }
103
104    UnicodeString nan(en.getSymbol(DecimalFormatSymbols::kNaNSymbol));
105    fr.setSymbol(DecimalFormatSymbols::kNaNSymbol, nan);
106    UnicodeString nan2(fr.getSymbol(DecimalFormatSymbols::kNaNSymbol));
107    if(nan != nan2) {
108        errln("ERROR: get/set NaN failed");
109    }
110
111    UnicodeString minusSign = en.getSymbol(DecimalFormatSymbols::kMinusSignSymbol);
112    fr.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, minusSign);
113    if(fr.getSymbol(DecimalFormatSymbols::kMinusSignSymbol) != en.getSymbol(DecimalFormatSymbols::kMinusSignSymbol)) {
114        errln("ERROR: get/set MinusSign failed");
115    }
116
117    UnicodeString exponential(en.getSymbol(DecimalFormatSymbols::kExponentialSymbol));
118    fr.setSymbol(DecimalFormatSymbols::kExponentialSymbol, exponential);
119    if(fr.getSymbol(DecimalFormatSymbols::kExponentialSymbol) != en.getSymbol(DecimalFormatSymbols::kExponentialSymbol)) {
120        errln("ERROR: get/set Exponential failed");
121    }
122
123    // Test get currency spacing before the currency.
124    status = U_ZERO_ERROR;
125    for (int32_t i = 0; i < (int32_t)UNUM_CURRENCY_SPACING_COUNT; i++) {
126        UnicodeString enCurrencyPattern = en.getPatternForCurrencySpacing(
127             (UCurrencySpacing)i, TRUE, status);
128        if(U_FAILURE(status)) {
129            errln("Error: cannot get CurrencyMatch for locale:en");
130            status = U_ZERO_ERROR;
131        }
132        UnicodeString frCurrencyPattern = fr.getPatternForCurrencySpacing(
133             (UCurrencySpacing)i, TRUE, status);
134        if(U_FAILURE(status)) {
135            errln("Error: cannot get CurrencyMatch for locale:fr");
136        }
137        if (enCurrencyPattern != frCurrencyPattern) {
138           errln("ERROR: get CurrencySpacing failed");
139        }
140    }
141    // Test get currencySpacing after the currency.
142    status = U_ZERO_ERROR;
143    for (int32_t i = 0; i < UNUM_CURRENCY_SPACING_COUNT; i++) {
144        UnicodeString enCurrencyPattern = en.getPatternForCurrencySpacing(
145            (UCurrencySpacing)i, FALSE, status);
146        if(U_FAILURE(status)) {
147            errln("Error: cannot get CurrencyMatch for locale:en");
148            status = U_ZERO_ERROR;
149        }
150        UnicodeString frCurrencyPattern = fr.getPatternForCurrencySpacing(
151             (UCurrencySpacing)i, FALSE, status);
152        if(U_FAILURE(status)) {
153            errln("Error: cannot get CurrencyMatch for locale:fr");
154        }
155        if (enCurrencyPattern != frCurrencyPattern) {
156            errln("ERROR: get CurrencySpacing failed");
157        }
158    }
159    // Test set curerncySpacing APIs
160    status = U_ZERO_ERROR;
161    UnicodeString dash = UnicodeString("-");
162    en.setPatternForCurrencySpacing(UNUM_CURRENCY_INSERT, TRUE, dash);
163    UnicodeString enCurrencyInsert = en.getPatternForCurrencySpacing(
164        UNUM_CURRENCY_INSERT, TRUE, status);
165    if (dash != enCurrencyInsert) {
166        errln("Error: Failed to setCurrencyInsert for locale:en");
167    }
168
169    status = U_ZERO_ERROR;
170    DecimalFormatSymbols foo(status);
171
172    DecimalFormatSymbols bar(foo);
173
174    en = fr;
175
176    if(en != fr || foo != bar) {
177        errln("ERROR: Copy Constructor or Assignment failed");
178    }
179
180    // test get/setSymbol()
181    if((int) UNUM_FORMAT_SYMBOL_COUNT != (int) DecimalFormatSymbols::kFormatSymbolCount) {
182        errln("unum.h and decimfmt.h have inconsistent numbers of format symbols!");
183        return;
184    }
185
186    int i;
187    for(i = 0; i < (int)DecimalFormatSymbols::kFormatSymbolCount; ++i) {
188        foo.setSymbol((DecimalFormatSymbols::ENumberFormatSymbol)i, UnicodeString((UChar32)(0x10330 + i)));
189    }
190    for(i = 0; i < (int)DecimalFormatSymbols::kFormatSymbolCount; ++i) {
191        if(foo.getSymbol((DecimalFormatSymbols::ENumberFormatSymbol)i) != UnicodeString((UChar32)(0x10330 + i))) {
192            errln("get/setSymbol did not roundtrip, got " +
193                  foo.getSymbol((DecimalFormatSymbols::ENumberFormatSymbol)i) +
194                  ", expected " +
195                  UnicodeString((UChar32)(0x10330 + i)));
196        }
197    }
198
199    DecimalFormatSymbols sym(Locale::getUS(), status);
200
201    UnicodeString customDecSeperator("S");
202    Verify(34.5, (UnicodeString)"00.00", sym, (UnicodeString)"34.50");
203    sym.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, customDecSeperator);
204    Verify(34.5, (UnicodeString)"00.00", sym, (UnicodeString)"34S50");
205    sym.setSymbol(DecimalFormatSymbols::kPercentSymbol, (UnicodeString)"P");
206    Verify(34.5, (UnicodeString)"00 %", sym, (UnicodeString)"3450 P");
207    sym.setSymbol(DecimalFormatSymbols::kCurrencySymbol, (UnicodeString)"D");
208    Verify(34.5, CharsToUnicodeString("\\u00a4##.##"), sym, (UnicodeString)"D34.5");
209    sym.setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol, (UnicodeString)"|");
210    Verify(3456.5, (UnicodeString)"0,000.##", sym, (UnicodeString)"3|456S5");
211
212}
213
214void IntlTestDecimalFormatSymbols::testLastResortData() {
215    IcuTestErrorCode errorCode(*this, "testLastResortData");
216    LocalPointer<DecimalFormatSymbols> lastResort(
217        DecimalFormatSymbols::createWithLastResortData(errorCode));
218    if(errorCode.logIfFailureAndReset("DecimalFormatSymbols::createWithLastResortData() failed")) {
219        return;
220    }
221    DecimalFormatSymbols root(Locale::getRoot(), errorCode);
222    if(errorCode.logDataIfFailureAndReset("DecimalFormatSymbols(root) failed")) {
223        return;
224    }
225    // Note: It is not necessary that the last resort data matches the root locale,
226    // but it seems weird if most symbols did not match.
227    // Also, one purpose for calling operator==() is to find uninitialized memory in a debug build.
228    if(*lastResort == root) {
229        errln("DecimalFormatSymbols last resort data unexpectedly matches root");
230    }
231    // Here we adjust for expected differences.
232    assertEquals("last-resort grouping separator",
233                 "", lastResort->getSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol));
234    lastResort->setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol, ",");
235    assertEquals("last-resort monetary grouping separator",
236                 "", lastResort->getSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol));
237    lastResort->setSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol, ",");
238    assertEquals("last-resort NaN",
239                 UnicodeString((UChar)0xfffd), lastResort->getSymbol(DecimalFormatSymbols::kNaNSymbol));
240    lastResort->setSymbol(DecimalFormatSymbols::kNaNSymbol, "NaN");
241    // Check that now all of the symbols match root.
242    for(int32_t i = 0; i < DecimalFormatSymbols::kFormatSymbolCount; ++i) {
243        DecimalFormatSymbols::ENumberFormatSymbol e = (DecimalFormatSymbols::ENumberFormatSymbol)i;
244        assertEquals("last-resort symbol vs. root", root.getSymbol(e), lastResort->getSymbol(e));
245    }
246    // Also, the CurrencySpacing patterns are empty in the last resort instance,
247    // but not in root.
248    Verify(1234567.25, "#,##0.##", *lastResort, "1,234,567.25");
249}
250
251void IntlTestDecimalFormatSymbols::Verify(double value, const UnicodeString& pattern,
252                                          const DecimalFormatSymbols &sym, const UnicodeString& expected){
253    UErrorCode status = U_ZERO_ERROR;
254    DecimalFormat df(pattern, sym, status);
255    if(U_FAILURE(status)){
256        errln("ERROR: construction of decimal format failed - %s", u_errorName(status));
257    }
258    UnicodeString buffer;
259    FieldPosition pos(FieldPosition::DONT_CARE);
260    buffer = df.format(value, buffer, pos);
261    if(buffer != expected){
262        errln((UnicodeString)"ERROR: format() returns wrong result\n Expected " +
263            expected + ", Got " + buffer);
264    }
265}
266
267#endif /* #if !UCONFIG_NO_FORMATTING */
268