1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
4 * COPYRIGHT:
5 * Copyright (c) 2005-2013, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 ********************************************************************/
8 /*
9 * File utexttst.c
10 *
11 * Modification History:
12 *
13 * Date Name Description
14 * 06/13/2005 Andy Heninger Creation
15 *******************************************************************************
16 */
17
18 #include <stdbool.h>
19
20 #include "unicode/utypes.h"
21 #include "unicode/utext.h"
22 #include "unicode/ustring.h"
23 #include "cintltst.h"
24 #include "memory.h"
25 #include "string.h"
26
27
28 static void TestAPI(void);
29 void addUTextTest(TestNode** root);
30
31
32 void
addUTextTest(TestNode ** root)33 addUTextTest(TestNode** root)
34 {
35 addTest(root, &TestAPI , "tsutil/UTextTest/TestAPI");
36 }
37
38
39 #define TEST_ASSERT(x) UPRV_BLOCK_MACRO_BEGIN { \
40 if ((x)==false) { \
41 log_err("Test failure in file %s at line %d\n", __FILE__, __LINE__); \
42 gFailed = true; \
43 } \
44 } UPRV_BLOCK_MACRO_END
45
46
47 #define TEST_SUCCESS(status) UPRV_BLOCK_MACRO_BEGIN { \
48 if (U_FAILURE(status)) { \
49 log_err("Test failure in file %s at line %d. Error = \"%s\"\n", \
50 __FILE__, __LINE__, u_errorName(status)); \
51 gFailed = true; \
52 } \
53 } UPRV_BLOCK_MACRO_END
54
55
56
57 /*
58 * TestAPI verify that the UText API is accessible from C programs.
59 * This is not intended to be a complete test of the API functionality. That is
60 * in the C++ intltest program.
61 * This test is intended to check that everything can be accessed and built in
62 * a pure C environment.
63 */
64
65
TestAPI(void)66 static void TestAPI(void) {
67 UErrorCode status = U_ZERO_ERROR;
68 UBool gFailed = false;
69 (void)gFailed; /* Suppress set but not used warning. */
70
71 /* Open */
72 {
73 UText utLoc = UTEXT_INITIALIZER;
74 const char * cString = "\x61\x62\x63\x64";
75 UChar uString[] = {0x41, 0x42, 0x43, 0};
76 UText *uta;
77 UText *utb;
78 UChar c;
79
80 uta = utext_openUChars(NULL, uString, -1, &status);
81 TEST_SUCCESS(status);
82 c = utext_next32(uta);
83 TEST_ASSERT(c == 0x41);
84 utb = utext_close(uta);
85 TEST_ASSERT(utb == NULL);
86
87 uta = utext_openUTF8(&utLoc, cString, -1, &status);
88 TEST_SUCCESS(status);
89 TEST_ASSERT(uta == &utLoc);
90
91 uta = utext_close(&utLoc);
92 TEST_ASSERT(uta == &utLoc);
93 }
94
95 /* utext_clone() */
96 {
97 UChar uString[] = {0x41, 0x42, 0x43, 0};
98 int64_t len;
99 UText *uta;
100 UText *utb;
101
102 status = U_ZERO_ERROR;
103 uta = utext_openUChars(NULL, uString, -1, &status);
104 TEST_SUCCESS(status);
105 utb = utext_clone(NULL, uta, false, false, &status);
106 TEST_SUCCESS(status);
107 TEST_ASSERT(utb != NULL);
108 TEST_ASSERT(utb != uta);
109 len = utext_nativeLength(uta);
110 TEST_ASSERT(len == u_strlen(uString));
111 utext_close(uta);
112 utext_close(utb);
113 }
114
115 /* basic access functions */
116 {
117 UChar uString[] = {0x41, 0x42, 0x43, 0};
118 UText *uta;
119 UChar32 c;
120 int64_t len;
121 UBool b;
122 int64_t i;
123
124 status = U_ZERO_ERROR;
125 uta = utext_openUChars(NULL, uString, -1, &status);
126 TEST_ASSERT(uta!=NULL);
127 TEST_SUCCESS(status);
128 b = utext_isLengthExpensive(uta);
129 TEST_ASSERT(b==true);
130 len = utext_nativeLength(uta);
131 TEST_ASSERT(len == u_strlen(uString));
132 b = utext_isLengthExpensive(uta);
133 TEST_ASSERT(b==false);
134
135 c = utext_char32At(uta, 0);
136 TEST_ASSERT(c==uString[0]);
137
138 c = utext_current32(uta);
139 TEST_ASSERT(c==uString[0]);
140
141 c = utext_next32(uta);
142 TEST_ASSERT(c==uString[0]);
143 c = utext_current32(uta);
144 TEST_ASSERT(c==uString[1]);
145
146 c = utext_previous32(uta);
147 TEST_ASSERT(c==uString[0]);
148 c = utext_current32(uta);
149 TEST_ASSERT(c==uString[0]);
150
151 c = utext_next32From(uta, 1);
152 TEST_ASSERT(c==uString[1]);
153 c = utext_next32From(uta, u_strlen(uString));
154 TEST_ASSERT(c==U_SENTINEL);
155
156 c = utext_previous32From(uta, 2);
157 TEST_ASSERT(c==uString[1]);
158 i = utext_getNativeIndex(uta);
159 TEST_ASSERT(i == 1);
160
161 utext_setNativeIndex(uta, 0);
162 b = utext_moveIndex32(uta, 1);
163 TEST_ASSERT(b==true);
164 i = utext_getNativeIndex(uta);
165 TEST_ASSERT(i==1);
166
167 b = utext_moveIndex32(uta, u_strlen(uString)-1);
168 TEST_ASSERT(b==true);
169 i = utext_getNativeIndex(uta);
170 TEST_ASSERT(i==u_strlen(uString));
171
172 b = utext_moveIndex32(uta, 1);
173 TEST_ASSERT(b==false);
174 i = utext_getNativeIndex(uta);
175 TEST_ASSERT(i==u_strlen(uString));
176
177 utext_setNativeIndex(uta, 0);
178 c = UTEXT_NEXT32(uta);
179 TEST_ASSERT(c==uString[0]);
180 c = utext_current32(uta);
181 TEST_ASSERT(c==uString[1]);
182
183 c = UTEXT_PREVIOUS32(uta);
184 TEST_ASSERT(c==uString[0]);
185 c = UTEXT_PREVIOUS32(uta);
186 TEST_ASSERT(c==U_SENTINEL);
187
188
189 utext_close(uta);
190 }
191
192 {
193 /*
194 * UText opened on a NULL string with zero length
195 */
196 UText *uta;
197 UChar32 c;
198
199 status = U_ZERO_ERROR;
200 uta = utext_openUChars(NULL, NULL, 0, &status);
201 TEST_SUCCESS(status);
202 c = UTEXT_NEXT32(uta);
203 TEST_ASSERT(c == U_SENTINEL);
204 utext_close(uta);
205
206 uta = utext_openUTF8(NULL, NULL, 0, &status);
207 TEST_SUCCESS(status);
208 c = UTEXT_NEXT32(uta);
209 TEST_ASSERT(c == U_SENTINEL);
210 utext_close(uta);
211 }
212
213
214 {
215 /*
216 * extract
217 */
218 UText *uta;
219 UChar uString[] = {0x41, 0x42, 0x43, 0};
220 UChar buf[100];
221 int32_t i;
222 /* Test pinning of input bounds */
223 UChar uString2[] = {0x41, 0x42, 0x43, 0x44, 0x45,
224 0x46, 0x47, 0x48, 0x49, 0x4A, 0};
225 UChar * uString2Ptr = uString2 + 5;
226
227 status = U_ZERO_ERROR;
228 uta = utext_openUChars(NULL, uString, -1, &status);
229 TEST_SUCCESS(status);
230
231 status = U_ZERO_ERROR;
232 i = utext_extract(uta, 0, 100, NULL, 0, &status);
233 TEST_ASSERT(status==U_BUFFER_OVERFLOW_ERROR);
234 TEST_ASSERT(i == u_strlen(uString));
235
236 status = U_ZERO_ERROR;
237 memset(buf, 0, sizeof(buf));
238 i = utext_extract(uta, 0, 100, buf, 100, &status);
239 TEST_SUCCESS(status);
240 TEST_ASSERT(i == u_strlen(uString));
241 i = u_strcmp(uString, buf);
242 TEST_ASSERT(i == 0);
243 utext_close(uta);
244
245 /* Test pinning of input bounds */
246 status = U_ZERO_ERROR;
247 uta = utext_openUChars(NULL, uString2Ptr, -1, &status);
248 TEST_SUCCESS(status);
249
250 status = U_ZERO_ERROR;
251 memset(buf, 0, sizeof(buf));
252 i = utext_extract(uta, -3, 20, buf, 100, &status);
253 TEST_SUCCESS(status);
254 TEST_ASSERT(i == u_strlen(uString2Ptr));
255 i = u_strcmp(uString2Ptr, buf);
256 TEST_ASSERT(i == 0);
257 utext_close(uta);
258 }
259
260 {
261 /*
262 * Copy, Replace, isWritable
263 * Can't create an editable UText from plain C, so all we
264 * can easily do is check that errors returned.
265 */
266 UText *uta;
267 UChar uString[] = {0x41, 0x42, 0x43, 0};
268 UBool b;
269
270 status = U_ZERO_ERROR;
271 uta = utext_openUChars(NULL, uString, -1, &status);
272 TEST_SUCCESS(status);
273
274 b = utext_isWritable(uta);
275 TEST_ASSERT(b == false);
276
277 b = utext_hasMetaData(uta);
278 TEST_ASSERT(b == false);
279
280 utext_replace(uta,
281 0, 1, /* start, limit */
282 uString, -1, /* replacement, replacement length */
283 &status);
284 TEST_ASSERT(status == U_NO_WRITE_PERMISSION);
285
286
287 utext_copy(uta,
288 0, 1, /* start, limit */
289 2, /* destination index */
290 false, /* move flag */
291 &status);
292 TEST_ASSERT(status == U_NO_WRITE_PERMISSION);
293
294 utext_close(uta);
295 }
296
297 {
298 // utext_equals() checks for the same type of text provider,
299 // same string pointer(!), and same index.
300 status = U_ZERO_ERROR;
301 const UChar *s = u"aßカ";
302 UText *ut1 = utext_openUChars(NULL, s, -1, &status);
303 UText *ut2 = utext_openUChars(NULL, s, 5, &status);
304 TEST_SUCCESS(status);
305 TEST_ASSERT(utext_equals(ut1, ut2));
306 UChar32 c = utext_next32(ut1);
307 TEST_ASSERT(c == u'a');
308 TEST_ASSERT(!utext_equals(ut1, ut2)); // indexes out of sync
309 c = utext_next32(ut2);
310 TEST_ASSERT(c == u'a');
311 TEST_ASSERT(utext_equals(ut1, ut2)); // back in sync
312 utext_close(ut1);
313 utext_close(ut2);
314 }
315 }
316