e77603e3c3
X-SVN-Rev: 41281
409 lines
17 KiB
C++
409 lines
17 KiB
C++
// © 2016 and later: Unicode, Inc. and others.
|
||
// License & terms of use: http://www.unicode.org/copyright.html
|
||
/********************************************************************
|
||
* COPYRIGHT:
|
||
* Copyright (c) 1997-2013, International Business Machines Corporation and
|
||
* others. All Rights Reserved.
|
||
********************************************************************/
|
||
|
||
#include "unicode/utypes.h"
|
||
|
||
#if !UCONFIG_NO_FORMATTING
|
||
|
||
#include "unicode/dcfmtsym.h"
|
||
#include "unicode/decimfmt.h"
|
||
#include "unicode/unum.h"
|
||
#include "tsdcfmsy.h"
|
||
|
||
void IntlTestDecimalFormatSymbols::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
|
||
{
|
||
if (exec) {
|
||
logln("TestSuite DecimalFormatSymbols:");
|
||
}
|
||
TESTCASE_AUTO_BEGIN;
|
||
TESTCASE_AUTO(testSymbols);
|
||
TESTCASE_AUTO(testLastResortData);
|
||
TESTCASE_AUTO(testDigitSymbols);
|
||
TESTCASE_AUTO(testNumberingSystem);
|
||
TESTCASE_AUTO_END;
|
||
}
|
||
|
||
/**
|
||
* Test the API of DecimalFormatSymbols; primarily a simple get/set set.
|
||
*/
|
||
void IntlTestDecimalFormatSymbols::testSymbols(/* char *par */)
|
||
{
|
||
UErrorCode status = U_ZERO_ERROR;
|
||
|
||
DecimalFormatSymbols fr(Locale::getFrench(), status);
|
||
if(U_FAILURE(status)) {
|
||
errcheckln(status, "ERROR: Couldn't create French DecimalFormatSymbols - %s", u_errorName(status));
|
||
return;
|
||
}
|
||
|
||
status = U_ZERO_ERROR;
|
||
DecimalFormatSymbols en(Locale::getEnglish(), status);
|
||
if(U_FAILURE(status)) {
|
||
errcheckln(status, "ERROR: Couldn't create English DecimalFormatSymbols - %s", u_errorName(status));
|
||
return;
|
||
}
|
||
|
||
if(en == fr || ! (en != fr) ) {
|
||
errln("ERROR: English DecimalFormatSymbols equal to French");
|
||
}
|
||
|
||
// just do some VERY basic tests to make sure that get/set work
|
||
|
||
UnicodeString zero = en.getSymbol(DecimalFormatSymbols::kZeroDigitSymbol);
|
||
fr.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, zero);
|
||
if(fr.getSymbol(DecimalFormatSymbols::kZeroDigitSymbol) != en.getSymbol(DecimalFormatSymbols::kZeroDigitSymbol)) {
|
||
errln("ERROR: get/set ZeroDigit failed");
|
||
}
|
||
|
||
UnicodeString group = en.getSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol);
|
||
fr.setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol, group);
|
||
if(fr.getSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol) != en.getSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol)) {
|
||
errln("ERROR: get/set GroupingSeparator failed");
|
||
}
|
||
|
||
UnicodeString decimal = en.getSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol);
|
||
fr.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, decimal);
|
||
if(fr.getSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol) != en.getSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol)) {
|
||
errln("ERROR: get/set DecimalSeparator failed");
|
||
}
|
||
|
||
UnicodeString perMill = en.getSymbol(DecimalFormatSymbols::kPerMillSymbol);
|
||
fr.setSymbol(DecimalFormatSymbols::kPerMillSymbol, perMill);
|
||
if(fr.getSymbol(DecimalFormatSymbols::kPerMillSymbol) != en.getSymbol(DecimalFormatSymbols::kPerMillSymbol)) {
|
||
errln("ERROR: get/set PerMill failed");
|
||
}
|
||
|
||
UnicodeString percent = en.getSymbol(DecimalFormatSymbols::kPercentSymbol);
|
||
fr.setSymbol(DecimalFormatSymbols::kPercentSymbol, percent);
|
||
if(fr.getSymbol(DecimalFormatSymbols::kPercentSymbol) != en.getSymbol(DecimalFormatSymbols::kPercentSymbol)) {
|
||
errln("ERROR: get/set Percent failed");
|
||
}
|
||
|
||
UnicodeString digit(en.getSymbol(DecimalFormatSymbols::kDigitSymbol));
|
||
fr.setSymbol(DecimalFormatSymbols::kDigitSymbol, digit);
|
||
if(fr.getSymbol(DecimalFormatSymbols::kDigitSymbol) != en.getSymbol(DecimalFormatSymbols::kDigitSymbol)) {
|
||
errln("ERROR: get/set Percent failed");
|
||
}
|
||
|
||
UnicodeString patternSeparator = en.getSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol);
|
||
fr.setSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol, patternSeparator);
|
||
if(fr.getSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol) != en.getSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol)) {
|
||
errln("ERROR: get/set PatternSeparator failed");
|
||
}
|
||
|
||
UnicodeString infinity(en.getSymbol(DecimalFormatSymbols::kInfinitySymbol));
|
||
fr.setSymbol(DecimalFormatSymbols::kInfinitySymbol, infinity);
|
||
UnicodeString infinity2(fr.getSymbol(DecimalFormatSymbols::kInfinitySymbol));
|
||
if(infinity != infinity2) {
|
||
errln("ERROR: get/set Infinity failed");
|
||
}
|
||
|
||
UnicodeString nan(en.getSymbol(DecimalFormatSymbols::kNaNSymbol));
|
||
fr.setSymbol(DecimalFormatSymbols::kNaNSymbol, nan);
|
||
UnicodeString nan2(fr.getSymbol(DecimalFormatSymbols::kNaNSymbol));
|
||
if(nan != nan2) {
|
||
errln("ERROR: get/set NaN failed");
|
||
}
|
||
|
||
UnicodeString minusSign = en.getSymbol(DecimalFormatSymbols::kMinusSignSymbol);
|
||
fr.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, minusSign);
|
||
if(fr.getSymbol(DecimalFormatSymbols::kMinusSignSymbol) != en.getSymbol(DecimalFormatSymbols::kMinusSignSymbol)) {
|
||
errln("ERROR: get/set MinusSign failed");
|
||
}
|
||
|
||
UnicodeString exponential(en.getSymbol(DecimalFormatSymbols::kExponentialSymbol));
|
||
fr.setSymbol(DecimalFormatSymbols::kExponentialSymbol, exponential);
|
||
if(fr.getSymbol(DecimalFormatSymbols::kExponentialSymbol) != en.getSymbol(DecimalFormatSymbols::kExponentialSymbol)) {
|
||
errln("ERROR: get/set Exponential failed");
|
||
}
|
||
|
||
// Test get currency spacing before the currency.
|
||
status = U_ZERO_ERROR;
|
||
for (int32_t i = 0; i < (int32_t)UNUM_CURRENCY_SPACING_COUNT; i++) {
|
||
UnicodeString enCurrencyPattern = en.getPatternForCurrencySpacing(
|
||
(UCurrencySpacing)i, TRUE, status);
|
||
if(U_FAILURE(status)) {
|
||
errln("Error: cannot get CurrencyMatch for locale:en");
|
||
status = U_ZERO_ERROR;
|
||
}
|
||
UnicodeString frCurrencyPattern = fr.getPatternForCurrencySpacing(
|
||
(UCurrencySpacing)i, TRUE, status);
|
||
if(U_FAILURE(status)) {
|
||
errln("Error: cannot get CurrencyMatch for locale:fr");
|
||
}
|
||
if (enCurrencyPattern != frCurrencyPattern) {
|
||
errln("ERROR: get CurrencySpacing failed");
|
||
}
|
||
}
|
||
// Test get currencySpacing after the currency.
|
||
status = U_ZERO_ERROR;
|
||
for (int32_t i = 0; i < UNUM_CURRENCY_SPACING_COUNT; i++) {
|
||
UnicodeString enCurrencyPattern = en.getPatternForCurrencySpacing(
|
||
(UCurrencySpacing)i, FALSE, status);
|
||
if(U_FAILURE(status)) {
|
||
errln("Error: cannot get CurrencyMatch for locale:en");
|
||
status = U_ZERO_ERROR;
|
||
}
|
||
UnicodeString frCurrencyPattern = fr.getPatternForCurrencySpacing(
|
||
(UCurrencySpacing)i, FALSE, status);
|
||
if(U_FAILURE(status)) {
|
||
errln("Error: cannot get CurrencyMatch for locale:fr");
|
||
}
|
||
if (enCurrencyPattern != frCurrencyPattern) {
|
||
errln("ERROR: get CurrencySpacing failed");
|
||
}
|
||
}
|
||
// Test set curerncySpacing APIs
|
||
status = U_ZERO_ERROR;
|
||
UnicodeString dash = UnicodeString("-");
|
||
en.setPatternForCurrencySpacing(UNUM_CURRENCY_INSERT, TRUE, dash);
|
||
UnicodeString enCurrencyInsert = en.getPatternForCurrencySpacing(
|
||
UNUM_CURRENCY_INSERT, TRUE, status);
|
||
if (dash != enCurrencyInsert) {
|
||
errln("Error: Failed to setCurrencyInsert for locale:en");
|
||
}
|
||
|
||
status = U_ZERO_ERROR;
|
||
DecimalFormatSymbols foo(status);
|
||
|
||
DecimalFormatSymbols bar(foo);
|
||
|
||
en = fr;
|
||
|
||
if(en != fr || foo != bar) {
|
||
errln("ERROR: Copy Constructor or Assignment failed");
|
||
}
|
||
|
||
// test get/setSymbol()
|
||
if((int) UNUM_FORMAT_SYMBOL_COUNT != (int) DecimalFormatSymbols::kFormatSymbolCount) {
|
||
errln("unum.h and decimfmt.h have inconsistent numbers of format symbols!");
|
||
return;
|
||
}
|
||
|
||
int i;
|
||
for(i = 0; i < (int)DecimalFormatSymbols::kFormatSymbolCount; ++i) {
|
||
foo.setSymbol((DecimalFormatSymbols::ENumberFormatSymbol)i, UnicodeString((UChar32)(0x10330 + i)));
|
||
}
|
||
for(i = 0; i < (int)DecimalFormatSymbols::kFormatSymbolCount; ++i) {
|
||
if(foo.getSymbol((DecimalFormatSymbols::ENumberFormatSymbol)i) != UnicodeString((UChar32)(0x10330 + i))) {
|
||
errln("get/setSymbol did not roundtrip, got " +
|
||
foo.getSymbol((DecimalFormatSymbols::ENumberFormatSymbol)i) +
|
||
", expected " +
|
||
UnicodeString((UChar32)(0x10330 + i)));
|
||
}
|
||
}
|
||
|
||
DecimalFormatSymbols sym(Locale::getUS(), status);
|
||
|
||
UnicodeString customDecSeperator("S");
|
||
Verify(34.5, u"00.00", sym, u"34.50");
|
||
sym.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, customDecSeperator);
|
||
Verify(34.5, u"00.00", sym, u"34S50");
|
||
sym.setSymbol(DecimalFormatSymbols::kPercentSymbol, u"P");
|
||
Verify(34.5, u"00 %", sym, u"3450 P");
|
||
sym.setSymbol(DecimalFormatSymbols::kCurrencySymbol, u"D");
|
||
Verify(34.5, u"\u00a4##.##", sym, u"D\u00a034.50");
|
||
sym.setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol, u"|");
|
||
Verify(3456.5, u"0,000.##", sym, u"3|456S5");
|
||
|
||
}
|
||
|
||
void IntlTestDecimalFormatSymbols::testLastResortData() {
|
||
IcuTestErrorCode errorCode(*this, "testLastResortData");
|
||
LocalPointer<DecimalFormatSymbols> lastResort(
|
||
DecimalFormatSymbols::createWithLastResortData(errorCode));
|
||
if(errorCode.logIfFailureAndReset("DecimalFormatSymbols::createWithLastResortData() failed")) {
|
||
return;
|
||
}
|
||
DecimalFormatSymbols root(Locale::getRoot(), errorCode);
|
||
if(errorCode.logDataIfFailureAndReset("DecimalFormatSymbols(root) failed")) {
|
||
return;
|
||
}
|
||
// Note: It is not necessary that the last resort data matches the root locale,
|
||
// but it seems weird if most symbols did not match.
|
||
// Also, one purpose for calling operator==() is to find uninitialized memory in a debug build.
|
||
if(*lastResort == root) {
|
||
errln("DecimalFormatSymbols last resort data unexpectedly matches root");
|
||
}
|
||
// Here we adjust for expected differences.
|
||
assertEquals("last-resort grouping separator",
|
||
"", lastResort->getSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol));
|
||
lastResort->setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol, ",");
|
||
assertEquals("last-resort monetary grouping separator",
|
||
"", lastResort->getSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol));
|
||
lastResort->setSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol, ",");
|
||
assertEquals("last-resort NaN",
|
||
UnicodeString((UChar)0xfffd), lastResort->getSymbol(DecimalFormatSymbols::kNaNSymbol));
|
||
lastResort->setSymbol(DecimalFormatSymbols::kNaNSymbol, "NaN");
|
||
// Check that now all of the symbols match root.
|
||
for(int32_t i = 0; i < DecimalFormatSymbols::kFormatSymbolCount; ++i) {
|
||
DecimalFormatSymbols::ENumberFormatSymbol e = (DecimalFormatSymbols::ENumberFormatSymbol)i;
|
||
assertEquals("last-resort symbol vs. root", root.getSymbol(e), lastResort->getSymbol(e));
|
||
}
|
||
// Also, the CurrencySpacing patterns are empty in the last resort instance,
|
||
// but not in root.
|
||
Verify(1234567.25, "#,##0.##", *lastResort, "1,234,567.25");
|
||
}
|
||
|
||
void IntlTestDecimalFormatSymbols::testDigitSymbols() {
|
||
// This test does more in ICU4J than in ICU4C right now.
|
||
// In ICU4C, it is basically just a test for codePointZero and getConstDigitSymbol.
|
||
UChar defZero = u'0';
|
||
UChar32 osmanyaZero = U'\U000104A0';
|
||
static const UChar* osmanyaDigitStrings[] = {
|
||
u"\U000104A0", u"\U000104A1", u"\U000104A2", u"\U000104A3", u"\U000104A4",
|
||
u"\U000104A5", u"\U000104A6", u"\U000104A7", u"\U000104A8", u"\U000104A9"
|
||
};
|
||
|
||
IcuTestErrorCode status(*this, "testDigitSymbols()");
|
||
DecimalFormatSymbols symbols(Locale("en"), status);
|
||
|
||
if (defZero != symbols.getCodePointZero()) {
|
||
errln("ERROR: Code point zero be ASCII 0");
|
||
}
|
||
for (int32_t i=0; i<=9; i++) {
|
||
assertEquals(UnicodeString("i. ASCII Digit at index ") + Int64ToUnicodeString(i),
|
||
UnicodeString(u'0' + i),
|
||
symbols.getConstDigitSymbol(i));
|
||
}
|
||
|
||
for (int32_t i=0; i<=9; i++) {
|
||
DecimalFormatSymbols::ENumberFormatSymbol key =
|
||
i == 0
|
||
? DecimalFormatSymbols::kZeroDigitSymbol
|
||
: static_cast<DecimalFormatSymbols::ENumberFormatSymbol>
|
||
(DecimalFormatSymbols::kOneDigitSymbol + i - 1);
|
||
symbols.setSymbol(key, UnicodeString(osmanyaDigitStrings[i]), FALSE);
|
||
}
|
||
// NOTE: in ICU4J, the calculation of codePointZero is smarter;
|
||
// in ICU4C, it is more conservative and is only set if propogateDigits is true.
|
||
if (-1 != symbols.getCodePointZero()) {
|
||
errln("ERROR: Code point zero be invalid");
|
||
}
|
||
for (int32_t i=0; i<=9; i++) {
|
||
assertEquals(UnicodeString("ii. Osmanya digit at index ") + Int64ToUnicodeString(i),
|
||
UnicodeString(osmanyaDigitStrings[i]),
|
||
symbols.getConstDigitSymbol(i));
|
||
}
|
||
|
||
// Check Osmanya codePointZero
|
||
symbols.setSymbol(
|
||
DecimalFormatSymbols::kZeroDigitSymbol,
|
||
UnicodeString(osmanyaDigitStrings[0]), TRUE);
|
||
if (osmanyaZero != symbols.getCodePointZero()) {
|
||
errln("ERROR: Code point zero be Osmanya code point zero");
|
||
}
|
||
for (int32_t i=0; i<=9; i++) {
|
||
assertEquals(UnicodeString("iii. Osmanya digit at index ") + Int64ToUnicodeString(i),
|
||
UnicodeString(osmanyaDigitStrings[i]),
|
||
symbols.getConstDigitSymbol(i));
|
||
}
|
||
|
||
// Check after copy
|
||
DecimalFormatSymbols copy(symbols);
|
||
if (osmanyaZero != copy.getCodePointZero()) {
|
||
errln("ERROR: Code point zero be Osmanya code point zero");
|
||
}
|
||
for (int32_t i=0; i<=9; i++) {
|
||
assertEquals(UnicodeString("iv. After copy at index ") + Int64ToUnicodeString(i),
|
||
UnicodeString(osmanyaDigitStrings[i]),
|
||
copy.getConstDigitSymbol(i));
|
||
}
|
||
|
||
// Check when loaded from resource bundle
|
||
DecimalFormatSymbols fromData(Locale("en@numbers=osma"), status);
|
||
if (osmanyaZero != fromData.getCodePointZero()) {
|
||
errln("ERROR: Code point zero be Osmanya code point zero");
|
||
}
|
||
for (int32_t i=0; i<=9; i++) {
|
||
assertEquals(UnicodeString("v. Resource bundle at index ") + Int64ToUnicodeString(i),
|
||
UnicodeString(osmanyaDigitStrings[i]),
|
||
fromData.getConstDigitSymbol(i));
|
||
}
|
||
|
||
// Setting a digit somewhere in the middle should invalidate codePointZero
|
||
symbols.setSymbol(DecimalFormatSymbols::kOneDigitSymbol, u"foo", FALSE);
|
||
if (-1 != symbols.getCodePointZero()) {
|
||
errln("ERROR: Code point zero be invalid");
|
||
}
|
||
|
||
// Reset digits to Latin
|
||
symbols.setSymbol(
|
||
DecimalFormatSymbols::kZeroDigitSymbol,
|
||
UnicodeString(defZero));
|
||
if (defZero != symbols.getCodePointZero()) {
|
||
errln("ERROR: Code point zero be ASCII 0");
|
||
}
|
||
for (int32_t i=0; i<=9; i++) {
|
||
assertEquals(UnicodeString("vi. ASCII Digit at index ") + Int64ToUnicodeString(i),
|
||
UnicodeString(u'0' + i),
|
||
symbols.getConstDigitSymbol(i));
|
||
}
|
||
}
|
||
|
||
void IntlTestDecimalFormatSymbols::testNumberingSystem() {
|
||
IcuTestErrorCode errorCode(*this, "testNumberingSystem");
|
||
struct testcase {
|
||
const char* locid;
|
||
const char* nsname;
|
||
const char16_t* expected1; // Expected number format string
|
||
const char16_t* expected2; // Expected pattern separator
|
||
};
|
||
static const testcase cases[9] = {
|
||
{"en", "latn", u"1,234.56", u";"},
|
||
{"en", "arab", u"١٬٢٣٤٫٥٦", u"؛"},
|
||
{"en", "mathsanb", u"𝟭,𝟮𝟯𝟰.𝟱𝟲", u";"},
|
||
{"en", "mymr", u"၁,၂၃၄.၅၆", u";"},
|
||
{"my", "latn", u"1,234.56", u";"},
|
||
{"my", "arab", u"١٬٢٣٤٫٥٦", u"؛"},
|
||
{"my", "mathsanb", u"𝟭,𝟮𝟯𝟰.𝟱𝟲", u";"},
|
||
{"my", "mymr", u"၁,၂၃၄.၅၆", u"၊"},
|
||
{"en@numbers=thai", "mymr", u"၁,၂၃၄.၅၆", u";"}, // conflicting numbering system
|
||
};
|
||
|
||
for (int i=0; i<8; i++) {
|
||
testcase cas = cases[i];
|
||
Locale loc(cas.locid);
|
||
LocalPointer<NumberingSystem> ns(NumberingSystem::createInstanceByName(cas.nsname, errorCode));
|
||
if (errorCode.logDataIfFailureAndReset("NumberingSystem failed")) {
|
||
return;
|
||
}
|
||
UnicodeString expected1(cas.expected1);
|
||
UnicodeString expected2(cas.expected2);
|
||
DecimalFormatSymbols dfs(loc, *ns, errorCode);
|
||
if (errorCode.logDataIfFailureAndReset("DecimalFormatSymbols failed")) {
|
||
return;
|
||
}
|
||
Verify(1234.56, "#,##0.##", dfs, expected1);
|
||
// The pattern separator is something that differs by numbering system in my@numbers=mymr.
|
||
UnicodeString actual2 = dfs.getSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol);
|
||
if (expected2 != actual2) {
|
||
errln((UnicodeString)"ERROR: DecimalFormatSymbols returned pattern separator " + actual2
|
||
+ " but we expected " + expected2);
|
||
}
|
||
}
|
||
}
|
||
|
||
void IntlTestDecimalFormatSymbols::Verify(double value, const UnicodeString& pattern,
|
||
const DecimalFormatSymbols &sym, const UnicodeString& expected){
|
||
UErrorCode status = U_ZERO_ERROR;
|
||
DecimalFormat df(pattern, sym, status);
|
||
if(U_FAILURE(status)){
|
||
errln("ERROR: construction of decimal format failed - %s", u_errorName(status));
|
||
}
|
||
UnicodeString buffer;
|
||
FieldPosition pos(FieldPosition::DONT_CARE);
|
||
buffer = df.format(value, buffer, pos);
|
||
if(buffer != expected){
|
||
errln((UnicodeString)"ERROR: format() returns wrong result\n Expected " +
|
||
expected + ", Got " + buffer);
|
||
}
|
||
}
|
||
|
||
#endif /* #if !UCONFIG_NO_FORMATTING */
|