• 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(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