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 "unicode/uformattedvalue.h"
9 #include "unicode/unum.h"
10 #include "unicode/ustring.h"
11 #include "cformtst.h"
12 #include "cintltst.h"
13 #include "cmemory.h"
14 #include "cstring.h"
15 #include "uassert.h"
16
17 static void TestBasic(void);
18 static void TestSetters(void);
19
20 static void AssertAllPartsEqual(
21 const char* messagePrefix,
22 const UConstrainedFieldPosition* ucfpos,
23 int32_t matching,
24 UFieldCategory category,
25 int32_t field,
26 int32_t start,
27 int32_t limit,
28 int64_t context);
29
30 void addUFormattedValueTest(TestNode** root);
31
32 #define TESTCASE(x) addTest(root, &x, "tsformat/uformattedvalue/" #x)
33
addUFormattedValueTest(TestNode ** root)34 void addUFormattedValueTest(TestNode** root) {
35 TESTCASE(TestBasic);
36 TESTCASE(TestSetters);
37 }
38
39
TestBasic()40 static void TestBasic() {
41 UErrorCode status = U_ZERO_ERROR;
42 UConstrainedFieldPosition* ucfpos = ucfpos_open(&status);
43 assertSuccess("opening ucfpos", &status);
44 assertTrue("ucfpos should not be null", ucfpos != NULL);
45
46 AssertAllPartsEqual(
47 "basic",
48 ucfpos,
49 7,
50 UFIELD_CATEGORY_UNDEFINED,
51 0,
52 0,
53 0,
54 0LL);
55
56 ucfpos_close(ucfpos);
57 }
58
TestSetters()59 void TestSetters() {
60 UErrorCode status = U_ZERO_ERROR;
61 UConstrainedFieldPosition* ucfpos = ucfpos_open(&status);
62 assertSuccess("opening ucfpos", &status);
63 assertTrue("ucfpos should not be null", ucfpos != NULL);
64
65 ucfpos_constrainCategory(ucfpos, UFIELD_CATEGORY_DATE, &status);
66 assertSuccess("setters 0", &status);
67 AssertAllPartsEqual(
68 "setters 0",
69 ucfpos,
70 4,
71 UFIELD_CATEGORY_DATE,
72 0,
73 0,
74 0,
75 0LL);
76
77 ucfpos_constrainField(ucfpos, UFIELD_CATEGORY_NUMBER, UNUM_COMPACT_FIELD, &status);
78 assertSuccess("setters 1", &status);
79 AssertAllPartsEqual(
80 "setters 1",
81 ucfpos,
82 2,
83 UFIELD_CATEGORY_NUMBER,
84 UNUM_COMPACT_FIELD,
85 0,
86 0,
87 0LL);
88
89 ucfpos_setInt64IterationContext(ucfpos, 42424242424242LL, &status);
90 assertSuccess("setters 2", &status);
91 AssertAllPartsEqual(
92 "setters 2",
93 ucfpos,
94 2,
95 UFIELD_CATEGORY_NUMBER,
96 UNUM_COMPACT_FIELD,
97 0,
98 0,
99 42424242424242LL);
100
101 ucfpos_setState(ucfpos, UFIELD_CATEGORY_NUMBER, UNUM_COMPACT_FIELD, 5, 10, &status);
102 assertSuccess("setters 3", &status);
103 AssertAllPartsEqual(
104 "setters 3",
105 ucfpos,
106 2,
107 UFIELD_CATEGORY_NUMBER,
108 UNUM_COMPACT_FIELD,
109 5,
110 10,
111 42424242424242LL);
112
113 ucfpos_reset(ucfpos, &status);
114 assertSuccess("setters 4", &status);
115 AssertAllPartsEqual(
116 "setters 4",
117 ucfpos,
118 7,
119 UFIELD_CATEGORY_UNDEFINED,
120 0,
121 0,
122 0,
123 0LL);
124
125 ucfpos_close(ucfpos);
126 }
127
128 /** For matching, turn on these bits:
129 *
130 * 1 = UNUM_INTEGER_FIELD
131 * 2 = UNUM_COMPACT_FIELD
132 * 4 = UDAT_AM_PM_FIELD
133 */
AssertAllPartsEqual(const char * messagePrefix,const UConstrainedFieldPosition * ucfpos,int32_t matching,UFieldCategory category,int32_t field,int32_t start,int32_t limit,int64_t context)134 static void AssertAllPartsEqual(
135 const char* messagePrefix,
136 const UConstrainedFieldPosition* ucfpos,
137 int32_t matching,
138 UFieldCategory category,
139 int32_t field,
140 int32_t start,
141 int32_t limit,
142 int64_t context) {
143
144 UErrorCode status = U_ZERO_ERROR;
145
146 char message[256];
147 uprv_strncpy(message, messagePrefix, 256);
148 int32_t prefixEnd = (int32_t)uprv_strlen(messagePrefix);
149 message[prefixEnd++] = ':';
150 message[prefixEnd++] = ' ';
151 U_ASSERT(prefixEnd < 256);
152
153 #define AAPE_MSG(suffix) (uprv_strncpy(message+prefixEnd, suffix, 256-prefixEnd)-prefixEnd)
154
155 UFieldCategory _category = ucfpos_getCategory(ucfpos, &status);
156 assertSuccess(AAPE_MSG("_"), &status);
157 assertIntEquals(AAPE_MSG("category"), category, _category);
158
159 int32_t _field = ucfpos_getField(ucfpos, &status);
160 assertSuccess(AAPE_MSG("field"), &status);
161 assertIntEquals(AAPE_MSG("field"), field, _field);
162
163 int32_t _start, _limit;
164 ucfpos_getIndexes(ucfpos, &_start, &_limit, &status);
165 assertSuccess(AAPE_MSG("indexes"), &status);
166 assertIntEquals(AAPE_MSG("start"), start, _start);
167 assertIntEquals(AAPE_MSG("limit"), limit, _limit);
168
169 int64_t _context = ucfpos_getInt64IterationContext(ucfpos, &status);
170 assertSuccess(AAPE_MSG("context"), &status);
171 assertIntEquals(AAPE_MSG("context"), context, _context);
172
173 UBool _matchesInteger = ucfpos_matchesField(ucfpos, UFIELD_CATEGORY_NUMBER, UNUM_INTEGER_FIELD, &status);
174 assertSuccess(AAPE_MSG("integer field"), &status);
175 assertTrue(AAPE_MSG("integer field"),
176 ((matching & 1) != 0) ? _matchesInteger : !_matchesInteger);
177
178 UBool _matchesCompact = ucfpos_matchesField(ucfpos, UFIELD_CATEGORY_NUMBER, UNUM_COMPACT_FIELD, &status);
179 assertSuccess(AAPE_MSG("compact field"), &status);
180 assertTrue(AAPE_MSG("compact field"),
181 ((matching & 2) != 0) ? _matchesCompact : !_matchesCompact);
182
183 UBool _matchesDate = ucfpos_matchesField(ucfpos, UFIELD_CATEGORY_DATE, UDAT_AM_PM_FIELD, &status);
184 assertSuccess(AAPE_MSG("date field"), &status);
185 assertTrue(AAPE_MSG("date field"),
186 ((matching & 4) != 0) ? _matchesDate : !_matchesDate);
187 }
188
189
checkFormattedValueString(const char * message,const UFormattedValue * fv,const UChar * expectedString,UErrorCode * ec)190 static void checkFormattedValueString(
191 const char* message,
192 const UFormattedValue* fv,
193 const UChar* expectedString,
194 UErrorCode* ec) {
195 int32_t length;
196 const UChar* actualString = ufmtval_getString(fv, &length, ec);
197 if (U_FAILURE(*ec)) {
198 assertIntEquals(message, 0, length);
199 return;
200 }
201 assertSuccess(message, ec);
202 // The string is guaranteed to be NUL-terminated.
203 int32_t actualLength = u_strlen(actualString);
204 assertIntEquals(message, actualLength, length);
205 assertUEquals(message, expectedString, actualString);
206 }
207
208 // Declared in cformtst.h
checkFormattedValue(const char * message,const UFormattedValue * fv,const UChar * expectedString,UFieldCategory expectedCategory,const UFieldPosition * expectedFieldPositions,int32_t expectedFieldPositionsLength)209 void checkFormattedValue(
210 const char* message,
211 const UFormattedValue* fv,
212 const UChar* expectedString,
213 UFieldCategory expectedCategory,
214 const UFieldPosition* expectedFieldPositions,
215 int32_t expectedFieldPositionsLength) {
216 (void)expectedFieldPositionsLength; // suppress compiler warnings about unused variable
217 UErrorCode ec = U_ZERO_ERROR;
218 checkFormattedValueString(message, fv, expectedString, &ec);
219 if (U_FAILURE(ec)) { return; }
220
221 // Basic loop over the fields (more rigorous testing in C++)
222 UConstrainedFieldPosition* ucfpos = ucfpos_open(&ec);
223 int32_t i = 0;
224 while (ufmtval_nextPosition(fv, ucfpos, &ec)) {
225 assertIntEquals("category",
226 expectedCategory, ucfpos_getCategory(ucfpos, &ec));
227 assertIntEquals("field",
228 expectedFieldPositions[i].field, ucfpos_getField(ucfpos, &ec));
229 int32_t start, limit;
230 ucfpos_getIndexes(ucfpos, &start, &limit, &ec);
231 assertIntEquals("start",
232 expectedFieldPositions[i].beginIndex, start);
233 assertIntEquals("limit",
234 expectedFieldPositions[i].endIndex, limit);
235 i++;
236 }
237 assertTrue("After loop", !ufmtval_nextPosition(fv, ucfpos, &ec));
238 assertSuccess("After loop", &ec);
239 ucfpos_close(ucfpos);
240 }
241
checkMixedFormattedValue(const char * message,const UFormattedValue * fv,const UChar * expectedString,const UFieldPositionWithCategory * expectedFieldPositions,int32_t length)242 void checkMixedFormattedValue(
243 const char* message,
244 const UFormattedValue* fv,
245 const UChar* expectedString,
246 const UFieldPositionWithCategory* expectedFieldPositions,
247 int32_t length) {
248 (void)length; // suppress compiler warnings about unused variable
249 UErrorCode ec = U_ZERO_ERROR;
250 checkFormattedValueString(message, fv, expectedString, &ec);
251 if (U_FAILURE(ec)) { return; }
252
253 // Basic loop over the fields (more rigorous testing in C++)
254 UConstrainedFieldPosition* ucfpos = ucfpos_open(&ec);
255 int32_t i = 0;
256 while (ufmtval_nextPosition(fv, ucfpos, &ec)) {
257 assertIntEquals("category",
258 expectedFieldPositions[i].category, ucfpos_getCategory(ucfpos, &ec));
259 assertIntEquals("field",
260 expectedFieldPositions[i].field, ucfpos_getField(ucfpos, &ec));
261 int32_t start, limit;
262 ucfpos_getIndexes(ucfpos, &start, &limit, &ec);
263 assertIntEquals("start",
264 expectedFieldPositions[i].beginIndex, start);
265 assertIntEquals("limit",
266 expectedFieldPositions[i].endIndex, limit);
267 i++;
268 }
269 assertTrue("After loop", !ufmtval_nextPosition(fv, ucfpos, &ec));
270 assertSuccess("After loop", &ec);
271 ucfpos_close(ucfpos);
272 }
273
274
275 #endif /* #if !UCONFIG_NO_FORMATTING */
276