diff --git a/.gitattributes b/.gitattributes index 1a10a09df7f..e41fb11e9ce 100644 --- a/.gitattributes +++ b/.gitattributes @@ -142,6 +142,7 @@ icu4c/source/test/cintltst/cintltst.vcxproj.filters -text icu4c/source/test/depstest/icu-dependencies-mode.el -text icu4c/source/test/intltest/intltest.vcxproj -text icu4c/source/test/intltest/intltest.vcxproj.filters -text +icu4c/source/test/intltest/numfmtspectest.cpp -text icu4c/source/test/iotest/iotest.vcxproj -text icu4c/source/test/iotest/iotest.vcxproj.filters -text icu4c/source/test/letest/cletest.vcxproj -text diff --git a/icu4c/source/test/intltest/Makefile.in b/icu4c/source/test/intltest/Makefile.in index d3e72c25cc2..4f2610f2a76 100644 --- a/icu4c/source/test/intltest/Makefile.in +++ b/icu4c/source/test/intltest/Makefile.in @@ -57,7 +57,7 @@ uobjtest.o idnaref.o idnaconf.o nptrans.o punyref.o testidn.o testidna.o uts46te incaltst.o calcasts.o v32test.o uvectest.o textfile.o tokiter.o utxttest.o \ windttst.o winnmtst.o winutil.o csdetest.o tzrulets.o tzoffloc.o tzfmttst.o ssearch.o dtifmtts.o \ tufmtts.o itspoof.o simplethread.o bidiconf.o locnmtst.o dcfmtest.o alphaindextst.o listformattertest.o genderinfotest.o compactdecimalformattest.o regiontst.o \ -reldatefmttest.o lrucachetest.o simplepatternformattertest.o measfmttest.o scientificformathelpertest.o +reldatefmttest.o lrucachetest.o simplepatternformattertest.o measfmttest.o scientificformathelpertest.o numfmtspectest.o DEPS = $(OBJECTS:.o=.d) diff --git a/icu4c/source/test/intltest/itformat.cpp b/icu4c/source/test/intltest/itformat.cpp index 948cc3a2689..e8dc872c17b 100644 --- a/icu4c/source/test/intltest/itformat.cpp +++ b/icu4c/source/test/intltest/itformat.cpp @@ -66,6 +66,7 @@ extern IntlTest *createRelativeDateTimeFormatterTest(); #endif extern IntlTest *createMeasureFormatTest(); extern IntlTest *createScientificFormatHelperTest(); +extern IntlTest *createNumberFormatSpecificationTest(); #define TESTCLASS(id, TestClass) \ case id: \ @@ -191,6 +192,15 @@ void IntlTestFormat::runIndexedTest( int32_t index, UBool exec, const char* &nam callTest(*test, par); } break; + case 49: + name = "NumberFormatSpecificationTest"; + if (exec) { + logln("NumberFormatSpecificationTest test---"); + logln((UnicodeString)""); + LocalPointer test(createNumberFormatSpecificationTest()); + callTest(*test, par); + } + break; default: name = ""; break; //needed to end loop } if (exec) { diff --git a/icu4c/source/test/intltest/numfmtspectest.cpp b/icu4c/source/test/intltest/numfmtspectest.cpp new file mode 100644 index 00000000000..ecd788f4e2c --- /dev/null +++ b/icu4c/source/test/intltest/numfmtspectest.cpp @@ -0,0 +1,252 @@ +/* +******************************************************************************* +* Copyright (C) 2014, International Business Machines Corporation and * +* others. All Rights Reserved. * +******************************************************************************* +* +* File NUMFMTSPECTEST.CPP +* +******************************************************************************* +*/ +#include +#include + +#include "intltest.h" + +#if !UCONFIG_NO_FORMATTING + +#include "unicode/localpointer.h" +#include "unicode/decimfmt.h" +#include "unicode/dtfmtsym.h" +#include "uassert.h" + +#define LENGTHOF(array) (int32_t)(sizeof(array) / sizeof((array)[0])) + +static const UChar kJPY[] = {0x4A, 0x50, 0x59}; + +static void fixNonBreakingSpace(UnicodeString &str) { + for (int32_t i = 0; i < str.length(); ++i) { + if (str[i] == 0xa0) { + str.setCharAt(i, 0x20); + } + } +} + +static NumberFormat *nfWithPattern(const char *pattern) { + UnicodeString upattern(pattern, -1, US_INV); + upattern = upattern.unescape(); + UErrorCode status = U_ZERO_ERROR; + DecimalFormat *result = new DecimalFormat( + upattern, new DecimalFormatSymbols("fr", status), status); + U_ASSERT(status == U_ZERO_ERROR); + return result; +} + +static UnicodeString format(double d, const NumberFormat &fmt) { + UnicodeString result; + fmt.format(d, result); + fixNonBreakingSpace(result); + return result; +} + +class NumberFormatSpecificationTest : public IntlTest { +public: + NumberFormatSpecificationTest() { + } + void TestBasicPatterns(); + void TestNfSetters(); + void TestRounding(); + void TestSignificantDigits(); + void TestScientificNotation(); + void TestPercent(); + void TestPerMilli(); + void TestPadding(); + void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par=0); +private: + void assertPatternFr( + const char *expected, double x, const char *pattern); + +}; + +void NumberFormatSpecificationTest::runIndexedTest( + int32_t index, UBool exec, const char *&name, char *) { + if (exec) { + logln("TestSuite NumberFormatSpecificationTest: "); + } + TESTCASE_AUTO_BEGIN; + TESTCASE_AUTO(TestBasicPatterns); + TESTCASE_AUTO(TestNfSetters); + TESTCASE_AUTO(TestRounding); + TESTCASE_AUTO(TestSignificantDigits); + TESTCASE_AUTO(TestScientificNotation); + TESTCASE_AUTO(TestPercent); + TESTCASE_AUTO(TestPerMilli); + TESTCASE_AUTO(TestPadding); + TESTCASE_AUTO_END; +} + +void NumberFormatSpecificationTest::TestBasicPatterns() { + assertPatternFr("1 234,57", 1234.567, "#,##0.##"); + assertPatternFr("1234,57", 1234.567, "0.##"); + assertPatternFr("1235", 1234.567, "0"); + assertPatternFr("1 234,567", 1234.567, "#,##0.###"); + assertPatternFr("1234,567", 1234.567, "###0.#####"); + assertPatternFr("1234,5670", 1234.567, "###0.0000#"); + assertPatternFr("01234,5670", 1234.567, "00000.0000"); + // Broken ticket 11026 + // assertPatternFr("1 234,57 \\u20ac", 1234.567, "#,##0.00 \\u00a4"); +} + +void NumberFormatSpecificationTest::TestNfSetters() { + LocalPointer nf(nfWithPattern("#,##0.##")); + nf->setMaximumIntegerDigits(5); + nf->setMinimumIntegerDigits(4); + assertEquals("", "34 567,89", format(1234567.89, *nf)); + assertEquals("", "0 034,56", format(34.56, *nf)); +} + +void NumberFormatSpecificationTest::TestRounding() { + assertPatternFr("1,0", 1.25, "0.5"); + assertPatternFr("2,0", 1.75, "0.5"); + assertPatternFr("-1,0", -1.25, "0.5"); + assertPatternFr("-02,0", -1.75, "00.5"); + assertPatternFr("0", 2.0, "4"); + assertPatternFr("8", 6.0, "4"); + assertPatternFr("8", 10.0, "4"); + assertPatternFr("99,90", 99.0, "2.70"); + assertPatternFr("273,00", 272.0, "2.73"); + assertPatternFr("1 03,60", 104.0, "#,#3.70"); +} + +void NumberFormatSpecificationTest::TestSignificantDigits() { + assertPatternFr("1230", 1234.0, "@@@"); + assertPatternFr("1 234", 1234.0, "@,@@@"); + assertPatternFr("1 235 000", 1234567.0, "@,@@@"); + assertPatternFr("1 234 567", 1234567.0, "@@@@,@@@"); + assertPatternFr("12 34 567,00", 1234567.0, "@@@@,@@,@@@"); + assertPatternFr("12 34 567,0", 1234567.0, "@@@@,@@,@@#"); + assertPatternFr("12 34 567", 1234567.0, "@@@@,@@,@##"); + assertPatternFr("12 34 567", 1234567.001, "@@@@,@@,@##"); + assertPatternFr("12 34 567", 1234567.001, "@@@@,@@,###"); + assertPatternFr("1 200", 1234.0, "#,#@@"); +} + +void NumberFormatSpecificationTest::TestScientificNotation() { + assertPatternFr("1,23E4", 12345.0, "0.00E0"); + assertPatternFr("123,00E2", 12300.0, "000.00E0"); + assertPatternFr("123,0E2", 12300.0, "000.0#E0"); + assertPatternFr("123,0E2", 12300.1, "000.0#E0"); + assertPatternFr("123,01E2", 12301.0, "000.0#E0"); + assertPatternFr("123,01E+02", 12301.0, "000.0#E+00"); + assertPatternFr("12,3E3", 12345.0, "##0.00E0"); + assertPatternFr("12,300E3", 12300.1, "##0.0000E0"); + assertPatternFr("12,30E3", 12300.1, "##0.000#E0"); + assertPatternFr("12,301E3", 12301.0, "##0.000#E0"); + // broken ticket 11020 + // assertPatternFr("1,25E4", 12301.2, "0.05E0"); + assertPatternFr("170,0E-3", 0.17, "##0.000#E0"); + +} + +void NumberFormatSpecificationTest::TestPercent() { + assertPatternFr("57,3%", 0.573, "0.0%"); + assertPatternFr("%57,3", 0.573, "%0.0"); + assertPatternFr("p%p57,3", 0.573, "p%p0.0"); + assertPatternFr("p%p0,6", 0.573, "p'%'p0.0"); + assertPatternFr("%3,260", 0.0326, "%@@@@"); + assertPatternFr("%1 540", 15.43, "%#,@@@"); + assertPatternFr("%1 656,4", 16.55, "%#,##4.1"); + assertPatternFr("%16,3E3", 162.55, "%##0.00E0"); +} + +void NumberFormatSpecificationTest::TestPerMilli() { + assertPatternFr("573,0\\u2030", 0.573, "0.0\\u2030"); + assertPatternFr("\\u2030573,0", 0.573, "\\u20300.0"); + assertPatternFr("p\\u2030p573,0", 0.573, "p\\u2030p0.0"); + assertPatternFr("p\\u2030p0,6", 0.573, "p'\\u2030'p0.0"); + assertPatternFr("\\u203032,60", 0.0326, "\\u2030@@@@"); + assertPatternFr("\\u203015 400", 15.43, "\\u2030#,@@@"); + assertPatternFr("\\u203016 551,7", 16.55, "\\u2030#,##4.1"); + assertPatternFr("\\u2030163E3", 162.55, "\\u2030##0.00E0"); +} + +void NumberFormatSpecificationTest::TestPadding() { + assertPatternFr("$***1 234", 1234, "$**####,##0"); + assertPatternFr("xxx$1 234", 1234, "*x$####,##0"); + assertPatternFr("1 234xxx$", 1234, "####,##0*x$"); + assertPatternFr("1 234$xxx", 1234, "####,##0$*x"); + assertPatternFr("ne1 234nx", -1234, "####,##0$*x;ne#n"); + assertPatternFr("n1 234*xx", -1234, "####,##0$*x;n#'*'"); + assertPatternFr("yyyy%432,6", 4.33, "*y%4.2######"); + // Broken ticket 11026 + // assertPatternFr("EUR *433,00", 433.0, "\\u00a4\\u00a4 **####0.00"); + // Broken ticket 11026 + // assertPatternFr("EUR *433,00", 433.0, "\\u00a4\\u00a4 **#######0"); + { + UnicodeString upattern("\\u00a4\\u00a4 **#######0", -1, US_INV); + upattern = upattern.unescape(); + UErrorCode status = U_ZERO_ERROR; + UnicodeString result; + DecimalFormat fmt( + upattern, new DecimalFormatSymbols("fr", status), status); + fmt.setCurrency(kJPY); + fmt.format(433.22, result); + assertSuccess("", status); + assertEquals("", "JPY ****433", result); + } + { + UnicodeString upattern( + "\\u00a4\\u00a4 **#######0;\\u00a4\\u00a4 (#)", -1, US_INV); + upattern = upattern.unescape(); + UErrorCode status = U_ZERO_ERROR; + UnicodeString result; + DecimalFormat fmt( + upattern, + new DecimalFormatSymbols("en_US", status), + status); + fmt.format(-433.22, result); + assertSuccess("", status); + assertEquals("", "USD (433.22)", result); + } + const char *paddedSciPattern = "QU**00.#####E0"; + assertPatternFr("QU***43,3E-1", 4.33, paddedSciPattern); + { + UErrorCode status = U_ZERO_ERROR; + DecimalFormatSymbols *sym = new DecimalFormatSymbols("fr", status); + sym->setSymbol(DecimalFormatSymbols::kExponentialSymbol, "EE"); + DecimalFormat fmt( + paddedSciPattern, + sym, + status); + UnicodeString result; + fmt.format(4.33, result); + assertSuccess("", status); + assertEquals("", "QU**43,3EE-1", result); + } + // padding cannot work as intended with scientific notation. + assertPatternFr("QU**43,32E-1", 4.332, paddedSciPattern); +} + +void NumberFormatSpecificationTest::assertPatternFr( + const char *expected, + double x, + const char *pattern) { + UnicodeString upattern(pattern, -1, US_INV); + UnicodeString uexpected(expected, -1, US_INV); + upattern = upattern.unescape(); + uexpected = uexpected.unescape(); + UErrorCode status = U_ZERO_ERROR; + UnicodeString result; + DecimalFormat fmt( + upattern, new DecimalFormatSymbols("fr", status), status); + fmt.format(x, result); + fixNonBreakingSpace(result); + assertSuccess("", status); + assertEquals("", uexpected, result); +} + +extern IntlTest *createNumberFormatSpecificationTest() { + return new NumberFormatSpecificationTest(); +} + +#endif