1 // © 2016 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 <set>
9
10 #include "unicode/formattedvalue.h"
11 #include "unicode/unum.h"
12 #include "unicode/udat.h"
13 #include "intltest.h"
14 #include "itformat.h"
15
16
17 class FormattedValueTest : public IntlTest {
18 public:
19 void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par=0);
20 private:
21 void testBasic();
22 void testSetters();
23 void testLocalPointer();
24
25 void assertAllPartsEqual(
26 UnicodeString messagePrefix,
27 const ConstrainedFieldPosition& cfpos,
28 int32_t matching,
29 UFieldCategory category,
30 int32_t field,
31 int32_t start,
32 int32_t limit,
33 int64_t context);
34 };
35
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)36 void FormattedValueTest::runIndexedTest(int32_t index, UBool exec, const char *&name, char *) {
37 if (exec) {
38 logln("TestSuite FormattedValueTest: ");
39 }
40 TESTCASE_AUTO_BEGIN;
41 TESTCASE_AUTO(testBasic);
42 TESTCASE_AUTO(testSetters);
43 TESTCASE_AUTO(testLocalPointer);
44 TESTCASE_AUTO_END;
45 }
46
47
testBasic()48 void FormattedValueTest::testBasic() {
49 IcuTestErrorCode status(*this, "testBasic");
50 ConstrainedFieldPosition cfpos;
51 assertAllPartsEqual(
52 u"basic",
53 cfpos,
54 7,
55 UFIELD_CATEGORY_UNDEFINED,
56 0,
57 0,
58 0,
59 0LL);
60 }
61
testSetters()62 void FormattedValueTest::testSetters() {
63 IcuTestErrorCode status(*this, "testSetters");
64 ConstrainedFieldPosition cfpos;
65
66 cfpos.constrainCategory(UFIELD_CATEGORY_DATE);
67 assertAllPartsEqual(
68 u"setters 0",
69 cfpos,
70 4,
71 UFIELD_CATEGORY_DATE,
72 0,
73 0,
74 0,
75 0LL);
76
77 cfpos.constrainField(UFIELD_CATEGORY_NUMBER, UNUM_COMPACT_FIELD);
78 assertAllPartsEqual(
79 u"setters 1",
80 cfpos,
81 2,
82 UFIELD_CATEGORY_NUMBER,
83 UNUM_COMPACT_FIELD,
84 0,
85 0,
86 0LL);
87
88 cfpos.setInt64IterationContext(42424242424242LL);
89 assertAllPartsEqual(
90 u"setters 2",
91 cfpos,
92 2,
93 UFIELD_CATEGORY_NUMBER,
94 UNUM_COMPACT_FIELD,
95 0,
96 0,
97 42424242424242LL);
98
99 cfpos.setState(UFIELD_CATEGORY_NUMBER, UNUM_COMPACT_FIELD, 5, 10);
100 assertAllPartsEqual(
101 u"setters 3",
102 cfpos,
103 2,
104 UFIELD_CATEGORY_NUMBER,
105 UNUM_COMPACT_FIELD,
106 5,
107 10,
108 42424242424242LL);
109
110 cfpos.reset();
111 assertAllPartsEqual(
112 u"setters 4",
113 cfpos,
114 7,
115 UFIELD_CATEGORY_UNDEFINED,
116 0,
117 0,
118 0,
119 0LL);
120 }
121
testLocalPointer()122 void FormattedValueTest::testLocalPointer() {
123 UErrorCode status = U_ZERO_ERROR;
124 LocalUConstrainedFieldPositionPointer ucfpos(ucfpos_open(&status));
125 assertSuccess("Openining LocalUConstrainedFieldPositionPointer", status);
126 assertEquals(u"Test that object is valid",
127 0LL,
128 ucfpos_getInt64IterationContext(ucfpos.getAlias(), &status));
129 assertSuccess("Using LocalUConstrainedFieldPositionPointer", status);
130 }
131
132 /** For matching, turn on these bits:
133 *
134 * 1 = UNUM_INTEGER_FIELD
135 * 2 = UNUM_COMPACT_FIELD
136 * 4 = UDAT_AM_PM_FIELD
137 */
assertAllPartsEqual(UnicodeString messagePrefix,const ConstrainedFieldPosition & cfpos,int32_t matching,UFieldCategory category,int32_t field,int32_t start,int32_t limit,int64_t context)138 void FormattedValueTest::assertAllPartsEqual(
139 UnicodeString messagePrefix,
140 const ConstrainedFieldPosition& cfpos,
141 int32_t matching,
142 UFieldCategory category,
143 int32_t field,
144 int32_t start,
145 int32_t limit,
146 int64_t context) {
147 assertEquals(messagePrefix + u": category",
148 category, cfpos.getCategory());
149 assertEquals(messagePrefix + u": field",
150 field, cfpos.getField());
151 assertEquals(messagePrefix + u": start",
152 start, cfpos.getStart());
153 assertEquals(messagePrefix + u": limit",
154 limit, cfpos.getLimit());
155 assertEquals(messagePrefix + u": context",
156 context, cfpos.getInt64IterationContext());
157
158 assertEquals(messagePrefix + u": integer field",
159 (UBool) ((matching & 1) != 0), cfpos.matchesField(UFIELD_CATEGORY_NUMBER, UNUM_INTEGER_FIELD));
160 assertEquals(messagePrefix + u": compact field",
161 (UBool) ((matching & 2) != 0), cfpos.matchesField(UFIELD_CATEGORY_NUMBER, UNUM_COMPACT_FIELD));
162 assertEquals(messagePrefix + u": date field",
163 (UBool) ((matching & 4) != 0), cfpos.matchesField(UFIELD_CATEGORY_DATE, UDAT_AM_PM_FIELD));
164 }
165
166
checkFormattedValue(const char16_t * message,const FormattedValue & fv,UnicodeString expectedString,UFieldCategory expectedCategory,const UFieldPosition * expectedFieldPositions,int32_t length)167 void IntlTestWithFieldPosition::checkFormattedValue(
168 const char16_t* message,
169 const FormattedValue& fv,
170 UnicodeString expectedString,
171 UFieldCategory expectedCategory,
172 const UFieldPosition* expectedFieldPositions,
173 int32_t length) {
174 LocalArray<UFieldPositionWithCategory> converted(new UFieldPositionWithCategory[length]);
175 for (int32_t i=0; i<length; i++) {
176 converted[i].category = expectedCategory;
177 converted[i].field = expectedFieldPositions[i].field;
178 converted[i].beginIndex = expectedFieldPositions[i].beginIndex;
179 converted[i].endIndex = expectedFieldPositions[i].endIndex;
180 }
181 checkMixedFormattedValue(message, fv, expectedString, converted.getAlias(), length);
182 }
183
184
CFPosToUnicodeString(const ConstrainedFieldPosition & cfpos)185 UnicodeString CFPosToUnicodeString(const ConstrainedFieldPosition& cfpos) {
186 UnicodeString sb;
187 sb.append(u"CFPos[");
188 sb.append(Int64ToUnicodeString(cfpos.getStart()));
189 sb.append(u'-');
190 sb.append(Int64ToUnicodeString(cfpos.getLimit()));
191 sb.append(u' ');
192 sb.append(Int64ToUnicodeString(cfpos.getCategory()));
193 sb.append(u':');
194 sb.append(Int64ToUnicodeString(cfpos.getField()));
195 sb.append(u']');
196 return sb;
197 }
198
199
checkMixedFormattedValue(const char16_t * message,const FormattedValue & fv,UnicodeString expectedString,const UFieldPositionWithCategory * expectedFieldPositions,int32_t length)200 void IntlTestWithFieldPosition::checkMixedFormattedValue(
201 const char16_t* message,
202 const FormattedValue& fv,
203 UnicodeString expectedString,
204 const UFieldPositionWithCategory* expectedFieldPositions,
205 int32_t length) {
206 IcuTestErrorCode status(*this, "checkMixedFormattedValue");
207 UnicodeString baseMessage = UnicodeString(message) + u": " + fv.toString(status) + u": ";
208
209 // Check string values
210 assertEquals(baseMessage + u"string", expectedString, fv.toString(status));
211 assertEquals(baseMessage + u"temp string", expectedString, fv.toTempString(status));
212
213 // The temp string is guaranteed to be NUL-terminated
214 UnicodeString readOnlyAlias = fv.toTempString(status);
215 if (!status.errIfFailureAndReset()) {
216 assertEquals(baseMessage + u"NUL-terminated",
217 0, readOnlyAlias.getBuffer()[readOnlyAlias.length()]);
218 }
219
220 // Check nextPosition over all fields
221 ConstrainedFieldPosition cfpos;
222 for (int32_t i = 0; i < length; i++) {
223 assertTrue(baseMessage + u"A has next position @ " + Int64ToUnicodeString(i),
224 fv.nextPosition(cfpos, status));
225 int32_t expectedCategory = expectedFieldPositions[i].category;
226 int32_t expectedField = expectedFieldPositions[i].field;
227 int32_t expectedStart = expectedFieldPositions[i].beginIndex;
228 int32_t expectedLimit = expectedFieldPositions[i].endIndex;
229 assertEquals(baseMessage + u"A category @ " + Int64ToUnicodeString(i),
230 expectedCategory, cfpos.getCategory());
231 assertEquals(baseMessage + u"A field @ " + Int64ToUnicodeString(i),
232 expectedField, cfpos.getField());
233 assertEquals(baseMessage + u"A start @ " + Int64ToUnicodeString(i),
234 expectedStart, cfpos.getStart());
235 assertEquals(baseMessage + u"A limit @ " + Int64ToUnicodeString(i),
236 expectedLimit, cfpos.getLimit());
237 }
238 UBool afterLoopResult = fv.nextPosition(cfpos, status);
239 assertFalse(baseMessage + u"A after loop: " + CFPosToUnicodeString(cfpos), afterLoopResult);
240 afterLoopResult = fv.nextPosition(cfpos, status);
241 assertFalse(baseMessage + u"A after loop again: " + CFPosToUnicodeString(cfpos), afterLoopResult);
242
243 // Check nextPosition constrained over each category one at a time
244 for (int32_t category=0; category<=UFIELD_CATEGORY_COUNT+1; category++) {
245 if (category == UFIELD_CATEGORY_COUNT+1) {
246 category = UFIELD_CATEGORY_LIST_SPAN;
247 }
248 cfpos.reset();
249 cfpos.constrainCategory(static_cast<UFieldCategory>(category));
250 for (int32_t i = 0; i < length; i++) {
251 if (expectedFieldPositions[i].category != category) {
252 continue;
253 }
254 assertTrue(baseMessage + u"B has next position @ " + Int64ToUnicodeString(i),
255 fv.nextPosition(cfpos, status));
256 int32_t expectedCategory = expectedFieldPositions[i].category;
257 int32_t expectedField = expectedFieldPositions[i].field;
258 int32_t expectedStart = expectedFieldPositions[i].beginIndex;
259 int32_t expectedLimit = expectedFieldPositions[i].endIndex;
260 assertEquals(baseMessage + u"B category @ " + Int64ToUnicodeString(i),
261 expectedCategory, cfpos.getCategory());
262 assertEquals(baseMessage + u"B field @ " + Int64ToUnicodeString(i),
263 expectedField, cfpos.getField());
264 assertEquals(baseMessage + u"B start @ " + Int64ToUnicodeString(i),
265 expectedStart, cfpos.getStart());
266 assertEquals(baseMessage + u"B limit @ " + Int64ToUnicodeString(i),
267 expectedLimit, cfpos.getLimit());
268 }
269 UBool afterLoopResult = fv.nextPosition(cfpos, status);
270 assertFalse(baseMessage + u"B after loop @ " + CFPosToUnicodeString(cfpos), afterLoopResult);
271 afterLoopResult = fv.nextPosition(cfpos, status);
272 assertFalse(baseMessage + u"B after loop again @ " + CFPosToUnicodeString(cfpos), afterLoopResult);
273 }
274
275 // Check nextPosition constrained over each field one at a time
276 std::set<std::pair<UFieldCategory, int32_t>> uniqueFields;
277 for (int32_t i = 0; i < length; i++) {
278 uniqueFields.insert({expectedFieldPositions[i].category, expectedFieldPositions[i].field});
279 }
280 for (std::pair<UFieldCategory, int32_t> categoryAndField : uniqueFields) {
281 cfpos.reset();
282 cfpos.constrainField(categoryAndField.first, categoryAndField.second);
283 for (int32_t i = 0; i < length; i++) {
284 if (expectedFieldPositions[i].category != categoryAndField.first) {
285 continue;
286 }
287 if (expectedFieldPositions[i].field != categoryAndField.second) {
288 continue;
289 }
290 assertTrue(baseMessage + u"C has next position @ " + Int64ToUnicodeString(i),
291 fv.nextPosition(cfpos, status));
292 int32_t expectedCategory = expectedFieldPositions[i].category;
293 int32_t expectedField = expectedFieldPositions[i].field;
294 int32_t expectedStart = expectedFieldPositions[i].beginIndex;
295 int32_t expectedLimit = expectedFieldPositions[i].endIndex;
296 assertEquals(baseMessage + u"C category @ " + Int64ToUnicodeString(i),
297 expectedCategory, cfpos.getCategory());
298 assertEquals(baseMessage + u"C field @ " + Int64ToUnicodeString(i),
299 expectedField, cfpos.getField());
300 assertEquals(baseMessage + u"C start @ " + Int64ToUnicodeString(i),
301 expectedStart, cfpos.getStart());
302 assertEquals(baseMessage + u"C limit @ " + Int64ToUnicodeString(i),
303 expectedLimit, cfpos.getLimit());
304 }
305 UBool afterLoopResult = fv.nextPosition(cfpos, status);
306 assertFalse(baseMessage + u"C after loop: " + CFPosToUnicodeString(cfpos), afterLoopResult);
307 afterLoopResult = fv.nextPosition(cfpos, status);
308 assertFalse(baseMessage + u"C after loop again: " + CFPosToUnicodeString(cfpos), afterLoopResult);
309 }
310 }
311
312
createFormattedValueTest()313 extern IntlTest *createFormattedValueTest() {
314 return new FormattedValueTest();
315 }
316
317 #endif /* !UCONFIG_NO_FORMATTING */
318