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