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