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 
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)16 void 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  */
testSymbols()30 void 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 
testLastResortData()212 void 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 
Verify(double value,const UnicodeString & pattern,const DecimalFormatSymbols & sym,const UnicodeString & expected)249 void 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