1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /*
4 **********************************************************************
5 * Copyright (C) 1998-2014, International Business Machines Corporation
6 * and others. All Rights Reserved.
7 **********************************************************************
8 *
9 * File cstrtest.c
10 *
11 * Modification History:
12 *
13 * Date Name Description
14 * 07/13/2000 Madhu created
15 *******************************************************************************
16 */
17
18 #include "unicode/ustring.h"
19 #include "unicode/ucnv.h"
20 #include "cstring.h"
21 #include "uinvchar.h"
22 #include "cintltst.h"
23 #include "cmemory.h"
24
25 static void TestAPI(void);
26 void addCStringTest(TestNode** root);
27
28 static void TestInvariant(void);
29 static void TestCompareInvEbcdicAsAscii(void);
30 static void TestLocaleAtSign(void);
31 static void TestNoInvariantAtSign(void);
32 static void TestInvCharToAscii(void);
33
addCStringTest(TestNode ** root)34 void addCStringTest(TestNode** root) {
35 addTest(root, &TestAPI, "tsutil/cstrtest/TestAPI");
36 addTest(root, &TestInvariant, "tsutil/cstrtest/TestInvariant");
37 addTest(root, &TestCompareInvEbcdicAsAscii, "tsutil/cstrtest/TestCompareInvEbcdicAsAscii");
38 addTest(root, &TestLocaleAtSign, "tsutil/cstrtest/TestLocaleAtSign");
39 addTest(root, &TestNoInvariantAtSign, "tsutil/cstrtest/TestNoInvariantAtSign");
40 addTest(root, &TestInvCharToAscii, "tsutil/cstrtest/TestInvCharToAscii");
41 }
42
TestAPI(void)43 static void TestAPI(void)
44 {
45 int32_t intValue=0;
46 char src[30]="HELLO THERE", dest[30];
47 static const char *const abc="abcdefghijklmnopqrstuvwxyz", *const ABC="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
48 const char *temp;
49 int32_t i;
50
51 log_verbose("Testing uprv_tolower() and uprv_toupper()\n");
52 for(i=0; i<=26; ++i) {
53 dest[i]=uprv_tolower(abc[i]);
54 }
55 if(0!=strcmp(abc, dest)) {
56 log_err("uprv_tolower(abc) failed\n");
57 }
58
59 for(i=0; i<=26; ++i) {
60 dest[i]=uprv_tolower(ABC[i]);
61 }
62 if(0!=strcmp(abc, dest)) {
63 log_err("uprv_tolower(ABC) failed\n");
64 }
65
66 for(i=0; i<=26; ++i) {
67 dest[i]=uprv_toupper(abc[i]);
68 }
69 if(0!=strcmp(ABC, dest)) {
70 log_err("uprv_toupper(abc) failed\n");
71 }
72
73 for(i=0; i<=26; ++i) {
74 dest[i]=uprv_toupper(ABC[i]);
75 }
76 if(0!=strcmp(ABC, dest)) {
77 log_err("uprv_toupper(ABC) failed\n");
78 }
79
80 log_verbose("Testing the API in cstring\n");
81 T_CString_toLowerCase(src);
82 if(uprv_strcmp(src, "hello there") != 0){
83 log_err("FAIL: *** T_CString_toLowerCase() failed. Expected: \"hello there\", Got: \"%s\"\n", src);
84 }
85 T_CString_toUpperCase(src);
86 if(uprv_strcmp(src, "HELLO THERE") != 0){
87 log_err("FAIL: *** T_CString_toUpperCase() failed. Expected: \"HELLO THERE\", Got: \"%s\"\n", src);
88 }
89
90 intValue=T_CString_stringToInteger("34556", 10);
91 if(intValue != 34556){
92 log_err("FAIL: ****T_CString_stringToInteger(\"34556\", 10) failed. Expected: 34556, Got: %d\n", intValue);
93 }
94 intValue=T_CString_stringToInteger("100", 16);
95 if(intValue != 256){
96 log_err("FAIL: ****T_CString_stringToInteger(\"100\", 16) failed. Expected: 256, Got: %d\n", intValue);
97 }
98 i = T_CString_integerToString(src, 34556, 10);
99 if(uprv_strcmp(src, "34556") != 0 || i != 5){
100 log_err("FAIL: ****integerToString(src, 34566, 10); failed. Expected: \"34556\", Got: %s\n", src);
101 }
102 i = T_CString_integerToString(src, 431, 16);
103 if(uprv_stricmp(src, "1AF") != 0 || i != 3){
104 log_err("FAIL: ****integerToString(src, 431, 16); failed. Expected: \"1AF\", Got: %s\n", src);
105 }
106 i = T_CString_int64ToString(src, U_INT64_MAX, 10);
107 if(uprv_strcmp(src, "9223372036854775807") != 0 || i != 19){
108 log_err("FAIL: ****integerToString(src, 9223372036854775807, 10); failed. Got: %s\n", src);
109 }
110 i = T_CString_int64ToString(src, U_INT64_MAX, 16);
111 if(uprv_stricmp(src, "7FFFFFFFFFFFFFFF") != 0 || i != 16){
112 log_err("FAIL: ****integerToString(src, 7FFFFFFFFFFFFFFF, 16); failed. Got: %s\n", src);
113 }
114
115 uprv_strcpy(src, "this is lower case");
116 if(uprv_stricmp(src, "THIS is lower CASE") != 0){
117 log_err("FAIL: *****uprv_stricmp() failed.");
118 }
119 if((intValue=uprv_stricmp(NULL, "first string is null") )!= -1){
120 log_err("FAIL: uprv_stricmp() where the first string is null failed. Expected: -1, returned %d\n", intValue);
121 }
122 if((intValue=uprv_stricmp("second string is null", NULL)) != 1){
123 log_err("FAIL: uprv_stricmp() where the second string is null failed. Expected: 1, returned %d\n", intValue);
124 }
125 if((intValue=uprv_stricmp(NULL, NULL)) != 0){
126 log_err("FAIL: uprv_stricmp(NULL, NULL) failed. Expected: 0, returned %d\n", intValue);
127 }
128 if((intValue=uprv_stricmp("", "")) != 0){
129 log_err("FAIL: uprv_stricmp(\"\", \"\") failed. Expected: 0, returned %d\n", intValue);
130 }
131 if((intValue=uprv_stricmp("", "abc")) != -1){
132 log_err("FAIL: uprv_stricmp(\"\", \"abc\") failed. Expected: -1, returned %d\n", intValue);
133 }
134 if((intValue=uprv_stricmp("abc", "")) != 1){
135 log_err("FAIL: uprv_stricmp(\"abc\", \"\") failed. Expected: 1, returned %d\n", intValue);
136 }
137
138 temp=uprv_strdup("strdup");
139 if(uprv_strcmp(temp, "strdup") !=0 ){
140 log_err("FAIL: uprv_strdup() failed. Expected: \"strdup\", Got: %s\n", temp);
141 }
142 uprv_free((char *)temp);
143
144 uprv_strcpy(src, "this is lower case");
145 if(uprv_strnicmp(src, "THIS", 4 ) != 0){
146 log_err("FAIL: *****uprv_strnicmp() failed.");
147 }
148 if((intValue=uprv_strnicmp(NULL, "first string is null", 10) )!= -1){
149 log_err("FAIL: uprv_strnicmp() where the first string is null failed. Expected: -1, returned %d\n", intValue);
150 }
151 if((intValue=uprv_strnicmp("second string is null", NULL, 10)) != 1){
152 log_err("FAIL: uprv_strnicmp() where the second string is null failed. Expected: 1, returned %d\n", intValue);
153 }
154 if((intValue=uprv_strnicmp(NULL, NULL, 10)) != 0){
155 log_err("FAIL: uprv_strnicmp(NULL, NULL, 10) failed. Expected: 0, returned %d\n", intValue);
156 }
157 if((intValue=uprv_strnicmp("", "", 10)) != 0){
158 log_err("FAIL: uprv_strnicmp(\"\", \"\") failed. Expected: 0, returned %d\n", intValue);
159 }
160 if((intValue=uprv_strnicmp("", "abc", 10)) != -1){
161 log_err("FAIL: uprv_stricmp(\"\", \"abc\", 10) failed. Expected: -1, returned %d\n", intValue);
162 }
163 if((intValue=uprv_strnicmp("abc", "", 10)) != 1){
164 log_err("FAIL: uprv_strnicmp(\"abc\", \"\", 10) failed. Expected: 1, returned %d\n", intValue);
165 }
166
167 }
168
169 /* test invariant-character handling */
170 static void
TestInvariant()171 TestInvariant() {
172 /* all invariant graphic chars and some control codes (not \n!) */
173 const char invariantChars[]=
174 "\t\r \"%&'()*+,-./"
175 "0123456789:;<=>?"
176 "ABCDEFGHIJKLMNOPQRSTUVWXYZ_"
177 "abcdefghijklmnopqrstuvwxyz";
178
179 const UChar invariantUChars[]={
180 9, 0xd, 0x20, 0x22, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
181 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
182 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
183 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5f,
184 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
185 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0
186 };
187
188 const char variantChars[]="\n!#$@[\\]^`{|}~";
189
190 const UChar variantUChars[]={
191 0x0a, 0x21, 0x23, 0x24, 0x40, 0x5b, 0x5c, 0x5d, 0x5e, 0x60, 0x7b, 0x7c, 0x7d, 0x7e, 0
192 };
193
194 const UChar nonASCIIUChars[]={ 0x80, 0xa0, 0x900, 0xff51 };
195
196 UChar us[120];
197 char cs[120];
198
199 int32_t i, length;
200
201 /* make sure that all invariant characters convert both ways */
202 length=sizeof(invariantChars);
203 u_charsToUChars(invariantChars, us, length);
204 if(u_strcmp(us, invariantUChars)!=0) {
205 log_err("u_charsToUChars(invariantChars) failed\n");
206 }
207
208 u_UCharsToChars(invariantUChars, cs, length);
209 if(strcmp(cs, invariantChars)!=0) {
210 log_err("u_UCharsToChars(invariantUChars) failed\n");
211 }
212
213
214 /*
215 * make sure that variant characters convert from source code literals to Unicode
216 * but not back to char *
217 */
218 length=sizeof(variantChars);
219 u_charsToUChars(variantChars, us, length);
220 if(u_strcmp(us, variantUChars)!=0) {
221 log_err("u_charsToUChars(variantChars) failed\n");
222 }
223
224 #ifndef U_DEBUG
225 /*
226 * Test u_UCharsToChars(variantUChars) only in release mode because it will
227 * cause an assertion failure in debug builds.
228 */
229 u_UCharsToChars(variantUChars, cs, length);
230 for(i=0; i<length; ++i) {
231 if(cs[i]!=0) {
232 log_err("u_UCharsToChars(variantUChars) converted the %d-th character to %02x instead of 00\n", i, cs[i]);
233 }
234 }
235 #endif
236
237 /*
238 * Verify that invariant characters roundtrip from Unicode to the
239 * default converter and back.
240 */
241 {
242 UConverter *cnv;
243 UErrorCode errorCode;
244
245 errorCode=U_ZERO_ERROR;
246 cnv=ucnv_open(NULL, &errorCode);
247 if(U_FAILURE(errorCode)) {
248 log_err("unable to open the default converter\n");
249 } else {
250 length=ucnv_fromUChars(cnv, cs, sizeof(cs), invariantUChars, -1, &errorCode);
251 if(U_FAILURE(errorCode)) {
252 log_err("ucnv_fromUChars(invariantUChars) failed - %s\n", u_errorName(errorCode));
253 } else if(length!=sizeof(invariantChars)-1 || strcmp(cs, invariantChars)!=0) {
254 log_err("ucnv_fromUChars(invariantUChars) failed\n");
255 }
256
257 errorCode=U_ZERO_ERROR;
258 length=ucnv_toUChars(cnv, us, UPRV_LENGTHOF(us), invariantChars, -1, &errorCode);
259 if(U_FAILURE(errorCode)) {
260 log_err("ucnv_toUChars(invariantChars) failed - %s\n", u_errorName(errorCode));
261 } else if(length!=UPRV_LENGTHOF(invariantUChars)-1 || u_strcmp(us, invariantUChars)!=0) {
262 log_err("ucnv_toUChars(invariantChars) failed\n");
263 }
264
265 ucnv_close(cnv);
266 }
267 }
268
269 /* API tests */
270 if(!uprv_isInvariantString(invariantChars, -1)) {
271 log_err("uprv_isInvariantString(invariantChars) failed\n");
272 }
273 if(!uprv_isInvariantUString(invariantUChars, -1)) {
274 log_err("uprv_isInvariantUString(invariantUChars) failed\n");
275 }
276 if(!uprv_isInvariantString(invariantChars+strlen(invariantChars), 1)) {
277 log_err("uprv_isInvariantString(\"\\0\") failed\n");
278 }
279
280 for(i=0; i<(int32_t)(sizeof(variantChars)-1); ++i) {
281 if(uprv_isInvariantString(variantChars+i, 1)) {
282 log_err("uprv_isInvariantString(variantChars[%d]) failed\n", i);
283 }
284 if(uprv_isInvariantUString(variantUChars+i, 1)) {
285 log_err("uprv_isInvariantUString(variantUChars[%d]) failed\n", i);
286 }
287 }
288
289 for(i=0; i<UPRV_LENGTHOF(nonASCIIUChars); ++i) {
290 if(uprv_isInvariantUString(nonASCIIUChars+i, 1)) {
291 log_err("uprv_isInvariantUString(nonASCIIUChars[%d]) failed\n", i);
292 }
293 }
294 }
295
getSign(int32_t n)296 static int32_t getSign(int32_t n) {
297 if(n<0) {
298 return -1;
299 } else if(n==0) {
300 return 0;
301 } else {
302 return 1;
303 }
304 }
305
306 static void
TestCompareInvEbcdicAsAscii()307 TestCompareInvEbcdicAsAscii() {
308 static const char *const invStrings[][2]={
309 /* invariant-character strings in ascending ASCII order */
310 /* EBCDIC native */
311 { "", "" },
312 { "\x6c", "%" },
313 { "\xf0", "0" },
314 { "\xf0\xf0", "00" },
315 { "\xf0\xf0\x81", "00a" },
316 { "\x7e", "=" },
317 { "\xc1", "A" },
318 { "\xc1\xf0\xf0", "A00" },
319 { "\xc1\xf0\xf0", "A00" },
320 { "\xc1\xc1", "AA" },
321 { "\xc1\xc1\xf0", "AA0" },
322 { "\x6d", "_" },
323 { "\x81", "a" },
324 { "\x81\xf0\xf0", "a00" },
325 { "\x81\xf0\xf0", "a00" },
326 { "\x81\x81", "aa" },
327 { "\x81\x81\xf0", "aa0" },
328 { "\x81\x81\x81", "aaa" },
329 { "\x81\x81\x82", "aab" }
330 };
331 int32_t i;
332 for(i=1; i<UPRV_LENGTHOF(invStrings); ++i) {
333 int32_t diff1, diff2;
334 /* compare previous vs. current */
335 diff1=getSign(uprv_compareInvEbcdicAsAscii(invStrings[i-1][0], invStrings[i][0]));
336 if(diff1>0 || (diff1==0 && 0!=uprv_strcmp(invStrings[i-1][0], invStrings[i][0]))) {
337 log_err("uprv_compareInvEbcdicAsAscii(%s, %s)=%hd is wrong\n",
338 invStrings[i-1][1], invStrings[i][1], (short)diff1);
339 }
340 /* compare current vs. previous, should be inverse diff */
341 diff2=getSign(uprv_compareInvEbcdicAsAscii(invStrings[i][0], invStrings[i-1][0]));
342 if(diff2!=-diff1) {
343 log_err("uprv_compareInvEbcdicAsAscii(%s, %s)=%hd is wrong\n",
344 invStrings[i][1], invStrings[i-1][1], (short)diff2);
345 }
346 }
347 }
348
349 // See U_CHARSET_FAMILY in unicode/platform.h.
350 static const char *nativeInvChars =
351 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
352 "abcdefghijklmnopqrstuvwxyz"
353 "0123456789 \"%&'()*+,-./:;<=>?_";
354 static const UChar *asciiInvChars =
355 u"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
356 u"abcdefghijklmnopqrstuvwxyz"
357 u"0123456789 \"%&'()*+,-./:;<=>?_";
358
359 static void
TestLocaleAtSign()360 TestLocaleAtSign() {
361 static const char *invLocale = "de-Latn_DE@PHONEBOOK";
362 for (int32_t i = 0;; ++i) {
363 char ic = invLocale[i];
364 if (ic == 0) { break; }
365 UBool expected = i == 10;
366 UBool actual = uprv_isAtSign(ic);
367 if (actual != expected) {
368 log_err("uprv_isAtSign('%c')=%d is wrong\n", ic, (int)actual);
369 }
370 }
371 }
372
373 // The at sign is not an invariant character.
374 static void
TestNoInvariantAtSign()375 TestNoInvariantAtSign() {
376 for (int32_t i = 0;; ++i) {
377 char ic = nativeInvChars[i];
378 UBool actual = uprv_isAtSign(ic);
379 if (actual) {
380 log_err("uprv_isAtSign(invariant '%c')=TRUE is wrong\n", ic);
381 }
382 if (ic == 0) { break; }
383 }
384 }
385
386 static void
TestInvCharToAscii()387 TestInvCharToAscii() {
388 for (int32_t i = 0;; ++i) {
389 char ic = nativeInvChars[i];
390 uint8_t ac = asciiInvChars[i];
391 uint8_t actual = uprv_invCharToAscii(ic);
392 if (actual != ac) {
393 log_err("uprv_invCharToAscii('%c') did not convert to ASCII 0x%02x\n", ic, (int)ac);
394 }
395 if (ic == 0) { break; }
396 }
397 }
398