]> git.saurik.com Git - apple/icu.git/blame - icuSources/test/cintltst/unumberformattertst.c
ICU-66108.tar.gz
[apple/icu.git] / icuSources / test / cintltst / unumberformattertst.c
CommitLineData
0f5d89e8
A
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// Allow implicit conversion from char16_t* to UnicodeString for this file:
9// Helpful in toString methods and elsewhere.
10#define UNISTR_FROM_STRING_EXPLICIT
11
12#include "unicode/unumberformatter.h"
13#include "unicode/umisc.h"
14#include "unicode/unum.h"
3d1f044b 15#include "cformtst.h"
0f5d89e8
A
16#include "cintltst.h"
17#include "cmemory.h"
18
19static void TestSkeletonFormatToString(void);
20
21static void TestSkeletonFormatToFields(void);
22
23static void TestExampleCode(void);
24
3d1f044b
A
25static void TestFormattedValue(void);
26
27static void TestSkeletonParseError(void);
28
0f5d89e8
A
29void addUNumberFormatterTest(TestNode** root);
30
3d1f044b
A
31#define TESTCASE(x) addTest(root, &x, "tsformat/unumberformatter/" #x)
32
0f5d89e8 33void addUNumberFormatterTest(TestNode** root) {
3d1f044b
A
34 TESTCASE(TestSkeletonFormatToString);
35 TESTCASE(TestSkeletonFormatToFields);
36 TESTCASE(TestExampleCode);
37 TESTCASE(TestFormattedValue);
38 TESTCASE(TestSkeletonParseError);
0f5d89e8
A
39}
40
41
42#define CAPACITY 30
43
44static void TestSkeletonFormatToString() {
45 UErrorCode ec = U_ZERO_ERROR;
46 UChar buffer[CAPACITY];
47 UFormattedNumber* result = NULL;
48
49 // setup:
50 UNumberFormatter* f = unumf_openForSkeletonAndLocale(
51 u"precision-integer currency/USD sign-accounting", -1, "en", &ec);
52 assertSuccessCheck("Should create without error", &ec, TRUE);
53 result = unumf_openResult(&ec);
54 assertSuccess("Should create result without error", &ec);
55
56 // int64 test:
57 unumf_formatInt(f, -444444, result, &ec);
58 // Missing data will give a U_MISSING_RESOURCE_ERROR here.
59 if (assertSuccessCheck("Should format integer without error", &ec, TRUE)) {
60 unumf_resultToString(result, buffer, CAPACITY, &ec);
61 assertSuccess("Should print string to buffer without error", &ec);
62 assertUEquals("Should produce expected string result", u"($444,444)", buffer);
63
64 // double test:
65 unumf_formatDouble(f, -5142.3, result, &ec);
66 assertSuccess("Should format double without error", &ec);
67 unumf_resultToString(result, buffer, CAPACITY, &ec);
68 assertSuccess("Should print string to buffer without error", &ec);
69 assertUEquals("Should produce expected string result", u"($5,142)", buffer);
70
71 // decnumber test:
72 unumf_formatDecimal(f, "9.876E2", -1, result, &ec);
73 assertSuccess("Should format decimal without error", &ec);
74 unumf_resultToString(result, buffer, CAPACITY, &ec);
75 assertSuccess("Should print string to buffer without error", &ec);
76 assertUEquals("Should produce expected string result", u"$988", buffer);
77 }
78
79 // cleanup:
80 unumf_closeResult(result);
81 unumf_close(f);
82}
83
84
85static void TestSkeletonFormatToFields() {
86 UErrorCode ec = U_ZERO_ERROR;
87 UFieldPositionIterator* ufpositer = NULL;
88
89 // setup:
90 UNumberFormatter* uformatter = unumf_openForSkeletonAndLocale(
91 u".00 measure-unit/length-meter sign-always", -1, "en", &ec);
92 assertSuccessCheck("Should create without error", &ec, TRUE);
93 UFormattedNumber* uresult = unumf_openResult(&ec);
94 assertSuccess("Should create result without error", &ec);
95 unumf_formatInt(uformatter, 9876543210L, uresult, &ec); // "+9,876,543,210.00 m"
96 if (assertSuccessCheck("unumf_formatInt() failed", &ec, TRUE)) {
97
98 // field position test:
340931cb 99 UFieldPosition ufpos = {UNUM_DECIMAL_SEPARATOR_FIELD, 0, 0};
0f5d89e8
A
100 unumf_resultNextFieldPosition(uresult, &ufpos, &ec);
101 assertIntEquals("Field position should be correct", 14, ufpos.beginIndex);
102 assertIntEquals("Field position should be correct", 15, ufpos.endIndex);
103
104 // field position iterator test:
105 ufpositer = ufieldpositer_open(&ec);
106 if (assertSuccessCheck("Should create iterator without error", &ec, TRUE)) {
107
108 unumf_resultGetAllFieldPositions(uresult, ufpositer, &ec);
109 static const UFieldPosition expectedFields[] = {
110 // Field, begin index, end index
111 {UNUM_SIGN_FIELD, 0, 1},
112 {UNUM_GROUPING_SEPARATOR_FIELD, 2, 3},
113 {UNUM_GROUPING_SEPARATOR_FIELD, 6, 7},
114 {UNUM_GROUPING_SEPARATOR_FIELD, 10, 11},
115 {UNUM_INTEGER_FIELD, 1, 14},
116 {UNUM_DECIMAL_SEPARATOR_FIELD, 14, 15},
3d1f044b
A
117 {UNUM_FRACTION_FIELD, 15, 17},
118 {UNUM_MEASURE_UNIT_FIELD, 18, 19}
0f5d89e8
A
119 };
120 UFieldPosition actual;
340931cb 121 for (int32_t i = 0; i < (int32_t)(sizeof(expectedFields) / sizeof(*expectedFields)); i++) {
0f5d89e8
A
122 // Iterate using the UFieldPosition to hold state...
123 UFieldPosition expected = expectedFields[i];
124 actual.field = ufieldpositer_next(ufpositer, &actual.beginIndex, &actual.endIndex);
125 assertTrue("Should not return a negative index yet", actual.field >= 0);
126 if (expected.field != actual.field) {
127 log_err(
128 "FAIL: iteration %d; expected field %d; got %d\n", i, expected.field, actual.field);
129 }
130 if (expected.beginIndex != actual.beginIndex) {
131 log_err(
132 "FAIL: iteration %d; expected beginIndex %d; got %d\n",
133 i,
134 expected.beginIndex,
135 actual.beginIndex);
136 }
137 if (expected.endIndex != actual.endIndex) {
138 log_err(
139 "FAIL: iteration %d; expected endIndex %d; got %d\n",
140 i,
141 expected.endIndex,
142 actual.endIndex);
143 }
144 }
145 actual.field = ufieldpositer_next(ufpositer, &actual.beginIndex, &actual.endIndex);
146 assertTrue("No more fields; should return a negative index", actual.field < 0);
147
148 // next field iteration:
149 actual.field = UNUM_GROUPING_SEPARATOR_FIELD;
150 actual.beginIndex = 0;
151 actual.endIndex = 0;
152 int32_t i = 1;
153 while (unumf_resultNextFieldPosition(uresult, &actual, &ec)) {
154 UFieldPosition expected = expectedFields[i++];
155 assertIntEquals("Grouping separator begin index", expected.beginIndex, actual.beginIndex);
156 assertIntEquals("Grouping separator end index", expected.endIndex, actual.endIndex);
157 }
158 assertIntEquals("Should have seen all grouping separators", 4, i);
159 }
160 }
161
162 // cleanup:
163 unumf_closeResult(uresult);
164 unumf_close(uformatter);
165 ufieldpositer_close(ufpositer);
166}
167
168
169static void TestExampleCode() {
170 // This is the example code given in unumberformatter.h.
171
172 // Setup:
173 UErrorCode ec = U_ZERO_ERROR;
174 UNumberFormatter* uformatter = unumf_openForSkeletonAndLocale(u"precision-integer", -1, "en", &ec);
175 UFormattedNumber* uresult = unumf_openResult(&ec);
176 UChar* buffer = NULL;
177 assertSuccessCheck("There should not be a failure in the example code", &ec, TRUE);
178
179 // Format a double:
180 unumf_formatDouble(uformatter, 5142.3, uresult, &ec);
181 if (assertSuccessCheck("There should not be a failure in the example code", &ec, TRUE)) {
182
183 // Export the string to a malloc'd buffer:
184 int32_t len = unumf_resultToString(uresult, NULL, 0, &ec);
185 assertTrue("No buffer yet", ec == U_BUFFER_OVERFLOW_ERROR);
186 ec = U_ZERO_ERROR;
187 buffer = (UChar*) uprv_malloc((len+1)*sizeof(UChar));
188 unumf_resultToString(uresult, buffer, len+1, &ec);
189 assertSuccess("There should not be a failure in the example code", &ec);
190 assertUEquals("Should produce expected string result", u"5,142", buffer);
191 }
192
193 // Cleanup:
194 unumf_close(uformatter);
195 unumf_closeResult(uresult);
196 uprv_free(buffer);
197}
198
199
3d1f044b
A
200static void TestFormattedValue() {
201 UErrorCode ec = U_ZERO_ERROR;
202 UNumberFormatter* uformatter = unumf_openForSkeletonAndLocale(
203 u".00 compact-short", -1, "en", &ec);
204 assertSuccessCheck("Should create without error", &ec, TRUE);
205 UFormattedNumber* uresult = unumf_openResult(&ec);
206 assertSuccess("Should create result without error", &ec);
207
208 unumf_formatInt(uformatter, 55000, uresult, &ec); // "55.00 K"
209 if (assertSuccessCheck("Should format without error", &ec, TRUE)) {
210 const UFormattedValue* fv = unumf_resultAsValue(uresult, &ec);
211 assertSuccess("Should convert without error", &ec);
212 static const UFieldPosition expectedFieldPositions[] = {
213 // field, begin index, end index
214 {UNUM_INTEGER_FIELD, 0, 2},
215 {UNUM_DECIMAL_SEPARATOR_FIELD, 2, 3},
216 {UNUM_FRACTION_FIELD, 3, 5},
217 {UNUM_COMPACT_FIELD, 5, 6}};
218 checkFormattedValue(
219 "FormattedNumber as FormattedValue",
220 fv,
221 u"55.00K",
222 UFIELD_CATEGORY_NUMBER,
223 expectedFieldPositions,
224 UPRV_LENGTHOF(expectedFieldPositions));
225 }
226
227 // cleanup:
228 unumf_closeResult(uresult);
229 unumf_close(uformatter);
230}
231
232
233static void TestSkeletonParseError() {
234 UErrorCode ec = U_ZERO_ERROR;
235 UNumberFormatter* uformatter;
236 UParseError perror;
237
238 // The UParseError can be null. The following should not segfault.
239 uformatter = unumf_openForSkeletonAndLocaleWithError(
240 u".00 measure-unit/typo", -1, "en", NULL, &ec);
241 unumf_close(uformatter);
242
243 // Now test the behavior.
244 ec = U_ZERO_ERROR;
245 uformatter = unumf_openForSkeletonAndLocaleWithError(
246 u".00 measure-unit/typo", -1, "en", &perror, &ec);
247
248 assertIntEquals("Should have set error code", U_NUMBER_SKELETON_SYNTAX_ERROR, ec);
249 assertIntEquals("Should have correct skeleton error offset", 17, perror.offset);
250 assertUEquals("Should have correct pre context", u"0 measure-unit/", perror.preContext);
251 assertUEquals("Should have correct post context", u"typo", perror.postContext);
252
253 // cleanup:
254 unumf_close(uformatter);
255}
256
257
0f5d89e8 258#endif /* #if !UCONFIG_NO_FORMATTING */