// © 2018 and later: Unicode, Inc. and others. // License & terms of use: http://www.unicode.org/copyright.html #include "unicode/utypes.h" #if !UCONFIG_NO_FORMATTING #include #include "numbertest.h" #include "unicode/simplenumberformatter.h" void SimpleNumberFormatterTest::runIndexedTest(int32_t index, UBool exec, const char*& name, char*) { if (exec) { logln("TestSuite SimpleNumberFormatterTest: "); } TESTCASE_AUTO_BEGIN; TESTCASE_AUTO(testBasic); TESTCASE_AUTO(testWithOptions); TESTCASE_AUTO(testDigits); TESTCASE_AUTO(testSymbols); TESTCASE_AUTO(testSign); TESTCASE_AUTO(testCopyMove); TESTCASE_AUTO(testCAPI); TESTCASE_AUTO_END; } void SimpleNumberFormatterTest::testBasic() { IcuTestErrorCode status(*this, "testBasic"); SimpleNumberFormatter snf = SimpleNumberFormatter::forLocale("de-CH", status); FormattedNumber result = snf.formatInt64(-1000007, status); static const UFieldPosition expectedFieldPositions[] = { // field, begin index, end index {UNUM_SIGN_FIELD, 0, 1}, {UNUM_GROUPING_SEPARATOR_FIELD, 2, 3}, {UNUM_GROUPING_SEPARATOR_FIELD, 6, 7}, {UNUM_INTEGER_FIELD, 1, 10}, }; checkFormattedValue( u"testBasic", result, u"-1’000’007", UFIELD_CATEGORY_NUMBER, expectedFieldPositions, UPRV_LENGTHOF(expectedFieldPositions)); } void SimpleNumberFormatterTest::testWithOptions() { IcuTestErrorCode status(*this, "testWithOptions"); SimpleNumber num = SimpleNumber::forInt64(1250000, status); num.setMaximumIntegerDigits(6, status); num.setMinimumIntegerDigits(6, status); num.setMinimumFractionDigits(2, status); num.multiplyByPowerOfTen(-2, status); num.roundTo(3, UNUM_ROUND_HALFUP, status); SimpleNumberFormatter snf = SimpleNumberFormatter::forLocale("bn", status); FormattedNumber result = snf.format(std::move(num), status); static const UFieldPosition expectedFieldPositions[] = { // field, begin index, end index {UNUM_GROUPING_SEPARATOR_FIELD, 1, 2}, {UNUM_GROUPING_SEPARATOR_FIELD, 4, 5}, {UNUM_INTEGER_FIELD, 0, 8}, {UNUM_DECIMAL_SEPARATOR_FIELD, 8, 9}, {UNUM_FRACTION_FIELD, 9, 11}, }; checkFormattedValue( u"testWithOptions", result, u"০,০৩,০০০.০০", UFIELD_CATEGORY_NUMBER, expectedFieldPositions, UPRV_LENGTHOF(expectedFieldPositions)); } void SimpleNumberFormatterTest::testDigits() { IcuTestErrorCode status(*this, "testDigits"); SimpleNumberFormatter snf = SimpleNumberFormatter::forLocaleAndGroupingStrategy( "en-US", UNUM_GROUPING_ON_ALIGNED, status ); { SimpleNumber num = SimpleNumber::forInt64(918273645, status); num.multiplyByPowerOfTen(-4, status); auto result = snf.format(std::move(num), status); assertEquals("no digit options", u"91,827.3645", result.toTempString(status)); } { SimpleNumber num = SimpleNumber::forInt64(918273645, status); num.multiplyByPowerOfTen(-4, status); num.setMaximumIntegerDigits(4, status); auto result = snf.format(std::move(num), status); assertEquals("setMaximumIntegerDigits", u"1,827.3645", result.toTempString(status)); } { SimpleNumber num = SimpleNumber::forInt64(918273645, status); num.multiplyByPowerOfTen(-4, status); num.setMaximumIntegerDigits(8, status); auto result = snf.format(std::move(num), status); assertEquals("bigger setMaximumIntegerDigits", u"91,827.3645", result.toTempString(status)); } { SimpleNumber num = SimpleNumber::forInt64(918273645, status); num.multiplyByPowerOfTen(-4, status); num.setMinimumIntegerDigits(6, status); auto result = snf.format(std::move(num), status); assertEquals("setMinimumIntegerDigits", u"091,827.3645", result.toTempString(status)); } { SimpleNumber num = SimpleNumber::forInt64(918273645, status); num.multiplyByPowerOfTen(-4, status); num.setMinimumIntegerDigits(8, status); num.setMinimumIntegerDigits(6, status); auto result = snf.format(std::move(num), status); assertEquals("double setMinimumIntegerDigits", u"091,827.3645", result.toTempString(status)); } { SimpleNumber num = SimpleNumber::forInt64(918273645, status); num.multiplyByPowerOfTen(-4, status); num.setMaximumIntegerDigits(4, status); num.setMinimumIntegerDigits(6, status); auto result = snf.format(std::move(num), status); assertEquals("setMaximumIntegerDigits setMinimumIntegerDigits", u"001,827.3645", result.toTempString(status)); } { SimpleNumber num = SimpleNumber::forInt64(918273645, status); num.multiplyByPowerOfTen(-4, status); num.setMinimumIntegerDigits(6, status); num.setMaximumIntegerDigits(4, status); auto result = snf.format(std::move(num), status); assertEquals("setMinimumIntegerDigits setMaximumIntegerDigits", u"1,827.3645", result.toTempString(status)); } { SimpleNumber num = SimpleNumber::forInt64(918273645, status); num.multiplyByPowerOfTen(-4, status); num.setMaximumIntegerDigits(8, status); num.setMinimumIntegerDigits(6, status); auto result = snf.format(std::move(num), status); assertEquals("bigger setMaximumIntegerDigits setMinimumIntegerDigits", u"091,827.3645", result.toTempString(status)); } { SimpleNumber num = SimpleNumber::forInt64(918273645, status); num.multiplyByPowerOfTen(-4, status); num.roundTo(-1, UNUM_ROUND_HALFEVEN, status); auto result = snf.format(std::move(num), status); assertEquals("roundTo", u"91,827.4", result.toTempString(status)); } { SimpleNumber num = SimpleNumber::forInt64(918273645, status); num.multiplyByPowerOfTen(-4, status); num.setMinimumFractionDigits(5, status); auto result = snf.format(std::move(num), status); assertEquals("setMinimumFractionDigits", u"91,827.36450", result.toTempString(status)); } { SimpleNumber num = SimpleNumber::forInt64(918273645, status); num.multiplyByPowerOfTen(-4, status); num.setMinimumFractionDigits(6, status); num.setMinimumFractionDigits(5, status); auto result = snf.format(std::move(num), status); assertEquals("double setMinimumFractionDigits", u"91,827.36450", result.toTempString(status)); } { SimpleNumber num = SimpleNumber::forInt64(918273645, status); num.multiplyByPowerOfTen(-4, status); num.roundTo(-1, UNUM_ROUND_HALFEVEN, status); num.setMinimumFractionDigits(5, status); auto result = snf.format(std::move(num), status); assertEquals("roundTo setMinimumFractionDigits", u"91,827.40000", result.toTempString(status)); } { SimpleNumber num = SimpleNumber::forInt64(918273645, status); num.multiplyByPowerOfTen(-4, status); num.setMinimumFractionDigits(5, status); num.roundTo(-1, UNUM_ROUND_HALFEVEN, status); auto result = snf.format(std::move(num), status); assertEquals("setMinimumFractionDigits roundTo", u"91,827.40000", result.toTempString(status)); } } void SimpleNumberFormatterTest::testSymbols() { IcuTestErrorCode status(*this, "testSymbols"); LocalPointer symbols(new DecimalFormatSymbols("bn", status), status); SimpleNumberFormatter snf = SimpleNumberFormatter::forLocaleAndSymbolsAndGroupingStrategy( "en-US", *symbols, UNUM_GROUPING_ON_ALIGNED, status ); auto result = snf.formatInt64(987654321, status); assertEquals("bn symbols with en-US pattern", u"৯৮৭,৬৫৪,৩২১", result.toTempString(status)); } void SimpleNumberFormatterTest::testSign() { IcuTestErrorCode status(*this, "testSign"); SimpleNumberFormatter snf = SimpleNumberFormatter::forLocale("und", status); struct TestCase { int64_t input; USimpleNumberSign sign; const char16_t* expected; } cases[] = { { 1, UNUM_SIMPLE_NUMBER_NO_SIGN, u"1" }, { 1, UNUM_SIMPLE_NUMBER_PLUS_SIGN, u"+1" }, { 1, UNUM_SIMPLE_NUMBER_MINUS_SIGN, u"-1" }, { 0, UNUM_SIMPLE_NUMBER_NO_SIGN, u"0" }, { 0, UNUM_SIMPLE_NUMBER_PLUS_SIGN, u"+0" }, { 0, UNUM_SIMPLE_NUMBER_MINUS_SIGN, u"-0" }, { -1, UNUM_SIMPLE_NUMBER_NO_SIGN, u"1" }, { -1, UNUM_SIMPLE_NUMBER_PLUS_SIGN, u"+1" }, { -1, UNUM_SIMPLE_NUMBER_MINUS_SIGN, u"-1" }, }; for (auto& cas : cases) { SimpleNumber num = SimpleNumber::forInt64(cas.input, status); num.setSign(cas.sign, status); auto result = snf.format(std::move(num), status); assertEquals("", cas.expected, result.toTempString(status)); } } void SimpleNumberFormatterTest::testCopyMove() { IcuTestErrorCode status(*this, "testCopyMove"); SimpleNumberFormatter snf0 = SimpleNumberFormatter::forLocale("und", status); SimpleNumber sn0 = SimpleNumber::forInt64(55, status); SimpleNumber sn1 = std::move(sn0); snf0.format(std::move(sn0), status); status.expectErrorAndReset(U_ILLEGAL_ARGUMENT_ERROR, "Use of moved number"); assertEquals("Move number constructor", u"55", snf0.format(std::move(sn1), status).toTempString(status)); SimpleNumber sn2; snf0.format(std::move(sn2), status); status.expectErrorAndReset(U_ILLEGAL_ARGUMENT_ERROR, "Default constructed number"); sn0 = SimpleNumber::forInt64(44, status); assertEquals("Move number assignment", u"44", snf0.format(std::move(sn0), status).toTempString(status)); SimpleNumberFormatter snf1 = std::move(snf0); snf0.format(SimpleNumber::forInt64(22, status), status); status.expectErrorAndReset(U_INVALID_STATE_ERROR, "Use of moved formatter"); assertEquals("Move formatter constructor", u"33", snf1.format(SimpleNumber::forInt64(33, status), status).toTempString(status)); SimpleNumberFormatter snf2; snf2.format(SimpleNumber::forInt64(22, status), status); status.expectErrorAndReset(U_INVALID_STATE_ERROR, "Default constructed formatter"); snf0 = std::move(snf1); assertEquals("Move formatter assignment", u"22", snf0.format(SimpleNumber::forInt64(22, status), status).toTempString(status)); snf0 = SimpleNumberFormatter::forLocale("de", status); sn0 = SimpleNumber::forInt64(22, status); sn0 = SimpleNumber::forInt64(11, status); assertEquals("Move assignment with nonempty fields", u"11", snf0.format(std::move(sn0), status).toTempString(status)); } void SimpleNumberFormatterTest::testCAPI() { IcuTestErrorCode status(*this, "testCAPI"); LocalUSimpleNumberFormatterPointer uformatter(usnumf_openForLocale("de-CH", status)); LocalUFormattedNumberPointer uresult(unumf_openResult(status)); usnumf_formatInt64(uformatter.getAlias(), 55, uresult.getAlias(), status); assertEquals("", u"55", ufmtval_getString(unumf_resultAsValue(uresult.getAlias(), status), nullptr, status)); LocalUSimpleNumberPointer unumber(usnum_openForInt64(44, status)); usnumf_format(uformatter.getAlias(), unumber.getAlias(), uresult.getAlias(), status); assertEquals("", u"44", ufmtval_getString(unumf_resultAsValue(uresult.getAlias(), status), nullptr, status)); // Can't re-use a number without setting it again usnumf_format(uformatter.getAlias(), unumber.getAlias(), uresult.getAlias(), status); status.expectErrorAndReset(U_ILLEGAL_ARGUMENT_ERROR); usnum_multiplyByPowerOfTen(unumber.getAlias(), 0, status); status.expectErrorAndReset(U_INVALID_STATE_ERROR); usnum_setToInt64(unumber.getAlias(), 2335, status); usnum_multiplyByPowerOfTen(unumber.getAlias(), -2, status); usnum_roundTo(unumber.getAlias(), -1, UNUM_ROUND_HALFEVEN, status); usnum_setMaximumIntegerDigits(unumber.getAlias(), 1, status); usnum_setMinimumFractionDigits(unumber.getAlias(), 3, status); usnum_setMinimumIntegerDigits(unumber.getAlias(), 3, status); usnumf_format(uformatter.getAlias(), unumber.getAlias(), uresult.getAlias(), status); assertEquals("", u"003.400", ufmtval_getString(unumf_resultAsValue(uresult.getAlias(), status), nullptr, status)); // Setting twice should overwrite the first value usnum_setToInt64(unumber.getAlias(), 1111, status); usnum_setToInt64(unumber.getAlias(), 2222, status); usnumf_format(uformatter.getAlias(), unumber.getAlias(), uresult.getAlias(), status); assertEquals("", u"2’222", ufmtval_getString(unumf_resultAsValue(uresult.getAlias(), status), nullptr, status)); { // This is the exact example in usimplenumberformatter.h LocalUSimpleNumberFormatterPointer uformatter(usnumf_openForLocale("de-CH", status)); LocalUFormattedNumberPointer uresult(unumf_openResult(status)); usnumf_formatInt64(uformatter.getAlias(), 55, uresult.getAlias(), status); assertEquals("", u"55", ufmtval_getString(unumf_resultAsValue(uresult.getAlias(), status), nullptr, status)); } } #endif