1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
4 * Copyright (c) 2015, International Business Machines Corporation
5 * and others. All Rights Reserved.
6 ********************************************************************/
7 /* C API TEST for UListFormatter */
8
9 #include "unicode/utypes.h"
10
11 #if !UCONFIG_NO_FORMATTING
12
13 #include "unicode/ustring.h"
14 #include "unicode/ulistformatter.h"
15 #include "cintltst.h"
16 #include "cmemory.h"
17 #include "cstring.h"
18 #include "cformtst.h"
19
20 static void TestUListFmt(void);
21 static void TestUListFmtToValue(void);
22 static void TestUListOpenStyled(void);
23
24 void addUListFmtTest(TestNode** root);
25
26 #define TESTCASE(x) addTest(root, &x, "tsformat/ulistfmttest/" #x)
27
addUListFmtTest(TestNode ** root)28 void addUListFmtTest(TestNode** root)
29 {
30 TESTCASE(TestUListFmt);
31 TESTCASE(TestUListFmtToValue);
32 TESTCASE(TestUListOpenStyled);
33 }
34
35 static const UChar str0[] = { 0x41,0 }; /* "A" */
36 static const UChar str1[] = { 0x42,0x62,0 }; /* "Bb" */
37 static const UChar str2[] = { 0x43,0x63,0x63,0 }; /* "Ccc" */
38 static const UChar str3[] = { 0x44,0x64,0x64,0x64,0 }; /* "Dddd" */
39 static const UChar str4[] = { 0x45,0x65,0x65,0x65,0x65,0 }; /* "Eeeee" */
40 static const UChar* strings[] = { str0, str1, str2, str3, str4 };
41 static const int32_t stringLengths[] = { 1, 2, 3, 4, 5 };
42 static const int32_t stringLengthsNeg[] = { -1, -1, -1, -1, -1 };
43
44 typedef struct {
45 const char * locale;
46 int32_t stringCount;
47 const char *expectedResult; /* invariant chars + escaped Unicode */
48 } ListFmtTestEntry;
49
50 static ListFmtTestEntry listFmtTestEntries[] = {
51 /* locale stringCount expectedResult */
52 { "en" , 5, "A, Bb, Ccc, Dddd, and Eeeee" },
53 { "en" , 2, "A and Bb" },
54 { "de" , 5, "A, Bb, Ccc, Dddd und Eeeee" },
55 { "de" , 2, "A und Bb" },
56 { "ja" , 5, "A\\u3001Bb\\u3001Ccc\\u3001Dddd\\u3001Eeeee" },
57 { "ja" , 2, "A\\u3001Bb" },
58 { "zh" , 5, "A\\u3001Bb\\u3001Ccc\\u3001Dddd\\u548CEeeee" },
59 { "zh" , 2, "A\\u548CBb" },
60 { NULL , 0, NULL } /* terminator */
61 };
62
63 enum {
64 kUBufMax = 128,
65 kBBufMax = 256
66 };
67
TestUListFmt()68 static void TestUListFmt() {
69 const ListFmtTestEntry * lftep;
70 for (lftep = listFmtTestEntries; lftep->locale != NULL ; lftep++ ) {
71 UErrorCode status = U_ZERO_ERROR;
72 UListFormatter *listfmt = ulistfmt_open(lftep->locale, &status);
73 if ( U_FAILURE(status) ) {
74 log_data_err("ERROR: ulistfmt_open fails for locale %s, status %s\n", lftep->locale, u_errorName(status));
75 } else {
76 UChar ubufActual[kUBufMax];
77 int32_t ulenActual = ulistfmt_format(listfmt, strings, stringLengths, lftep->stringCount, ubufActual, kUBufMax, &status);
78 if ( U_FAILURE(status) ) {
79 log_err("ERROR: ulistfmt_format fails for locale %s count %d (real lengths), status %s\n", lftep->locale, lftep->stringCount, u_errorName(status));
80 } else {
81 UChar ubufExpected[kUBufMax];
82 int32_t ulenExpected = u_unescape(lftep->expectedResult, ubufExpected, kUBufMax);
83 if (ulenActual != ulenExpected || u_strncmp(ubufActual, ubufExpected, ulenExpected) != 0) {
84 log_err("ERROR: ulistfmt_format for locale %s count %d (real lengths), actual \"%s\" != expected \"%s\"\n", lftep->locale,
85 lftep->stringCount, aescstrdup(ubufActual, ulenActual), aescstrdup(ubufExpected, ulenExpected));
86 }
87 }
88 /* try again with all lengths -1 */
89 status = U_ZERO_ERROR;
90 ulenActual = ulistfmt_format(listfmt, strings, stringLengthsNeg, lftep->stringCount, ubufActual, kUBufMax, &status);
91 if ( U_FAILURE(status) ) {
92 log_err("ERROR: ulistfmt_format fails for locale %s count %d (-1 lengths), status %s\n", lftep->locale, lftep->stringCount, u_errorName(status));
93 } else {
94 UChar ubufExpected[kUBufMax];
95 int32_t ulenExpected = u_unescape(lftep->expectedResult, ubufExpected, kUBufMax);
96 if (ulenActual != ulenExpected || u_strncmp(ubufActual, ubufExpected, ulenExpected) != 0) {
97 log_err("ERROR: ulistfmt_format for locale %s count %d (-1 lengths), actual \"%s\" != expected \"%s\"\n", lftep->locale,
98 lftep->stringCount, aescstrdup(ubufActual, ulenActual), aescstrdup(ubufExpected, ulenExpected));
99 }
100 }
101 /* try again with NULL lengths */
102 status = U_ZERO_ERROR;
103 ulenActual = ulistfmt_format(listfmt, strings, NULL, lftep->stringCount, ubufActual, kUBufMax, &status);
104 if ( U_FAILURE(status) ) {
105 log_err("ERROR: ulistfmt_format fails for locale %s count %d (NULL lengths), status %s\n", lftep->locale, lftep->stringCount, u_errorName(status));
106 } else {
107 UChar ubufExpected[kUBufMax];
108 int32_t ulenExpected = u_unescape(lftep->expectedResult, ubufExpected, kUBufMax);
109 if (ulenActual != ulenExpected || u_strncmp(ubufActual, ubufExpected, ulenExpected) != 0) {
110 log_err("ERROR: ulistfmt_format for locale %s count %d (NULL lengths), actual \"%s\" != expected \"%s\"\n", lftep->locale,
111 lftep->stringCount, aescstrdup(ubufActual, ulenActual), aescstrdup(ubufExpected, ulenExpected));
112 }
113 }
114
115 /* try calls that should return error */
116 status = U_ZERO_ERROR;
117 ulenActual = ulistfmt_format(listfmt, NULL, NULL, lftep->stringCount, ubufActual, kUBufMax, &status);
118 if (status != U_ILLEGAL_ARGUMENT_ERROR || ulenActual > 0) {
119 log_err("ERROR: ulistfmt_format for locale %s count %d with NULL strings, expected U_ILLEGAL_ARGUMENT_ERROR, got %s, result %d\n", lftep->locale,
120 lftep->stringCount, u_errorName(status), ulenActual);
121 }
122 status = U_ZERO_ERROR;
123 ulenActual = ulistfmt_format(listfmt, strings, NULL, lftep->stringCount, NULL, kUBufMax, &status);
124 if (status != U_ILLEGAL_ARGUMENT_ERROR || ulenActual > 0) {
125 log_err("ERROR: ulistfmt_format for locale %s count %d with NULL result, expected U_ILLEGAL_ARGUMENT_ERROR, got %s, result %d\n", lftep->locale,
126 lftep->stringCount, u_errorName(status), ulenActual);
127 }
128
129 ulistfmt_close(listfmt);
130 }
131 }
132 }
133
TestUListFmtToValue()134 static void TestUListFmtToValue() {
135 UErrorCode ec = U_ZERO_ERROR;
136 UListFormatter* fmt = ulistfmt_open("en", &ec);
137 UFormattedList* fl = ulistfmt_openResult(&ec);
138 assertSuccess("Opening", &ec);
139
140 {
141 const char* message = "Field position test 1";
142 const UChar* expectedString = u"hello, wonderful, and world";
143 const UChar* inputs[] = {
144 u"hello",
145 u"wonderful",
146 u"world"
147 };
148 ulistfmt_formatStringsToResult(fmt, inputs, NULL, UPRV_LENGTHOF(inputs), fl, &ec);
149 assertSuccess("Formatting", &ec);
150 static const UFieldPositionWithCategory expectedFieldPositions[] = {
151 // field, begin index, end index
152 {UFIELD_CATEGORY_LIST_SPAN, 0, 0, 5},
153 {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 0, 5},
154 {UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD, 5, 7},
155 {UFIELD_CATEGORY_LIST_SPAN, 1, 7, 16},
156 {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 7, 16},
157 {UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD, 16, 22},
158 {UFIELD_CATEGORY_LIST_SPAN, 2, 22, 27},
159 {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 22, 27}};
160 checkMixedFormattedValue(
161 message,
162 ulistfmt_resultAsValue(fl, &ec),
163 expectedString,
164 expectedFieldPositions,
165 UPRV_LENGTHOF(expectedFieldPositions));
166 }
167 {
168 const char* message = "Field position test 1";
169 const UChar* expectedString = u"A, B, C, D, E, F, and G";
170 const UChar* inputs[] = {
171 u"A",
172 u"B",
173 u"C",
174 u"D",
175 u"E",
176 u"F",
177 u"G"
178 };
179 ulistfmt_formatStringsToResult(fmt, inputs, NULL, UPRV_LENGTHOF(inputs), fl, &ec);
180 assertSuccess("Formatting", &ec);
181 static const UFieldPositionWithCategory expectedFieldPositions[] = {
182 // field, begin index, end index
183 {UFIELD_CATEGORY_LIST_SPAN, 0, 0, 1},
184 {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 0, 1},
185 {UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD, 1, 3},
186 {UFIELD_CATEGORY_LIST_SPAN, 1, 3, 4},
187 {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 3, 4},
188 {UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD, 4, 6},
189 {UFIELD_CATEGORY_LIST_SPAN, 2, 6, 7},
190 {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 6, 7},
191 {UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD, 7, 9},
192 {UFIELD_CATEGORY_LIST_SPAN, 3, 9, 10},
193 {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 9, 10},
194 {UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD, 10, 12},
195 {UFIELD_CATEGORY_LIST_SPAN, 4, 12, 13},
196 {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 12, 13},
197 {UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD, 13, 15},
198 {UFIELD_CATEGORY_LIST_SPAN, 5, 15, 16},
199 {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 15, 16},
200 {UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD, 16, 22},
201 {UFIELD_CATEGORY_LIST_SPAN, 6, 22, 23},
202 {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 22, 23}};
203 checkMixedFormattedValue(
204 message,
205 ulistfmt_resultAsValue(fl, &ec),
206 expectedString,
207 expectedFieldPositions,
208 UPRV_LENGTHOF(expectedFieldPositions));
209 }
210
211 ulistfmt_close(fmt);
212 ulistfmt_closeResult(fl);
213 }
214
TestUListOpenStyled()215 static void TestUListOpenStyled() {
216 UErrorCode ec = U_ZERO_ERROR;
217 UListFormatter* fmt = ulistfmt_openForType("en", ULISTFMT_TYPE_OR, ULISTFMT_WIDTH_SHORT, &ec);
218 UFormattedList* fl = ulistfmt_openResult(&ec);
219 assertSuccess("Opening", &ec);
220
221 {
222 const char* message = "openStyled test 1";
223 const UChar* expectedString = u"A, B, or C";
224 const UChar* inputs[] = {
225 u"A",
226 u"B",
227 u"C",
228 };
229 ulistfmt_formatStringsToResult(fmt, inputs, NULL, UPRV_LENGTHOF(inputs), fl, &ec);
230 assertSuccess("Formatting", &ec);
231 static const UFieldPositionWithCategory expectedFieldPositions[] = {
232 // field, begin index, end index
233 {UFIELD_CATEGORY_LIST_SPAN, 0, 0, 1},
234 {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 0, 1},
235 {UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD, 1, 3},
236 {UFIELD_CATEGORY_LIST_SPAN, 1, 3, 4},
237 {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 3, 4},
238 {UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD, 4, 9},
239 {UFIELD_CATEGORY_LIST_SPAN, 2, 9, 10},
240 {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 9, 10}};
241 checkMixedFormattedValue(
242 message,
243 ulistfmt_resultAsValue(fl, &ec),
244 expectedString,
245 expectedFieldPositions,
246 UPRV_LENGTHOF(expectedFieldPositions));
247 }
248
249 ulistfmt_close(fmt);
250 ulistfmt_closeResult(fl);
251 }
252
253
254 #endif /* #if !UCONFIG_NO_FORMATTING */
255