1 // © 2018 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3
4 #include "unicode/utypes.h"
5
6 #if !UCONFIG_NO_FORMATTING
7
8 #include <cmath>
9
10 #include "numbertest.h"
11 #include "unicode/simplenumberformatter.h"
12
13
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)14 void SimpleNumberFormatterTest::runIndexedTest(int32_t index, UBool exec, const char*& name, char*) {
15 if (exec) {
16 logln("TestSuite SimpleNumberFormatterTest: ");
17 }
18 TESTCASE_AUTO_BEGIN;
19 TESTCASE_AUTO(testBasic);
20 TESTCASE_AUTO(testWithOptions);
21 TESTCASE_AUTO(testSymbols);
22 TESTCASE_AUTO(testSign);
23 TESTCASE_AUTO(testCopyMove);
24 TESTCASE_AUTO(testCAPI);
25 TESTCASE_AUTO_END;
26 }
27
testBasic()28 void SimpleNumberFormatterTest::testBasic() {
29 IcuTestErrorCode status(*this, "testBasic");
30
31 SimpleNumberFormatter snf = SimpleNumberFormatter::forLocale("de-CH", status);
32 FormattedNumber result = snf.formatInt64(-1000007, status);
33
34 static const UFieldPosition expectedFieldPositions[] = {
35 // field, begin index, end index
36 {UNUM_SIGN_FIELD, 0, 1},
37 {UNUM_GROUPING_SEPARATOR_FIELD, 2, 3},
38 {UNUM_GROUPING_SEPARATOR_FIELD, 6, 7},
39 {UNUM_INTEGER_FIELD, 1, 10},
40 };
41 checkFormattedValue(
42 u"testBasic",
43 result,
44 u"-1’000’007",
45 UFIELD_CATEGORY_NUMBER,
46 expectedFieldPositions,
47 UPRV_LENGTHOF(expectedFieldPositions));
48 }
49
testWithOptions()50 void SimpleNumberFormatterTest::testWithOptions() {
51 IcuTestErrorCode status(*this, "testWithOptions");
52
53 SimpleNumber num = SimpleNumber::forInt64(1250000, status);
54 num.setMinimumIntegerDigits(6, status);
55 num.setMinimumFractionDigits(2, status);
56 num.multiplyByPowerOfTen(-2, status);
57 num.roundTo(3, UNUM_ROUND_HALFUP, status);
58 num.truncateStart(4, status);
59 SimpleNumberFormatter snf = SimpleNumberFormatter::forLocale("bn", status);
60 FormattedNumber result = snf.format(std::move(num), status);
61
62 static const UFieldPosition expectedFieldPositions[] = {
63 // field, begin index, end index
64 {UNUM_GROUPING_SEPARATOR_FIELD, 1, 2},
65 {UNUM_GROUPING_SEPARATOR_FIELD, 4, 5},
66 {UNUM_INTEGER_FIELD, 0, 8},
67 {UNUM_DECIMAL_SEPARATOR_FIELD, 8, 9},
68 {UNUM_FRACTION_FIELD, 9, 11},
69 };
70 checkFormattedValue(
71 u"testWithOptions",
72 result,
73 u"০,০৩,০০০.০০",
74 UFIELD_CATEGORY_NUMBER,
75 expectedFieldPositions,
76 UPRV_LENGTHOF(expectedFieldPositions));
77 }
78
testSymbols()79 void SimpleNumberFormatterTest::testSymbols() {
80 IcuTestErrorCode status(*this, "testSymbols");
81
82 LocalPointer<DecimalFormatSymbols> symbols(new DecimalFormatSymbols("bn", status), status);
83 SimpleNumberFormatter snf = SimpleNumberFormatter::forLocaleAndSymbolsAndGroupingStrategy(
84 "en-US",
85 *symbols,
86 UNUM_GROUPING_ON_ALIGNED,
87 status
88 );
89 auto result = snf.formatInt64(987654321, status);
90
91 assertEquals("bn symbols with en-US pattern",
92 u"৯৮৭,৬৫৪,৩২১",
93 result.toTempString(status));
94 }
95
testSign()96 void SimpleNumberFormatterTest::testSign() {
97 IcuTestErrorCode status(*this, "testSign");
98
99 SimpleNumberFormatter snf = SimpleNumberFormatter::forLocale("und", status);
100
101 struct TestCase {
102 int64_t input;
103 USimpleNumberSign sign;
104 const char16_t* expected;
105 } cases[] = {
106 { 1, UNUM_SIMPLE_NUMBER_NO_SIGN, u"1" },
107 { 1, UNUM_SIMPLE_NUMBER_PLUS_SIGN, u"+1" },
108 { 1, UNUM_SIMPLE_NUMBER_MINUS_SIGN, u"-1" },
109 { 0, UNUM_SIMPLE_NUMBER_NO_SIGN, u"0" },
110 { 0, UNUM_SIMPLE_NUMBER_PLUS_SIGN, u"+0" },
111 { 0, UNUM_SIMPLE_NUMBER_MINUS_SIGN, u"-0" },
112 { -1, UNUM_SIMPLE_NUMBER_NO_SIGN, u"1" },
113 { -1, UNUM_SIMPLE_NUMBER_PLUS_SIGN, u"+1" },
114 { -1, UNUM_SIMPLE_NUMBER_MINUS_SIGN, u"-1" },
115 };
116 for (auto& cas : cases) {
117 SimpleNumber num = SimpleNumber::forInt64(cas.input, status);
118 num.setSign(cas.sign, status);
119 auto result = snf.format(std::move(num), status);
120 assertEquals("", cas.expected, result.toTempString(status));
121 }
122 }
123
testCopyMove()124 void SimpleNumberFormatterTest::testCopyMove() {
125 IcuTestErrorCode status(*this, "testCopyMove");
126
127 SimpleNumberFormatter snf0 = SimpleNumberFormatter::forLocale("und", status);
128
129 SimpleNumber sn0 = SimpleNumber::forInt64(55, status);
130 SimpleNumber sn1 = std::move(sn0);
131
132 snf0.format(std::move(sn0), status);
133 status.expectErrorAndReset(U_ILLEGAL_ARGUMENT_ERROR, "Use of moved number");
134
135 assertEquals("Move number constructor",
136 u"55",
137 snf0.format(std::move(sn1), status).toTempString(status));
138
139 SimpleNumber sn2;
140 snf0.format(std::move(sn2), status);
141 status.expectErrorAndReset(U_ILLEGAL_ARGUMENT_ERROR, "Default constructed number");
142
143 sn0 = SimpleNumber::forInt64(44, status);
144
145 assertEquals("Move number assignment",
146 u"44",
147 snf0.format(std::move(sn0), status).toTempString(status));
148
149 SimpleNumberFormatter snf1 = std::move(snf0);
150
151 snf0.format(SimpleNumber::forInt64(22, status), status);
152 status.expectErrorAndReset(U_INVALID_STATE_ERROR, "Use of moved formatter");
153
154 assertEquals("Move formatter constructor",
155 u"33",
156 snf1.format(SimpleNumber::forInt64(33, status), status).toTempString(status));
157
158 SimpleNumberFormatter snf2;
159 snf2.format(SimpleNumber::forInt64(22, status), status);
160 status.expectErrorAndReset(U_INVALID_STATE_ERROR, "Default constructed formatter");
161
162 snf0 = std::move(snf1);
163
164 assertEquals("Move formatter assignment",
165 u"22",
166 snf0.format(SimpleNumber::forInt64(22, status), status).toTempString(status));
167
168 snf0 = SimpleNumberFormatter::forLocale("de", status);
169 sn0 = SimpleNumber::forInt64(22, status);
170 sn0 = SimpleNumber::forInt64(11, status);
171
172 assertEquals("Move assignment with nonempty fields",
173 u"11",
174 snf0.format(std::move(sn0), status).toTempString(status));
175 }
176
testCAPI()177 void SimpleNumberFormatterTest::testCAPI() {
178 IcuTestErrorCode status(*this, "testCAPI");
179
180 LocalUSimpleNumberFormatterPointer uformatter(usnumf_openForLocale("de-CH", status));
181 LocalUFormattedNumberPointer uresult(unumf_openResult(status));
182 usnumf_formatInt64(uformatter.getAlias(), 55, uresult.getAlias(), status);
183 assertEquals("",
184 u"55",
185 ufmtval_getString(unumf_resultAsValue(uresult.getAlias(), status), nullptr, status));
186
187 LocalUSimpleNumberPointer unumber(usnum_openForInt64(44, status));
188 usnumf_format(uformatter.getAlias(), unumber.getAlias(), uresult.getAlias(), status);
189 assertEquals("",
190 u"44",
191 ufmtval_getString(unumf_resultAsValue(uresult.getAlias(), status), nullptr, status));
192
193 // Can't re-use a number without setting it again
194 usnumf_format(uformatter.getAlias(), unumber.getAlias(), uresult.getAlias(), status);
195 status.expectErrorAndReset(U_ILLEGAL_ARGUMENT_ERROR);
196 usnum_multiplyByPowerOfTen(unumber.getAlias(), 0, status);
197 status.expectErrorAndReset(U_INVALID_STATE_ERROR);
198
199 usnum_setToInt64(unumber.getAlias(), 2335, status);
200 usnum_multiplyByPowerOfTen(unumber.getAlias(), -2, status);
201 usnum_roundTo(unumber.getAlias(), -1, UNUM_ROUND_HALFEVEN, status);
202 usnum_truncateStart(unumber.getAlias(), 1, status);
203 usnum_setMinimumFractionDigits(unumber.getAlias(), 3, status);
204 usnum_setMinimumIntegerDigits(unumber.getAlias(), 3, status);
205 usnumf_format(uformatter.getAlias(), unumber.getAlias(), uresult.getAlias(), status);
206 assertEquals("",
207 u"003.400",
208 ufmtval_getString(unumf_resultAsValue(uresult.getAlias(), status), nullptr, status));
209
210 // Setting twice should overwrite the first value
211 usnum_setToInt64(unumber.getAlias(), 1111, status);
212 usnum_setToInt64(unumber.getAlias(), 2222, status);
213 usnumf_format(uformatter.getAlias(), unumber.getAlias(), uresult.getAlias(), status);
214 assertEquals("",
215 u"2’222",
216 ufmtval_getString(unumf_resultAsValue(uresult.getAlias(), status), nullptr, status));
217
218 {
219 // This is the exact example in usimplenumberformatter.h
220 LocalUSimpleNumberFormatterPointer uformatter(usnumf_openForLocale("de-CH", status));
221 LocalUFormattedNumberPointer uresult(unumf_openResult(status));
222 usnumf_formatInt64(uformatter.getAlias(), 55, uresult.getAlias(), status);
223 assertEquals("",
224 u"55",
225 ufmtval_getString(unumf_resultAsValue(uresult.getAlias(), status), nullptr, status));
226 }
227 }
228
229
230 #endif
231