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