• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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