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