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(testDigits);
22 TESTCASE_AUTO(testSymbols);
23 TESTCASE_AUTO(testSign);
24 TESTCASE_AUTO(testCopyMove);
25 TESTCASE_AUTO(testCAPI);
26 TESTCASE_AUTO_END;
27 }
28
testBasic()29 void SimpleNumberFormatterTest::testBasic() {
30 IcuTestErrorCode status(*this, "testBasic");
31
32 SimpleNumberFormatter snf = SimpleNumberFormatter::forLocale("de-CH", status);
33 FormattedNumber result = snf.formatInt64(-1000007, status);
34
35 static const UFieldPosition expectedFieldPositions[] = {
36 // field, begin index, end index
37 {UNUM_SIGN_FIELD, 0, 1},
38 {UNUM_GROUPING_SEPARATOR_FIELD, 2, 3},
39 {UNUM_GROUPING_SEPARATOR_FIELD, 6, 7},
40 {UNUM_INTEGER_FIELD, 1, 10},
41 };
42 checkFormattedValue(
43 u"testBasic",
44 result,
45 u"-1’000’007",
46 UFIELD_CATEGORY_NUMBER,
47 expectedFieldPositions,
48 UPRV_LENGTHOF(expectedFieldPositions));
49 }
50
testWithOptions()51 void SimpleNumberFormatterTest::testWithOptions() {
52 IcuTestErrorCode status(*this, "testWithOptions");
53
54 SimpleNumber num = SimpleNumber::forInt64(1250000, status);
55 num.setMaximumIntegerDigits(6, status);
56 num.setMinimumIntegerDigits(6, status);
57 num.setMinimumFractionDigits(2, status);
58 num.multiplyByPowerOfTen(-2, status);
59 num.roundTo(3, UNUM_ROUND_HALFUP, status);
60 SimpleNumberFormatter snf = SimpleNumberFormatter::forLocale("bn", status);
61 FormattedNumber result = snf.format(std::move(num), status);
62
63 static const UFieldPosition expectedFieldPositions[] = {
64 // field, begin index, end index
65 {UNUM_GROUPING_SEPARATOR_FIELD, 1, 2},
66 {UNUM_GROUPING_SEPARATOR_FIELD, 4, 5},
67 {UNUM_INTEGER_FIELD, 0, 8},
68 {UNUM_DECIMAL_SEPARATOR_FIELD, 8, 9},
69 {UNUM_FRACTION_FIELD, 9, 11},
70 };
71 checkFormattedValue(
72 u"testWithOptions",
73 result,
74 u"০,০৩,০০০.০০",
75 UFIELD_CATEGORY_NUMBER,
76 expectedFieldPositions,
77 UPRV_LENGTHOF(expectedFieldPositions));
78 }
79
testDigits()80 void SimpleNumberFormatterTest::testDigits() {
81 IcuTestErrorCode status(*this, "testDigits");
82
83 SimpleNumberFormatter snf = SimpleNumberFormatter::forLocaleAndGroupingStrategy(
84 "en-US",
85 UNUM_GROUPING_ON_ALIGNED,
86 status
87 );
88
89 {
90 SimpleNumber num = SimpleNumber::forInt64(918273645, status);
91 num.multiplyByPowerOfTen(-4, status);
92 auto result = snf.format(std::move(num), status);
93 assertEquals("no digit options",
94 u"91,827.3645",
95 result.toTempString(status));
96 }
97
98 {
99 SimpleNumber num = SimpleNumber::forInt64(918273645, status);
100 num.multiplyByPowerOfTen(-4, status);
101 num.setMaximumIntegerDigits(4, status);
102 auto result = snf.format(std::move(num), status);
103 assertEquals("setMaximumIntegerDigits",
104 u"1,827.3645",
105 result.toTempString(status));
106 }
107
108 {
109 SimpleNumber num = SimpleNumber::forInt64(918273645, status);
110 num.multiplyByPowerOfTen(-4, status);
111 num.setMaximumIntegerDigits(8, status);
112 auto result = snf.format(std::move(num), status);
113 assertEquals("bigger setMaximumIntegerDigits",
114 u"91,827.3645",
115 result.toTempString(status));
116 }
117
118 {
119 SimpleNumber num = SimpleNumber::forInt64(918273645, status);
120 num.multiplyByPowerOfTen(-4, status);
121 num.setMinimumIntegerDigits(6, status);
122 auto result = snf.format(std::move(num), status);
123 assertEquals("setMinimumIntegerDigits",
124 u"091,827.3645",
125 result.toTempString(status));
126 }
127
128 {
129 SimpleNumber num = SimpleNumber::forInt64(918273645, status);
130 num.multiplyByPowerOfTen(-4, status);
131 num.setMinimumIntegerDigits(8, status);
132 num.setMinimumIntegerDigits(6, status);
133 auto result = snf.format(std::move(num), status);
134 assertEquals("double setMinimumIntegerDigits",
135 u"091,827.3645",
136 result.toTempString(status));
137 }
138
139 {
140 SimpleNumber num = SimpleNumber::forInt64(918273645, status);
141 num.multiplyByPowerOfTen(-4, status);
142 num.setMaximumIntegerDigits(4, status);
143 num.setMinimumIntegerDigits(6, status);
144 auto result = snf.format(std::move(num), status);
145 assertEquals("setMaximumIntegerDigits setMinimumIntegerDigits",
146 u"001,827.3645",
147 result.toTempString(status));
148 }
149
150 {
151 SimpleNumber num = SimpleNumber::forInt64(918273645, status);
152 num.multiplyByPowerOfTen(-4, status);
153 num.setMinimumIntegerDigits(6, status);
154 num.setMaximumIntegerDigits(4, status);
155 auto result = snf.format(std::move(num), status);
156 assertEquals("setMinimumIntegerDigits setMaximumIntegerDigits",
157 u"1,827.3645",
158 result.toTempString(status));
159 }
160
161 {
162 SimpleNumber num = SimpleNumber::forInt64(918273645, status);
163 num.multiplyByPowerOfTen(-4, status);
164 num.setMaximumIntegerDigits(8, status);
165 num.setMinimumIntegerDigits(6, status);
166 auto result = snf.format(std::move(num), status);
167 assertEquals("bigger setMaximumIntegerDigits setMinimumIntegerDigits",
168 u"091,827.3645",
169 result.toTempString(status));
170 }
171
172 {
173 SimpleNumber num = SimpleNumber::forInt64(918273645, status);
174 num.multiplyByPowerOfTen(-4, status);
175 num.roundTo(-1, UNUM_ROUND_HALFEVEN, status);
176 auto result = snf.format(std::move(num), status);
177 assertEquals("roundTo",
178 u"91,827.4",
179 result.toTempString(status));
180 }
181
182 {
183 SimpleNumber num = SimpleNumber::forInt64(918273645, status);
184 num.multiplyByPowerOfTen(-4, status);
185 num.setMinimumFractionDigits(5, status);
186 auto result = snf.format(std::move(num), status);
187 assertEquals("setMinimumFractionDigits",
188 u"91,827.36450",
189 result.toTempString(status));
190 }
191
192 {
193 SimpleNumber num = SimpleNumber::forInt64(918273645, status);
194 num.multiplyByPowerOfTen(-4, status);
195 num.setMinimumFractionDigits(6, status);
196 num.setMinimumFractionDigits(5, status);
197 auto result = snf.format(std::move(num), status);
198 assertEquals("double setMinimumFractionDigits",
199 u"91,827.36450",
200 result.toTempString(status));
201 }
202
203 {
204 SimpleNumber num = SimpleNumber::forInt64(918273645, status);
205 num.multiplyByPowerOfTen(-4, status);
206 num.roundTo(-1, UNUM_ROUND_HALFEVEN, status);
207 num.setMinimumFractionDigits(5, status);
208 auto result = snf.format(std::move(num), status);
209 assertEquals("roundTo setMinimumFractionDigits",
210 u"91,827.40000",
211 result.toTempString(status));
212 }
213
214 {
215 SimpleNumber num = SimpleNumber::forInt64(918273645, status);
216 num.multiplyByPowerOfTen(-4, status);
217 num.setMinimumFractionDigits(5, status);
218 num.roundTo(-1, UNUM_ROUND_HALFEVEN, status);
219 auto result = snf.format(std::move(num), status);
220 assertEquals("setMinimumFractionDigits roundTo",
221 u"91,827.40000",
222 result.toTempString(status));
223 }
224 }
225
testSymbols()226 void SimpleNumberFormatterTest::testSymbols() {
227 IcuTestErrorCode status(*this, "testSymbols");
228
229 LocalPointer<DecimalFormatSymbols> symbols(new DecimalFormatSymbols("bn", status), status);
230 SimpleNumberFormatter snf = SimpleNumberFormatter::forLocaleAndSymbolsAndGroupingStrategy(
231 "en-US",
232 *symbols,
233 UNUM_GROUPING_ON_ALIGNED,
234 status
235 );
236 auto result = snf.formatInt64(987654321, status);
237
238 assertEquals("bn symbols with en-US pattern",
239 u"৯৮৭,৬৫৪,৩২১",
240 result.toTempString(status));
241 }
242
testSign()243 void SimpleNumberFormatterTest::testSign() {
244 IcuTestErrorCode status(*this, "testSign");
245
246 SimpleNumberFormatter snf = SimpleNumberFormatter::forLocale("und", status);
247
248 struct TestCase {
249 int64_t input;
250 USimpleNumberSign sign;
251 const char16_t* expected;
252 } cases[] = {
253 { 1, UNUM_SIMPLE_NUMBER_NO_SIGN, u"1" },
254 { 1, UNUM_SIMPLE_NUMBER_PLUS_SIGN, u"+1" },
255 { 1, UNUM_SIMPLE_NUMBER_MINUS_SIGN, u"-1" },
256 { 0, UNUM_SIMPLE_NUMBER_NO_SIGN, u"0" },
257 { 0, UNUM_SIMPLE_NUMBER_PLUS_SIGN, u"+0" },
258 { 0, UNUM_SIMPLE_NUMBER_MINUS_SIGN, u"-0" },
259 { -1, UNUM_SIMPLE_NUMBER_NO_SIGN, u"1" },
260 { -1, UNUM_SIMPLE_NUMBER_PLUS_SIGN, u"+1" },
261 { -1, UNUM_SIMPLE_NUMBER_MINUS_SIGN, u"-1" },
262 };
263 for (auto& cas : cases) {
264 SimpleNumber num = SimpleNumber::forInt64(cas.input, status);
265 num.setSign(cas.sign, status);
266 auto result = snf.format(std::move(num), status);
267 assertEquals("", cas.expected, result.toTempString(status));
268 }
269 }
270
testCopyMove()271 void SimpleNumberFormatterTest::testCopyMove() {
272 IcuTestErrorCode status(*this, "testCopyMove");
273
274 SimpleNumberFormatter snf0 = SimpleNumberFormatter::forLocale("und", status);
275
276 SimpleNumber sn0 = SimpleNumber::forInt64(55, status);
277 SimpleNumber sn1 = std::move(sn0);
278
279 snf0.format(std::move(sn0), status);
280 status.expectErrorAndReset(U_ILLEGAL_ARGUMENT_ERROR, "Use of moved number");
281
282 assertEquals("Move number constructor",
283 u"55",
284 snf0.format(std::move(sn1), status).toTempString(status));
285
286 SimpleNumber sn2;
287 snf0.format(std::move(sn2), status);
288 status.expectErrorAndReset(U_ILLEGAL_ARGUMENT_ERROR, "Default constructed number");
289
290 sn0 = SimpleNumber::forInt64(44, status);
291
292 assertEquals("Move number assignment",
293 u"44",
294 snf0.format(std::move(sn0), status).toTempString(status));
295
296 SimpleNumberFormatter snf1 = std::move(snf0);
297
298 snf0.format(SimpleNumber::forInt64(22, status), status);
299 status.expectErrorAndReset(U_INVALID_STATE_ERROR, "Use of moved formatter");
300
301 assertEquals("Move formatter constructor",
302 u"33",
303 snf1.format(SimpleNumber::forInt64(33, status), status).toTempString(status));
304
305 SimpleNumberFormatter snf2;
306 snf2.format(SimpleNumber::forInt64(22, status), status);
307 status.expectErrorAndReset(U_INVALID_STATE_ERROR, "Default constructed formatter");
308
309 snf0 = std::move(snf1);
310
311 assertEquals("Move formatter assignment",
312 u"22",
313 snf0.format(SimpleNumber::forInt64(22, status), status).toTempString(status));
314
315 snf0 = SimpleNumberFormatter::forLocale("de", status);
316 sn0 = SimpleNumber::forInt64(22, status);
317 sn0 = SimpleNumber::forInt64(11, status);
318
319 assertEquals("Move assignment with nonempty fields",
320 u"11",
321 snf0.format(std::move(sn0), status).toTempString(status));
322 }
323
testCAPI()324 void SimpleNumberFormatterTest::testCAPI() {
325 IcuTestErrorCode status(*this, "testCAPI");
326
327 LocalUSimpleNumberFormatterPointer uformatter(usnumf_openForLocale("de-CH", status));
328 LocalUFormattedNumberPointer uresult(unumf_openResult(status));
329 usnumf_formatInt64(uformatter.getAlias(), 55, uresult.getAlias(), status);
330 assertEquals("",
331 u"55",
332 ufmtval_getString(unumf_resultAsValue(uresult.getAlias(), status), nullptr, status));
333
334 LocalUSimpleNumberPointer unumber(usnum_openForInt64(44, status));
335 usnumf_format(uformatter.getAlias(), unumber.getAlias(), uresult.getAlias(), status);
336 assertEquals("",
337 u"44",
338 ufmtval_getString(unumf_resultAsValue(uresult.getAlias(), status), nullptr, status));
339
340 // Can't re-use a number without setting it again
341 usnumf_format(uformatter.getAlias(), unumber.getAlias(), uresult.getAlias(), status);
342 status.expectErrorAndReset(U_ILLEGAL_ARGUMENT_ERROR);
343 usnum_multiplyByPowerOfTen(unumber.getAlias(), 0, status);
344 status.expectErrorAndReset(U_INVALID_STATE_ERROR);
345
346 usnum_setToInt64(unumber.getAlias(), 2335, status);
347 usnum_multiplyByPowerOfTen(unumber.getAlias(), -2, status);
348 usnum_roundTo(unumber.getAlias(), -1, UNUM_ROUND_HALFEVEN, status);
349 usnum_setMaximumIntegerDigits(unumber.getAlias(), 1, status);
350 usnum_setMinimumFractionDigits(unumber.getAlias(), 3, status);
351 usnum_setMinimumIntegerDigits(unumber.getAlias(), 3, status);
352 usnumf_format(uformatter.getAlias(), unumber.getAlias(), uresult.getAlias(), status);
353 assertEquals("",
354 u"003.400",
355 ufmtval_getString(unumf_resultAsValue(uresult.getAlias(), status), nullptr, status));
356
357 // Setting twice should overwrite the first value
358 usnum_setToInt64(unumber.getAlias(), 1111, status);
359 usnum_setToInt64(unumber.getAlias(), 2222, status);
360 usnumf_format(uformatter.getAlias(), unumber.getAlias(), uresult.getAlias(), status);
361 assertEquals("",
362 u"2’222",
363 ufmtval_getString(unumf_resultAsValue(uresult.getAlias(), status), nullptr, status));
364
365 {
366 // This is the exact example in usimplenumberformatter.h
367 LocalUSimpleNumberFormatterPointer uformatter(usnumf_openForLocale("de-CH", status));
368 LocalUFormattedNumberPointer uresult(unumf_openResult(status));
369 usnumf_formatInt64(uformatter.getAlias(), 55, uresult.getAlias(), status);
370 assertEquals("",
371 u"55",
372 ufmtval_getString(unumf_resultAsValue(uresult.getAlias(), status), nullptr, status));
373 }
374 }
375
376
377 #endif
378