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