1 /*
2 ******************************************************************************
3 *
4 *   Copyright (C) 2002-2015, International Business Machines
5 *   Corporation and others.  All Rights Reserved.
6 *
7 ******************************************************************************
8 *   file name:  custrtst.c
9 *   encoding:   US-ASCII
10 *   tab size:   8 (not used)
11 *   indentation:4
12 *
13 *   created on: 2002oct09
14 *   created by: Markus W. Scherer
15 *
16 *   Tests of ustring.h Unicode string API functions.
17 */
18 
19 #include "unicode/ustring.h"
20 #include "unicode/ucnv.h"
21 #include "unicode/uiter.h"
22 #include "cintltst.h"
23 #include "cmemory.h"
24 #include <string.h>
25 
26 /* get the sign of an integer */
27 #define _SIGN(value) ((value)==0 ? 0 : ((int32_t)(value)>>31)|1)
28 
29 /* test setup --------------------------------------------------------------- */
30 
31 static void setUpDataTable(void);
32 static void TestStringCopy(void);
33 static void TestStringFunctions(void);
34 static void TestStringSearching(void);
35 static void TestSurrogateSearching(void);
36 static void TestUnescape(void);
37 static void TestCountChar32(void);
38 static void TestUCharIterator(void);
39 
40 void addUStringTest(TestNode** root);
41 
addUStringTest(TestNode ** root)42 void addUStringTest(TestNode** root)
43 {
44     addTest(root, &TestStringCopy, "tsutil/custrtst/TestStringCopy");
45     addTest(root, &TestStringFunctions, "tsutil/custrtst/TestStringFunctions");
46     addTest(root, &TestStringSearching, "tsutil/custrtst/TestStringSearching");
47     addTest(root, &TestSurrogateSearching, "tsutil/custrtst/TestSurrogateSearching");
48     addTest(root, &TestUnescape, "tsutil/custrtst/TestUnescape");
49     addTest(root, &TestCountChar32, "tsutil/custrtst/TestCountChar32");
50     addTest(root, &TestUCharIterator, "tsutil/custrtst/TestUCharIterator");
51 }
52 
53 /* test data for TestStringFunctions ---------------------------------------- */
54 
55 UChar*** dataTable = NULL;
56 
57 static const char* raw[3][4] = {
58 
59     /* First String */
60     {   "English_",  "French_",   "Croatian_", "English_"},
61     /* Second String */
62     {   "United States",    "France",   "Croatia",  "Unites States"},
63 
64    /* Concatenated string */
65     {   "English_United States", "French_France", "Croatian_Croatia", "English_United States"}
66 };
67 
setUpDataTable()68 static void setUpDataTable()
69 {
70     int32_t i,j;
71     if(dataTable == NULL) {
72         dataTable = (UChar***)calloc(sizeof(UChar**),3);
73 
74             for (i = 0; i < 3; i++) {
75               dataTable[i] = (UChar**)calloc(sizeof(UChar*),4);
76                 for (j = 0; j < 4; j++){
77                     dataTable[i][j] = (UChar*) malloc(sizeof(UChar)*(strlen(raw[i][j])+1));
78                     u_uastrcpy(dataTable[i][j],raw[i][j]);
79                 }
80             }
81     }
82 }
83 
cleanUpDataTable()84 static void cleanUpDataTable()
85 {
86     int32_t i,j;
87     if(dataTable != NULL) {
88         for (i=0; i<3; i++) {
89             for(j = 0; j<4; j++) {
90                 free(dataTable[i][j]);
91             }
92             free(dataTable[i]);
93         }
94         free(dataTable);
95     }
96     dataTable = NULL;
97 }
98 
99 /*Tests  for u_strcat(),u_strcmp(), u_strlen(), u_strcpy(),u_strncat(),u_strncmp(),u_strncpy, u_uastrcpy(),u_austrcpy(), u_uastrncpy(); */
TestStringFunctions()100 static void TestStringFunctions()
101 {
102     int32_t i,j,k;
103     UChar temp[512];
104     UChar nullTemp[512];
105     char test[512];
106     char tempOut[512];
107 
108     setUpDataTable();
109 
110     log_verbose("Testing u_strlen()\n");
111     if( u_strlen(dataTable[0][0])!= u_strlen(dataTable[0][3]) || u_strlen(dataTable[0][0]) == u_strlen(dataTable[0][2]))
112         log_err("There is an error in u_strlen()");
113 
114     log_verbose("Testing u_memcpy() and u_memcmp()\n");
115 
116     for(i=0;i<3;++i)
117     {
118         for(j=0;j<4;++j)
119         {
120             log_verbose("Testing  %s\n", u_austrcpy(tempOut, dataTable[i][j]));
121             temp[0] = 0;
122             temp[7] = 0xA4; /* Mark the end */
123             u_memcpy(temp,dataTable[i][j], 7);
124 
125             if(temp[7] != 0xA4)
126                 log_err("an error occured in u_memcpy()\n");
127             if(u_memcmp(temp, dataTable[i][j], 7)!=0)
128                 log_err("an error occured in u_memcpy() or u_memcmp()\n");
129         }
130     }
131     if(u_memcmp(dataTable[0][0], dataTable[1][1], 7)==0)
132         log_err("an error occured in u_memcmp()\n");
133 
134     log_verbose("Testing u_memset()\n");
135     nullTemp[0] = 0;
136     nullTemp[7] = 0;
137     u_memset(nullTemp, 0xa4, 7);
138     for (i = 0; i < 7; i++) {
139         if(nullTemp[i] != 0xa4) {
140             log_err("an error occured in u_memset()\n");
141         }
142     }
143     if(nullTemp[7] != 0) {
144         log_err("u_memset() went too far\n");
145     }
146 
147     u_memset(nullTemp, 0, 7);
148     nullTemp[7] = 0xa4;
149     temp[7] = 0;
150     u_memcpy(temp,nullTemp, 7);
151     if(u_memcmp(temp, nullTemp, 7)!=0 || temp[7]!=0)
152         log_err("an error occured in u_memcpy() or u_memcmp()\n");
153 
154 
155     log_verbose("Testing u_memmove()\n");
156     for (i = 0; i < 7; i++) {
157         temp[i] = (UChar)i;
158     }
159     u_memmove(temp + 1, temp, 7);
160     if(temp[0] != 0) {
161         log_err("an error occured in u_memmove()\n");
162     }
163     for (i = 1; i <= 7; i++) {
164         if(temp[i] != (i - 1)) {
165             log_err("an error occured in u_memmove()\n");
166         }
167     }
168 
169     log_verbose("Testing u_strcpy() and u_strcmp()\n");
170 
171     for(i=0;i<3;++i)
172     {
173         for(j=0;j<4;++j)
174         {
175             log_verbose("Testing  %s\n", u_austrcpy(tempOut, dataTable[i][j]));
176             temp[0] = 0;
177             u_strcpy(temp,dataTable[i][j]);
178 
179             if(u_strcmp(temp,dataTable[i][j])!=0)
180                 log_err("something threw an error in u_strcpy() or u_strcmp()\n");
181         }
182     }
183     if(u_strcmp(dataTable[0][0], dataTable[1][1])==0)
184         log_err("an error occured in u_memcmp()\n");
185 
186     log_verbose("testing u_strcat()\n");
187     i=0;
188     for(j=0; j<2;++j)
189     {
190         u_uastrcpy(temp, "");
191         u_strcpy(temp,dataTable[i][j]);
192         u_strcat(temp,dataTable[i+1][j]);
193         if(u_strcmp(temp,dataTable[i+2][j])!=0)
194             log_err("something threw an error in u_strcat()\n");
195 
196     }
197     log_verbose("Testing u_strncmp()\n");
198     for(i=0,j=0;j<4; ++j)
199     {
200         k=u_strlen(dataTable[i][j]);
201         if(u_strncmp(dataTable[i][j],dataTable[i+2][j],k)!=0)
202             log_err("Something threw an error in u_strncmp\n");
203     }
204     if(u_strncmp(dataTable[0][0], dataTable[1][1], 7)==0)
205         log_err("an error occured in u_memcmp()\n");
206 
207 
208     log_verbose("Testing u_strncat\n");
209     for(i=0,j=0;j<4; ++j)
210     {
211         k=u_strlen(dataTable[i][j]);
212 
213         u_uastrcpy(temp,"");
214 
215         if(u_strcmp(u_strncat(temp,dataTable[i+2][j],k),dataTable[i][j])!=0)
216             log_err("something threw an error in u_strncat or u_uastrcpy()\n");
217 
218     }
219 
220     log_verbose("Testing u_strncpy() and u_uastrcpy()\n");
221     for(i=2,j=0;j<4; ++j)
222     {
223         k=u_strlen(dataTable[i][j]);
224         u_strncpy(temp, dataTable[i][j],k);
225         temp[k] = 0xa4;
226 
227         if(u_strncmp(temp, dataTable[i][j],k)!=0)
228             log_err("something threw an error in u_strncpy()\n");
229 
230         if(temp[k] != 0xa4)
231             log_err("something threw an error in u_strncpy()\n");
232 
233         u_memset(temp, 0x3F, (sizeof(temp) / sizeof(UChar)) - 1);
234         u_uastrncpy(temp, raw[i][j], k-1);
235         if(u_strncmp(temp, dataTable[i][j],k-1)!=0)
236             log_err("something threw an error in u_uastrncpy(k-1)\n");
237 
238         if(temp[k-1] != 0x3F)
239             log_err("something threw an error in u_uastrncpy(k-1)\n");
240 
241         u_memset(temp, 0x3F, (sizeof(temp) / sizeof(UChar)) - 1);
242         u_uastrncpy(temp, raw[i][j], k+1);
243         if(u_strcmp(temp, dataTable[i][j])!=0)
244             log_err("something threw an error in u_uastrncpy(k+1)\n");
245 
246         if(temp[k] != 0)
247             log_err("something threw an error in u_uastrncpy(k+1)\n");
248 
249         u_memset(temp, 0x3F, (sizeof(temp) / sizeof(UChar)) - 1);
250         u_uastrncpy(temp, raw[i][j], k);
251         if(u_strncmp(temp, dataTable[i][j], k)!=0)
252             log_err("something threw an error in u_uastrncpy(k)\n");
253 
254         if(temp[k] != 0x3F)
255             log_err("something threw an error in u_uastrncpy(k)\n");
256     }
257 
258     log_verbose("Testing u_strchr() and u_memchr()\n");
259 
260     for(i=2,j=0;j<4;j++)
261     {
262         UChar saveVal = dataTable[i][j][0];
263         UChar *findPtr = u_strchr(dataTable[i][j], 0x005F);
264         int32_t dataSize = (int32_t)(u_strlen(dataTable[i][j]) + 1);
265 
266         log_verbose("%s ", u_austrcpy(tempOut, findPtr));
267 
268         if (findPtr == NULL || *findPtr != 0x005F) {
269             log_err("u_strchr can't find '_' in the string\n");
270         }
271 
272         findPtr = u_strchr32(dataTable[i][j], 0x005F);
273         if (findPtr == NULL || *findPtr != 0x005F) {
274             log_err("u_strchr32 can't find '_' in the string\n");
275         }
276 
277         findPtr = u_strchr(dataTable[i][j], 0);
278         if (findPtr != (&(dataTable[i][j][dataSize - 1]))) {
279             log_err("u_strchr can't find NULL in the string\n");
280         }
281 
282         findPtr = u_strchr32(dataTable[i][j], 0);
283         if (findPtr != (&(dataTable[i][j][dataSize - 1]))) {
284             log_err("u_strchr32 can't find NULL in the string\n");
285         }
286 
287         findPtr = u_memchr(dataTable[i][j], 0, dataSize);
288         if (findPtr != (&(dataTable[i][j][dataSize - 1]))) {
289             log_err("u_memchr can't find NULL in the string\n");
290         }
291 
292         findPtr = u_memchr32(dataTable[i][j], 0, dataSize);
293         if (findPtr != (&(dataTable[i][j][dataSize - 1]))) {
294             log_err("u_memchr32 can't find NULL in the string\n");
295         }
296 
297         dataTable[i][j][0] = 0;
298         /* Make sure we skip over the NULL termination */
299         findPtr = u_memchr(dataTable[i][j], 0x005F, dataSize);
300         if (findPtr == NULL || *findPtr != 0x005F) {
301             log_err("u_memchr can't find '_' in the string\n");
302         }
303 
304         findPtr = u_memchr32(dataTable[i][j], 0x005F, dataSize);
305         if (findPtr == NULL || *findPtr != 0x005F) {
306             log_err("u_memchr32 can't find '_' in the string\n");
307         }
308         findPtr = u_memchr32(dataTable[i][j], 0xFFFD, dataSize);
309         if (findPtr != NULL) {
310             log_err("Should have found NULL when the character is not there.\n");
311         }
312         dataTable[i][j][0] = saveVal;   /* Put it back for the other tests */
313     }
314 
315     /*
316      * test that u_strchr32()
317      * does not find surrogate code points when they are part of matched pairs
318      * (= part of supplementary code points)
319      * Jitterbug 1542
320      */
321     {
322         static const UChar s[]={
323             /*   0       1       2       3       4       5       6       7       8  9 */
324             0x0061, 0xd841, 0xdc02, 0xd841, 0x0062, 0xdc02, 0xd841, 0xdc02, 0x0063, 0
325         };
326 
327         if(u_strchr32(s, 0xd841)!=(s+3) || u_strchr32(s, 0xdc02)!=(s+5)) {
328             log_err("error: u_strchr32(surrogate) finds a partial supplementary code point\n");
329         }
330         if(u_memchr32(s, 0xd841, 9)!=(s+3) || u_memchr32(s, 0xdc02, 9)!=(s+5)) {
331             log_err("error: u_memchr32(surrogate) finds a partial supplementary code point\n");
332         }
333     }
334 
335     log_verbose("Testing u_austrcpy()");
336     u_austrcpy(test,dataTable[0][0]);
337     if(strcmp(test,raw[0][0])!=0)
338         log_err("There is an error in u_austrcpy()");
339 
340 
341     log_verbose("Testing u_strtok_r()");
342     {
343         const char tokString[] = "  ,  1 2 3  AHHHHH! 5.5 6 7    ,        8\n";
344         const char *tokens[] = {",", "1", "2", "3", "AHHHHH!", "5.5", "6", "7", "8\n"};
345         UChar delimBuf[sizeof(test)];
346         UChar currTokenBuf[sizeof(tokString)];
347         UChar *state;
348         uint32_t currToken = 0;
349         UChar *ptr;
350 
351         u_uastrcpy(temp, tokString);
352         u_uastrcpy(delimBuf, " ");
353 
354         ptr = u_strtok_r(temp, delimBuf, &state);
355         u_uastrcpy(delimBuf, " ,");
356         while (ptr != NULL) {
357             u_uastrcpy(currTokenBuf, tokens[currToken]);
358             if (u_strcmp(ptr, currTokenBuf) != 0) {
359                 log_err("u_strtok_r mismatch at %d. Got: %s, Expected: %s\n", currToken, ptr, tokens[currToken]);
360             }
361             ptr = u_strtok_r(NULL, delimBuf, &state);
362             currToken++;
363         }
364 
365         if (currToken != sizeof(tokens)/sizeof(tokens[0])) {
366             log_err("Didn't get correct number of tokens\n");
367         }
368         state = delimBuf;       /* Give it an "invalid" saveState */
369         u_uastrcpy(currTokenBuf, "");
370         if (u_strtok_r(currTokenBuf, delimBuf, &state) != NULL) {
371             log_err("Didn't get NULL for empty string\n");
372         }
373         if (state != NULL) {
374             log_err("State should be NULL for empty string\n");
375         }
376         state = delimBuf;       /* Give it an "invalid" saveState */
377         u_uastrcpy(currTokenBuf, ", ,");
378         if (u_strtok_r(currTokenBuf, delimBuf, &state) != NULL) {
379             log_err("Didn't get NULL for a string of delimiters\n");
380         }
381         if (state != NULL) {
382             log_err("State should be NULL for a string of delimiters\n");
383         }
384 
385         state = delimBuf;       /* Give it an "invalid" saveState */
386         u_uastrcpy(currTokenBuf, "q, ,");
387         if (u_strtok_r(currTokenBuf, delimBuf, &state) == NULL) {
388             log_err("Got NULL for a string that does not begin with delimiters\n");
389         }
390         if (u_strtok_r(NULL, delimBuf, &state) != NULL) {
391             log_err("Didn't get NULL for a string that ends in delimiters\n");
392         }
393         if (state != NULL) {
394             log_err("State should be NULL for empty string\n");
395         }
396 
397         state = delimBuf;       /* Give it an "invalid" saveState */
398         u_uastrcpy(currTokenBuf, tokString);
399         u_uastrcpy(temp, tokString);
400         u_uastrcpy(delimBuf, "q");  /* Give it a delimiter that it can't find. */
401         ptr = u_strtok_r(currTokenBuf, delimBuf, &state);
402         if (ptr == NULL || u_strcmp(ptr, temp) != 0) {
403             log_err("Should have recieved the same string when there are no delimiters\n");
404         }
405         if (u_strtok_r(NULL, delimBuf, &state) != NULL) {
406             log_err("Should not have found another token in a one token string\n");
407         }
408     }
409 
410     /* test u_strcmpCodePointOrder() */
411     {
412         /* these strings are in ascending order */
413         static const UChar strings[][4]={
414             { 0x61, 0 },                    /* U+0061 */
415             { 0x20ac, 0xd801, 0 },          /* U+20ac U+d801 */
416             { 0x20ac, 0xd800, 0xdc00, 0 },  /* U+20ac U+10000 */
417             { 0xd800, 0 },                  /* U+d800 */
418             { 0xd800, 0xff61, 0 },          /* U+d800 U+ff61 */
419             { 0xdfff, 0 },                  /* U+dfff */
420             { 0xff61, 0xdfff, 0 },          /* U+ff61 U+dfff */
421             { 0xff61, 0xd800, 0xdc02, 0 },  /* U+ff61 U+10002 */
422             { 0xd800, 0xdc02, 0 },          /* U+10002 */
423             { 0xd84d, 0xdc56, 0 }           /* U+23456 */
424         };
425 
426         UCharIterator iter1, iter2;
427         int32_t len1, len2, r1, r2;
428 
429         for(i=0; i<(sizeof(strings)/sizeof(strings[0])-1); ++i) {
430             if(u_strcmpCodePointOrder(strings[i], strings[i+1])>=0) {
431                 log_err("error: u_strcmpCodePointOrder() fails for string %d and the following one\n", i);
432             }
433             if(u_strncmpCodePointOrder(strings[i], strings[i+1], 10)>=0) {
434                 log_err("error: u_strncmpCodePointOrder() fails for string %d and the following one\n", i);
435             }
436 
437             /* There are at least 2 UChars in each string - verify that strncmp()==memcmp(). */
438             if(u_strncmpCodePointOrder(strings[i], strings[i+1], 2)!=u_memcmpCodePointOrder(strings[i], strings[i+1], 2)) {
439                 log_err("error: u_strncmpCodePointOrder(2)!=u_memcmpCodePointOrder(2) for string %d and the following one\n", i);
440             }
441 
442             /* test u_strCompare(TRUE) */
443             len1=u_strlen(strings[i]);
444             len2=u_strlen(strings[i+1]);
445             if( u_strCompare(strings[i], -1, strings[i+1], -1, TRUE)>=0 ||
446                 u_strCompare(strings[i], -1, strings[i+1], len2, TRUE)>=0 ||
447                 u_strCompare(strings[i], len1, strings[i+1], -1, TRUE)>=0 ||
448                 u_strCompare(strings[i], len1, strings[i+1], len2, TRUE)>=0
449             ) {
450                 log_err("error: u_strCompare(code point order) fails for string %d and the following one\n", i);
451             }
452 
453             /* test u_strCompare(FALSE) */
454             r1=u_strCompare(strings[i], -1, strings[i+1], -1, FALSE);
455             r2=u_strcmp(strings[i], strings[i+1]);
456             if(_SIGN(r1)!=_SIGN(r2)) {
457                 log_err("error: u_strCompare(code unit order)!=u_strcmp() for string %d and the following one\n", i);
458             }
459 
460             /* test u_strCompareIter() */
461             uiter_setString(&iter1, strings[i], len1);
462             uiter_setString(&iter2, strings[i+1], len2);
463             if(u_strCompareIter(&iter1, &iter2, TRUE)>=0) {
464                 log_err("error: u_strCompareIter(code point order) fails for string %d and the following one\n", i);
465             }
466             r1=u_strCompareIter(&iter1, &iter2, FALSE);
467             if(_SIGN(r1)!=_SIGN(u_strcmp(strings[i], strings[i+1]))) {
468                 log_err("error: u_strCompareIter(code unit order)!=u_strcmp() for string %d and the following one\n", i);
469             }
470         }
471     }
472 
473     cleanUpDataTable();
474 }
475 
TestStringSearching()476 static void TestStringSearching()
477 {
478     const UChar testString[] = {0x0061, 0x0062, 0x0063, 0x0064, 0x0064, 0x0061, 0};
479     const UChar testSurrogateString[] = {0xdbff, 0x0061, 0x0062, 0xdbff, 0xdfff, 0x0063, 0x0064, 0x0064, 0xdbff, 0xdfff, 0xdb00, 0xdf00, 0x0061, 0};
480     const UChar surrMatchSet1[] = {0xdbff, 0xdfff, 0};
481     const UChar surrMatchSet2[] = {0x0061, 0x0062, 0xdbff, 0xdfff, 0};
482     const UChar surrMatchSet3[] = {0xdb00, 0xdf00, 0xdbff, 0xdfff, 0};
483     const UChar surrMatchSet4[] = {0x0000};
484     const UChar surrMatchSetBad[] = {0xdbff, 0x0061, 0};
485     const UChar surrMatchSetBad2[] = {0x0061, 0xdbff, 0};
486     const UChar surrMatchSetBad3[] = {0xdbff, 0x0061, 0x0062, 0xdbff, 0xdfff, 0};   /* has partial surrogate */
487     const UChar
488         empty[] = { 0 },
489         a[] = { 0x61, 0 },
490         ab[] = { 0x61, 0x62, 0 },
491         ba[] = { 0x62, 0x61, 0 },
492         abcd[] = { 0x61, 0x62, 0x63, 0x64, 0 },
493         cd[] = { 0x63, 0x64, 0 },
494         dc[] = { 0x64, 0x63, 0 },
495         cdh[] = { 0x63, 0x64, 0x68, 0 },
496         f[] = { 0x66, 0 },
497         fg[] = { 0x66, 0x67, 0 },
498         gf[] = { 0x67, 0x66, 0 };
499 
500     log_verbose("Testing u_strpbrk()");
501 
502     if (u_strpbrk(testString, a) != &testString[0]) {
503         log_err("u_strpbrk couldn't find first letter a.\n");
504     }
505     if (u_strpbrk(testString, dc) != &testString[2]) {
506         log_err("u_strpbrk couldn't find d or c.\n");
507     }
508     if (u_strpbrk(testString, cd) != &testString[2]) {
509         log_err("u_strpbrk couldn't find c or d.\n");
510     }
511     if (u_strpbrk(testString, cdh) != &testString[2]) {
512         log_err("u_strpbrk couldn't find c, d or h.\n");
513     }
514     if (u_strpbrk(testString, f) != NULL) {
515         log_err("u_strpbrk didn't return NULL for \"f\".\n");
516     }
517     if (u_strpbrk(testString, fg) != NULL) {
518         log_err("u_strpbrk didn't return NULL for \"fg\".\n");
519     }
520     if (u_strpbrk(testString, gf) != NULL) {
521         log_err("u_strpbrk didn't return NULL for \"gf\".\n");
522     }
523     if (u_strpbrk(testString, empty) != NULL) {
524         log_err("u_strpbrk didn't return NULL for \"\".\n");
525     }
526 
527     log_verbose("Testing u_strpbrk() with surrogates");
528 
529     if (u_strpbrk(testSurrogateString, a) != &testSurrogateString[1]) {
530         log_err("u_strpbrk couldn't find first letter a.\n");
531     }
532     if (u_strpbrk(testSurrogateString, dc) != &testSurrogateString[5]) {
533         log_err("u_strpbrk couldn't find d or c.\n");
534     }
535     if (u_strpbrk(testSurrogateString, cd) != &testSurrogateString[5]) {
536         log_err("u_strpbrk couldn't find c or d.\n");
537     }
538     if (u_strpbrk(testSurrogateString, cdh) != &testSurrogateString[5]) {
539         log_err("u_strpbrk couldn't find c, d or h.\n");
540     }
541     if (u_strpbrk(testSurrogateString, f) != NULL) {
542         log_err("u_strpbrk didn't return NULL for \"f\".\n");
543     }
544     if (u_strpbrk(testSurrogateString, fg) != NULL) {
545         log_err("u_strpbrk didn't return NULL for \"fg\".\n");
546     }
547     if (u_strpbrk(testSurrogateString, gf) != NULL) {
548         log_err("u_strpbrk didn't return NULL for \"gf\".\n");
549     }
550     if (u_strpbrk(testSurrogateString, surrMatchSet1) != &testSurrogateString[3]) {
551         log_err("u_strpbrk couldn't find \"0xdbff, 0xdfff\".\n");
552     }
553     if (u_strpbrk(testSurrogateString, surrMatchSet2) != &testSurrogateString[1]) {
554         log_err("u_strpbrk couldn't find \"0xdbff, a, b, 0xdbff, 0xdfff\".\n");
555     }
556     if (u_strpbrk(testSurrogateString, surrMatchSet3) != &testSurrogateString[3]) {
557         log_err("u_strpbrk couldn't find \"0xdb00, 0xdf00, 0xdbff, 0xdfff\".\n");
558     }
559     if (u_strpbrk(testSurrogateString, surrMatchSet4) != NULL) {
560         log_err("u_strpbrk should have returned NULL for empty string.\n");
561     }
562     if (u_strpbrk(testSurrogateString, surrMatchSetBad) != &testSurrogateString[0]) {
563         log_err("u_strpbrk should have found bad surrogate.\n");
564     }
565 
566     log_verbose("Testing u_strcspn()");
567 
568     if (u_strcspn(testString, a) != 0) {
569         log_err("u_strcspn couldn't find first letter a.\n");
570     }
571     if (u_strcspn(testString, dc) != 2) {
572         log_err("u_strcspn couldn't find d or c.\n");
573     }
574     if (u_strcspn(testString, cd) != 2) {
575         log_err("u_strcspn couldn't find c or d.\n");
576     }
577     if (u_strcspn(testString, cdh) != 2) {
578         log_err("u_strcspn couldn't find c, d or h.\n");
579     }
580     if (u_strcspn(testString, f) != u_strlen(testString)) {
581         log_err("u_strcspn didn't return NULL for \"f\".\n");
582     }
583     if (u_strcspn(testString, fg) != u_strlen(testString)) {
584         log_err("u_strcspn didn't return NULL for \"fg\".\n");
585     }
586     if (u_strcspn(testString, gf) != u_strlen(testString)) {
587         log_err("u_strcspn didn't return NULL for \"gf\".\n");
588     }
589 
590     log_verbose("Testing u_strcspn() with surrogates");
591 
592     if (u_strcspn(testSurrogateString, a) != 1) {
593         log_err("u_strcspn couldn't find first letter a.\n");
594     }
595     if (u_strcspn(testSurrogateString, dc) != 5) {
596         log_err("u_strcspn couldn't find d or c.\n");
597     }
598     if (u_strcspn(testSurrogateString, cd) != 5) {
599         log_err("u_strcspn couldn't find c or d.\n");
600     }
601     if (u_strcspn(testSurrogateString, cdh) != 5) {
602         log_err("u_strcspn couldn't find c, d or h.\n");
603     }
604     if (u_strcspn(testSurrogateString, f) != u_strlen(testSurrogateString)) {
605         log_err("u_strcspn didn't return NULL for \"f\".\n");
606     }
607     if (u_strcspn(testSurrogateString, fg) != u_strlen(testSurrogateString)) {
608         log_err("u_strcspn didn't return NULL for \"fg\".\n");
609     }
610     if (u_strcspn(testSurrogateString, gf) != u_strlen(testSurrogateString)) {
611         log_err("u_strcspn didn't return NULL for \"gf\".\n");
612     }
613     if (u_strcspn(testSurrogateString, surrMatchSet1) != 3) {
614         log_err("u_strcspn couldn't find \"0xdbff, 0xdfff\".\n");
615     }
616     if (u_strcspn(testSurrogateString, surrMatchSet2) != 1) {
617         log_err("u_strcspn couldn't find \"a, b, 0xdbff, 0xdfff\".\n");
618     }
619     if (u_strcspn(testSurrogateString, surrMatchSet3) != 3) {
620         log_err("u_strcspn couldn't find \"0xdb00, 0xdf00, 0xdbff, 0xdfff\".\n");
621     }
622     if (u_strcspn(testSurrogateString, surrMatchSet4) != u_strlen(testSurrogateString)) {
623         log_err("u_strcspn should have returned strlen for empty string.\n");
624     }
625 
626 
627     log_verbose("Testing u_strspn()");
628 
629     if (u_strspn(testString, a) != 1) {
630         log_err("u_strspn couldn't skip first letter a.\n");
631     }
632     if (u_strspn(testString, ab) != 2) {
633         log_err("u_strspn couldn't skip a or b.\n");
634     }
635     if (u_strspn(testString, ba) != 2) {
636         log_err("u_strspn couldn't skip a or b.\n");
637     }
638     if (u_strspn(testString, f) != 0) {
639         log_err("u_strspn didn't return 0 for \"f\".\n");
640     }
641     if (u_strspn(testString, dc) != 0) {
642         log_err("u_strspn couldn't find first letter a (skip d or c).\n");
643     }
644     if (u_strspn(testString, abcd) != u_strlen(testString)) {
645         log_err("u_strspn couldn't skip over the whole string.\n");
646     }
647     if (u_strspn(testString, empty) != 0) {
648         log_err("u_strspn should have returned 0 for empty string.\n");
649     }
650 
651     log_verbose("Testing u_strspn() with surrogates");
652     if (u_strspn(testSurrogateString, surrMatchSetBad) != 2) {
653         log_err("u_strspn couldn't skip 0xdbff or a.\n");
654     }
655     if (u_strspn(testSurrogateString, surrMatchSetBad2) != 2) {
656         log_err("u_strspn couldn't skip 0xdbff or a.\n");
657     }
658     if (u_strspn(testSurrogateString, f) != 0) {
659         log_err("u_strspn couldn't skip d or c (skip first letter).\n");
660     }
661     if (u_strspn(testSurrogateString, dc) != 0) {
662         log_err("u_strspn couldn't skip d or c (skip first letter).\n");
663     }
664     if (u_strspn(testSurrogateString, cd) != 0) {
665         log_err("u_strspn couldn't skip d or c (skip first letter).\n");
666     }
667     if (u_strspn(testSurrogateString, testSurrogateString) != u_strlen(testSurrogateString)) {
668         log_err("u_strspn couldn't skip whole string.\n");
669     }
670     if (u_strspn(testSurrogateString, surrMatchSet1) != 0) {
671         log_err("u_strspn couldn't skip \"0xdbff, 0xdfff\" (get first letter).\n");
672     }
673     if (u_strspn(testSurrogateString, surrMatchSetBad3) != 5) {
674         log_err("u_strspn couldn't skip \"0xdbff, a, b, 0xdbff, 0xdfff\".\n");
675     }
676     if (u_strspn(testSurrogateString, surrMatchSet4) != 0) {
677         log_err("u_strspn should have returned 0 for empty string.\n");
678     }
679 }
680 
681 /*
682  * All binary Unicode string searches should behave the same for equivalent input.
683  * See Jitterbug 2145.
684  * There are some new functions, too - just test them all.
685  */
686 static void
TestSurrogateSearching()687 TestSurrogateSearching() {
688     static const UChar s[]={
689         /* 0       1       2     3       4     5       6     7       8       9    10 11 */
690         0x61, 0xd801, 0xdc02, 0x61, 0xdc02, 0x61, 0xd801, 0x61, 0xd801, 0xdc02, 0x61, 0
691     }, sub_a[]={
692         0x61, 0
693     }, sub_b[]={
694         0x62, 0
695     }, sub_lead[]={
696         0xd801, 0
697     }, sub_trail[]={
698         0xdc02, 0
699     }, sub_supp[]={
700         0xd801, 0xdc02, 0
701     }, sub_supp2[]={
702         0xd801, 0xdc03, 0
703     }, sub_a_lead[]={
704         0x61, 0xd801, 0
705     }, sub_trail_a[]={
706         0xdc02, 0x61, 0
707     }, sub_aba[]={
708         0x61, 0x62, 0x61, 0
709     };
710     static const UChar a=0x61, b=0x62, lead=0xd801, trail=0xdc02, nul=0;
711     static const UChar32 supp=0x10402, supp2=0x10403, ill=0x123456;
712 
713     const UChar *first, *last;
714 
715     /* search for NUL code point: find end of string */
716     first=s+u_strlen(s);
717 
718     if(
719         first!=u_strchr(s, nul) ||
720         first!=u_strchr32(s, nul) ||
721         first!=u_memchr(s, nul, UPRV_LENGTHOF(s)) ||
722         first!=u_memchr32(s, nul, UPRV_LENGTHOF(s)) ||
723         first!=u_strrchr(s, nul) ||
724         first!=u_strrchr32(s, nul) ||
725         first!=u_memrchr(s, nul, UPRV_LENGTHOF(s)) ||
726         first!=u_memrchr32(s, nul, UPRV_LENGTHOF(s))
727     ) {
728         log_err("error: one of the u_str[|mem][r]chr[32](s, nul) does not find the terminator of s\n");
729     }
730 
731     /* search for empty substring: find beginning of string */
732     if(
733         s!=u_strstr(s, &nul) ||
734         s!=u_strFindFirst(s, -1, &nul, -1) ||
735         s!=u_strFindFirst(s, -1, &nul, 0) ||
736         s!=u_strFindFirst(s, UPRV_LENGTHOF(s), &nul, -1) ||
737         s!=u_strFindFirst(s, UPRV_LENGTHOF(s), &nul, 0) ||
738         s!=u_strrstr(s, &nul) ||
739         s!=u_strFindLast(s, -1, &nul, -1) ||
740         s!=u_strFindLast(s, -1, &nul, 0) ||
741         s!=u_strFindLast(s, UPRV_LENGTHOF(s), &nul, -1) ||
742         s!=u_strFindLast(s, UPRV_LENGTHOF(s), &nul, 0)
743     ) {
744         log_err("error: one of the u_str[str etc](s, \"\") does not find s itself\n");
745     }
746 
747     /* find 'a' in s[1..10[ */
748     first=s+3;
749     last=s+7;
750     if(
751         first!=u_strchr(s+1, a) ||
752         first!=u_strchr32(s+1, a) ||
753         first!=u_memchr(s+1, a, 9) ||
754         first!=u_memchr32(s+1, a, 9) ||
755         first!=u_strstr(s+1, sub_a) ||
756         first!=u_strFindFirst(s+1, -1, sub_a, -1) ||
757         first!=u_strFindFirst(s+1, -1, &a, 1) ||
758         first!=u_strFindFirst(s+1, 9, sub_a, -1) ||
759         first!=u_strFindFirst(s+1, 9, &a, 1) ||
760         (s+10)!=u_strrchr(s+1, a) ||
761         (s+10)!=u_strrchr32(s+1, a) ||
762         last!=u_memrchr(s+1, a, 9) ||
763         last!=u_memrchr32(s+1, a, 9) ||
764         (s+10)!=u_strrstr(s+1, sub_a) ||
765         (s+10)!=u_strFindLast(s+1, -1, sub_a, -1) ||
766         (s+10)!=u_strFindLast(s+1, -1, &a, 1) ||
767         last!=u_strFindLast(s+1, 9, sub_a, -1) ||
768         last!=u_strFindLast(s+1, 9, &a, 1)
769     ) {
770         log_err("error: one of the u_str[chr etc]('a') does not find the correct place\n");
771     }
772 
773     /* do not find 'b' in s[1..10[ */
774     if(
775         NULL!=u_strchr(s+1, b) ||
776         NULL!=u_strchr32(s+1, b) ||
777         NULL!=u_memchr(s+1, b, 9) ||
778         NULL!=u_memchr32(s+1, b, 9) ||
779         NULL!=u_strstr(s+1, sub_b) ||
780         NULL!=u_strFindFirst(s+1, -1, sub_b, -1) ||
781         NULL!=u_strFindFirst(s+1, -1, &b, 1) ||
782         NULL!=u_strFindFirst(s+1, 9, sub_b, -1) ||
783         NULL!=u_strFindFirst(s+1, 9, &b, 1) ||
784         NULL!=u_strrchr(s+1, b) ||
785         NULL!=u_strrchr32(s+1, b) ||
786         NULL!=u_memrchr(s+1, b, 9) ||
787         NULL!=u_memrchr32(s+1, b, 9) ||
788         NULL!=u_strrstr(s+1, sub_b) ||
789         NULL!=u_strFindLast(s+1, -1, sub_b, -1) ||
790         NULL!=u_strFindLast(s+1, -1, &b, 1) ||
791         NULL!=u_strFindLast(s+1, 9, sub_b, -1) ||
792         NULL!=u_strFindLast(s+1, 9, &b, 1)
793     ) {
794         log_err("error: one of the u_str[chr etc]('b') incorrectly finds something\n");
795     }
796 
797     /* do not find a non-code point in s[1..10[ */
798     if(
799         NULL!=u_strchr32(s+1, ill) ||
800         NULL!=u_memchr32(s+1, ill, 9) ||
801         NULL!=u_strrchr32(s+1, ill) ||
802         NULL!=u_memrchr32(s+1, ill, 9)
803     ) {
804         log_err("error: one of the u_str[chr etc](illegal code point) incorrectly finds something\n");
805     }
806 
807     /* find U+d801 in s[1..10[ */
808     first=s+6;
809     if(
810         first!=u_strchr(s+1, lead) ||
811         first!=u_strchr32(s+1, lead) ||
812         first!=u_memchr(s+1, lead, 9) ||
813         first!=u_memchr32(s+1, lead, 9) ||
814         first!=u_strstr(s+1, sub_lead) ||
815         first!=u_strFindFirst(s+1, -1, sub_lead, -1) ||
816         first!=u_strFindFirst(s+1, -1, &lead, 1) ||
817         first!=u_strFindFirst(s+1, 9, sub_lead, -1) ||
818         first!=u_strFindFirst(s+1, 9, &lead, 1) ||
819         first!=u_strrchr(s+1, lead) ||
820         first!=u_strrchr32(s+1, lead) ||
821         first!=u_memrchr(s+1, lead, 9) ||
822         first!=u_memrchr32(s+1, lead, 9) ||
823         first!=u_strrstr(s+1, sub_lead) ||
824         first!=u_strFindLast(s+1, -1, sub_lead, -1) ||
825         first!=u_strFindLast(s+1, -1, &lead, 1) ||
826         first!=u_strFindLast(s+1, 9, sub_lead, -1) ||
827         first!=u_strFindLast(s+1, 9, &lead, 1)
828     ) {
829         log_err("error: one of the u_str[chr etc](U+d801) does not find the correct place\n");
830     }
831 
832     /* find U+dc02 in s[1..10[ */
833     first=s+4;
834     if(
835         first!=u_strchr(s+1, trail) ||
836         first!=u_strchr32(s+1, trail) ||
837         first!=u_memchr(s+1, trail, 9) ||
838         first!=u_memchr32(s+1, trail, 9) ||
839         first!=u_strstr(s+1, sub_trail) ||
840         first!=u_strFindFirst(s+1, -1, sub_trail, -1) ||
841         first!=u_strFindFirst(s+1, -1, &trail, 1) ||
842         first!=u_strFindFirst(s+1, 9, sub_trail, -1) ||
843         first!=u_strFindFirst(s+1, 9, &trail, 1) ||
844         first!=u_strrchr(s+1, trail) ||
845         first!=u_strrchr32(s+1, trail) ||
846         first!=u_memrchr(s+1, trail, 9) ||
847         first!=u_memrchr32(s+1, trail, 9) ||
848         first!=u_strrstr(s+1, sub_trail) ||
849         first!=u_strFindLast(s+1, -1, sub_trail, -1) ||
850         first!=u_strFindLast(s+1, -1, &trail, 1) ||
851         first!=u_strFindLast(s+1, 9, sub_trail, -1) ||
852         first!=u_strFindLast(s+1, 9, &trail, 1)
853     ) {
854         log_err("error: one of the u_str[chr etc](U+dc02) does not find the correct place\n");
855     }
856 
857     /* find U+10402 in s[1..10[ */
858     first=s+1;
859     last=s+8;
860     if(
861         first!=u_strchr32(s+1, supp) ||
862         first!=u_memchr32(s+1, supp, 9) ||
863         first!=u_strstr(s+1, sub_supp) ||
864         first!=u_strFindFirst(s+1, -1, sub_supp, -1) ||
865         first!=u_strFindFirst(s+1, -1, sub_supp, 2) ||
866         first!=u_strFindFirst(s+1, 9, sub_supp, -1) ||
867         first!=u_strFindFirst(s+1, 9, sub_supp, 2) ||
868         last!=u_strrchr32(s+1, supp) ||
869         last!=u_memrchr32(s+1, supp, 9) ||
870         last!=u_strrstr(s+1, sub_supp) ||
871         last!=u_strFindLast(s+1, -1, sub_supp, -1) ||
872         last!=u_strFindLast(s+1, -1, sub_supp, 2) ||
873         last!=u_strFindLast(s+1, 9, sub_supp, -1) ||
874         last!=u_strFindLast(s+1, 9, sub_supp, 2)
875     ) {
876         log_err("error: one of the u_str[chr etc](U+10402) does not find the correct place\n");
877     }
878 
879     /* do not find U+10402 in a single UChar */
880     if(
881         NULL!=u_memchr32(s+1, supp, 1) ||
882         NULL!=u_strFindFirst(s+1, 1, sub_supp, -1) ||
883         NULL!=u_strFindFirst(s+1, 1, sub_supp, 2) ||
884         NULL!=u_memrchr32(s+1, supp, 1) ||
885         NULL!=u_strFindLast(s+1, 1, sub_supp, -1) ||
886         NULL!=u_strFindLast(s+1, 1, sub_supp, 2) ||
887         NULL!=u_memrchr32(s+2, supp, 1) ||
888         NULL!=u_strFindLast(s+2, 1, sub_supp, -1) ||
889         NULL!=u_strFindLast(s+2, 1, sub_supp, 2)
890     ) {
891         log_err("error: one of the u_str[chr etc](U+10402) incorrectly finds a supplementary c.p. in a single UChar\n");
892     }
893 
894     /* do not find U+10403 in s[1..10[ */
895     if(
896         NULL!=u_strchr32(s+1, supp2) ||
897         NULL!=u_memchr32(s+1, supp2, 9) ||
898         NULL!=u_strstr(s+1, sub_supp2) ||
899         NULL!=u_strFindFirst(s+1, -1, sub_supp2, -1) ||
900         NULL!=u_strFindFirst(s+1, -1, sub_supp2, 2) ||
901         NULL!=u_strFindFirst(s+1, 9, sub_supp2, -1) ||
902         NULL!=u_strFindFirst(s+1, 9, sub_supp2, 2) ||
903         NULL!=u_strrchr32(s+1, supp2) ||
904         NULL!=u_memrchr32(s+1, supp2, 9) ||
905         NULL!=u_strrstr(s+1, sub_supp2) ||
906         NULL!=u_strFindLast(s+1, -1, sub_supp2, -1) ||
907         NULL!=u_strFindLast(s+1, -1, sub_supp2, 2) ||
908         NULL!=u_strFindLast(s+1, 9, sub_supp2, -1) ||
909         NULL!=u_strFindLast(s+1, 9, sub_supp2, 2)
910     ) {
911         log_err("error: one of the u_str[chr etc](U+10403) incorrectly finds something\n");
912     }
913 
914     /* find <0061 d801> in s[1..10[ */
915     first=s+5;
916     if(
917         first!=u_strstr(s+1, sub_a_lead) ||
918         first!=u_strFindFirst(s+1, -1, sub_a_lead, -1) ||
919         first!=u_strFindFirst(s+1, -1, sub_a_lead, 2) ||
920         first!=u_strFindFirst(s+1, 9, sub_a_lead, -1) ||
921         first!=u_strFindFirst(s+1, 9, sub_a_lead, 2) ||
922         first!=u_strrstr(s+1, sub_a_lead) ||
923         first!=u_strFindLast(s+1, -1, sub_a_lead, -1) ||
924         first!=u_strFindLast(s+1, -1, sub_a_lead, 2) ||
925         first!=u_strFindLast(s+1, 9, sub_a_lead, -1) ||
926         first!=u_strFindLast(s+1, 9, sub_a_lead, 2)
927     ) {
928         log_err("error: one of the u_str[str etc](<0061 d801>) does not find the correct place\n");
929     }
930 
931     /* find <dc02 0061> in s[1..10[ */
932     first=s+4;
933     if(
934         first!=u_strstr(s+1, sub_trail_a) ||
935         first!=u_strFindFirst(s+1, -1, sub_trail_a, -1) ||
936         first!=u_strFindFirst(s+1, -1, sub_trail_a, 2) ||
937         first!=u_strFindFirst(s+1, 9, sub_trail_a, -1) ||
938         first!=u_strFindFirst(s+1, 9, sub_trail_a, 2) ||
939         first!=u_strrstr(s+1, sub_trail_a) ||
940         first!=u_strFindLast(s+1, -1, sub_trail_a, -1) ||
941         first!=u_strFindLast(s+1, -1, sub_trail_a, 2) ||
942         first!=u_strFindLast(s+1, 9, sub_trail_a, -1) ||
943         first!=u_strFindLast(s+1, 9, sub_trail_a, 2)
944     ) {
945         log_err("error: one of the u_str[str etc](<dc02 0061>) does not find the correct place\n");
946     }
947 
948     /* do not find "aba" in s[1..10[ */
949     if(
950         NULL!=u_strstr(s+1, sub_aba) ||
951         NULL!=u_strFindFirst(s+1, -1, sub_aba, -1) ||
952         NULL!=u_strFindFirst(s+1, -1, sub_aba, 3) ||
953         NULL!=u_strFindFirst(s+1, 9, sub_aba, -1) ||
954         NULL!=u_strFindFirst(s+1, 9, sub_aba, 3) ||
955         NULL!=u_strrstr(s+1, sub_aba) ||
956         NULL!=u_strFindLast(s+1, -1, sub_aba, -1) ||
957         NULL!=u_strFindLast(s+1, -1, sub_aba, 3) ||
958         NULL!=u_strFindLast(s+1, 9, sub_aba, -1) ||
959         NULL!=u_strFindLast(s+1, 9, sub_aba, 3)
960     ) {
961         log_err("error: one of the u_str[str etc](\"aba\") incorrectly finds something\n");
962     }
963 }
964 
TestStringCopy()965 static void TestStringCopy()
966 {
967     UChar temp[40];
968     UChar *result=0;
969     UChar subString[5];
970     UChar uchars[]={0x61, 0x62, 0x63, 0x00};
971     char  charOut[40];
972     char  chars[]="abc";    /* needs default codepage */
973 
974     log_verbose("Testing u_uastrncpy() and u_uastrcpy()");
975 
976     u_uastrcpy(temp, "abc");
977     if(u_strcmp(temp, uchars) != 0) {
978         log_err("There is an error in u_uastrcpy() Expected %s Got %s\n", austrdup(uchars), austrdup(temp));
979     }
980 
981     temp[0] = 0xFB; /* load garbage into it */
982     temp[1] = 0xFB;
983     temp[2] = 0xFB;
984     temp[3] = 0xFB;
985 
986     u_uastrncpy(temp, "abcabcabc", 3);
987     if(u_strncmp(uchars, temp, 3) != 0){
988         log_err("There is an error in u_uastrncpy() Expected %s Got %s\n", austrdup(uchars), austrdup(temp));
989     }
990     if(temp[3] != 0xFB) {
991         log_err("u_uastrncpy wrote past it's bounds. Expected undisturbed byte at 3\n");
992     }
993 
994     charOut[0] = (char)0x7B; /* load garbage into it */
995     charOut[1] = (char)0x7B;
996     charOut[2] = (char)0x7B;
997     charOut[3] = (char)0x7B;
998 
999     temp[0] = 0x0061;
1000     temp[1] = 0x0062;
1001     temp[2] = 0x0063;
1002     temp[3] = 0x0061;
1003     temp[4] = 0x0062;
1004     temp[5] = 0x0063;
1005     temp[6] = 0x0000;
1006 
1007     u_austrncpy(charOut, temp, 3);
1008     if(strncmp(chars, charOut, 3) != 0){
1009         log_err("There is an error in u_austrncpy() Expected %s Got %s\n", austrdup(uchars), austrdup(temp));
1010     }
1011     if(charOut[3] != (char)0x7B) {
1012         log_err("u_austrncpy wrote past it's bounds. Expected undisturbed byte at 3\n");
1013     }
1014 
1015     /*Testing u_strchr()*/
1016     log_verbose("Testing u_strchr\n");
1017     temp[0]=0x42;
1018     temp[1]=0x62;
1019     temp[2]=0x62;
1020     temp[3]=0x63;
1021     temp[4]=0xd841;
1022     temp[5]=0xd841;
1023     temp[6]=0xdc02;
1024     temp[7]=0;
1025     result=u_strchr(temp, (UChar)0x62);
1026     if(result != temp+1){
1027         log_err("There is an error in u_strchr() Expected match at position 1 Got %ld (pointer 0x%lx)\n", result-temp, result);
1028     }
1029     /*Testing u_strstr()*/
1030     log_verbose("Testing u_strstr\n");
1031     subString[0]=0x62;
1032     subString[1]=0x63;
1033     subString[2]=0;
1034     result=u_strstr(temp, subString);
1035     if(result != temp+2){
1036         log_err("There is an error in u_strstr() Expected match at position 2 Got %ld (pointer 0x%lx)\n", result-temp, result);
1037     }
1038     result=u_strstr(temp, subString+2); /* subString+2 is an empty string */
1039     if(result != temp){
1040         log_err("There is an error in u_strstr() Expected match at position 0 Got %ld (pointer 0x%lx)\n", result-temp, result);
1041     }
1042     result=u_strstr(subString, temp);
1043     if(result != NULL){
1044         log_err("There is an error in u_strstr() Expected NULL \"not found\" Got non-NULL \"found\" result\n");
1045     }
1046 
1047     /*Testing u_strchr32*/
1048     log_verbose("Testing u_strchr32\n");
1049     result=u_strchr32(temp, (UChar32)0x62);
1050     if(result != temp+1){
1051         log_err("There is an error in u_strchr32() Expected match at position 1 Got %ld (pointer 0x%lx)\n", result-temp, result);
1052     }
1053     result=u_strchr32(temp, (UChar32)0xfb);
1054     if(result != NULL){
1055         log_err("There is an error in u_strchr32() Expected NULL \"not found\" Got non-NULL \"found\" result\n");
1056     }
1057     result=u_strchr32(temp, (UChar32)0x20402);
1058     if(result != temp+5){
1059         log_err("There is an error in u_strchr32() Expected match at position 5 Got %ld (pointer 0x%lx)\n", result-temp, result);
1060     }
1061 
1062     temp[7]=0xfc00;
1063     result=u_memchr32(temp, (UChar32)0x20402, 7);
1064     if(result != temp+5){
1065         log_err("There is an error in u_memchr32() Expected match at position 5 Got %ld (pointer 0x%lx)\n", result-temp, result);
1066     }
1067     result=u_memchr32(temp, (UChar32)0x20402, 6);
1068     if(result != NULL){
1069         log_err("There is an error in u_memchr32() Expected no match Got %ld (pointer 0x%lx)\n", result-temp, result);
1070     }
1071     result=u_memchr32(temp, (UChar32)0x20402, 1);
1072     if(result != NULL){
1073         log_err("There is an error in u_memchr32() Expected no match Got %ld (pointer 0x%lx)\n", result-temp, result);
1074     }
1075     result=u_memchr32(temp, (UChar32)0xfc00, 8);
1076     if(result != temp+7){
1077         log_err("There is an error in u_memchr32() Expected match at position 7 Got %ld (pointer 0x%lx)\n", result-temp, result);
1078     }
1079 }
1080 
1081 /* test u_unescape() and u_unescapeAt() ------------------------------------- */
1082 
1083 static void
TestUnescape()1084 TestUnescape() {
1085     static UChar buffer[200];
1086 
1087     static const char* input =
1088         "Sch\\u00f6nes Auto: \\u20ac 11240.\\fPrivates Zeichen: \\U00102345\\e\\cC\\n \\x1b\\x{263a}";
1089 
1090     static const UChar expect[]={
1091         0x53, 0x63, 0x68, 0xf6, 0x6e, 0x65, 0x73, 0x20, 0x41, 0x75, 0x74, 0x6f, 0x3a, 0x20,
1092         0x20ac, 0x20, 0x31, 0x31, 0x32, 0x34, 0x30, 0x2e, 0x0c,
1093         0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x73, 0x20,
1094         0x5a, 0x65, 0x69, 0x63, 0x68, 0x65, 0x6e, 0x3a, 0x20, 0xdbc8, 0xdf45, 0x1b, 0x03, 0x0a, 0x20, 0x1b, 0x263A, 0
1095     };
1096     static const int32_t explength = sizeof(expect)/sizeof(expect[0])-1;
1097     int32_t length;
1098 
1099     /* test u_unescape() */
1100     length=u_unescape(input, buffer, sizeof(buffer)/sizeof(buffer[0]));
1101     if(length!=explength || u_strcmp(buffer, expect)!=0) {
1102         log_err("failure in u_unescape(): length %d!=%d and/or incorrect result string\n", length,
1103                 explength);
1104     }
1105 
1106     /* try preflighting */
1107     length=u_unescape(input, NULL, sizeof(buffer)/sizeof(buffer[0]));
1108     if(length!=explength || u_strcmp(buffer, expect)!=0) {
1109         log_err("failure in u_unescape(preflighting): length %d!=%d\n", length, explength);
1110     }
1111 
1112     /* ### TODO: test u_unescapeAt() */
1113 }
1114 
1115 /* test code point counting functions --------------------------------------- */
1116 
1117 /* reference implementation of u_strHasMoreChar32Than() */
1118 static int32_t
_refStrHasMoreChar32Than(const UChar * s,int32_t length,int32_t number)1119 _refStrHasMoreChar32Than(const UChar *s, int32_t length, int32_t number) {
1120     int32_t count=u_countChar32(s, length);
1121     return count>number;
1122 }
1123 
1124 /* compare the real function against the reference */
1125 static void
_testStrHasMoreChar32Than(const UChar * s,int32_t i,int32_t length,int32_t number)1126 _testStrHasMoreChar32Than(const UChar *s, int32_t i, int32_t length, int32_t number) {
1127     if(u_strHasMoreChar32Than(s, length, number)!=_refStrHasMoreChar32Than(s, length, number)) {
1128         log_err("u_strHasMoreChar32Than(s+%d, %d, %d)=%hd is wrong\n",
1129                 i, length, number, u_strHasMoreChar32Than(s, length, number));
1130     }
1131 }
1132 
1133 static void
TestCountChar32()1134 TestCountChar32() {
1135     static const UChar string[]={
1136         0x61, 0x62, 0xd800, 0xdc00,
1137         0xd801, 0xdc01, 0x63, 0xd802,
1138         0x64, 0xdc03, 0x65, 0x66,
1139         0xd804, 0xdc04, 0xd805, 0xdc05,
1140         0x67
1141     };
1142     UChar buffer[100];
1143     int32_t i, length, number;
1144 
1145     /* test u_strHasMoreChar32Than() with length>=0 */
1146     length=UPRV_LENGTHOF(string);
1147     while(length>=0) {
1148         for(i=0; i<=length; ++i) {
1149             for(number=-1; number<=((length-i)+2); ++number) {
1150                 _testStrHasMoreChar32Than(string+i, i, length-i, number);
1151             }
1152         }
1153         --length;
1154     }
1155 
1156     /* test u_strHasMoreChar32Than() with NUL-termination (length=-1) */
1157     length=UPRV_LENGTHOF(string);
1158     u_memcpy(buffer, string, length);
1159     while(length>=0) {
1160         buffer[length]=0;
1161         for(i=0; i<=length; ++i) {
1162             for(number=-1; number<=((length-i)+2); ++number) {
1163                 _testStrHasMoreChar32Than(buffer+i, i, -1, number);
1164             }
1165         }
1166         --length;
1167     }
1168 
1169     /* test u_strHasMoreChar32Than() with NULL string (bad input) */
1170     for(length=-1; length<=1; ++length) {
1171         for(i=0; i<=length; ++i) {
1172             for(number=-2; number<=2; ++number) {
1173                 _testStrHasMoreChar32Than(NULL, 0, length, number);
1174             }
1175         }
1176     }
1177 }
1178 
1179 /* UCharIterator ------------------------------------------------------------ */
1180 
1181 /*
1182  * Compare results from two iterators, should be same.
1183  * Assume that the text is not empty and that
1184  * iteration start==0 and iteration limit==length.
1185  */
1186 static void
compareIterators(UCharIterator * iter1,const char * n1,UCharIterator * iter2,const char * n2)1187 compareIterators(UCharIterator *iter1, const char *n1,
1188                  UCharIterator *iter2, const char *n2) {
1189     int32_t i, pos1, pos2, middle, length;
1190     UChar32 c1, c2;
1191 
1192     /* compare lengths */
1193     length=iter1->getIndex(iter1, UITER_LENGTH);
1194     pos2=iter2->getIndex(iter2, UITER_LENGTH);
1195     if(length!=pos2) {
1196         log_err("%s->getIndex(length)=%d != %d=%s->getIndex(length)\n", n1, length, pos2, n2);
1197         return;
1198     }
1199 
1200     /* set into the middle */
1201     middle=length/2;
1202 
1203     pos1=iter1->move(iter1, middle, UITER_ZERO);
1204     if(pos1!=middle) {
1205         log_err("%s->move(from 0 to middle %d)=%d does not move to the middle\n", n1, middle, pos1);
1206         return;
1207     }
1208 
1209     pos2=iter2->move(iter2, middle, UITER_ZERO);
1210     if(pos2!=middle) {
1211         log_err("%s->move(from 0 to middle %d)=%d does not move to the middle\n", n2, middle, pos2);
1212         return;
1213     }
1214 
1215     /* test current() */
1216     c1=iter1->current(iter1);
1217     c2=iter2->current(iter2);
1218     if(c1!=c2) {
1219         log_err("%s->current()=U+%04x != U+%04x=%s->current() at middle=%d\n", n1, c1, c2, n2, middle);
1220         return;
1221     }
1222 
1223     /* move forward 3 UChars */
1224     for(i=0; i<3; ++i) {
1225         c1=iter1->next(iter1);
1226         c2=iter2->next(iter2);
1227         if(c1!=c2) {
1228             log_err("%s->next()=U+%04x != U+%04x=%s->next() at %d (started in middle)\n", n1, c1, c2, n2, iter1->getIndex(iter1, UITER_CURRENT));
1229             return;
1230         }
1231     }
1232 
1233     /* move backward 5 UChars */
1234     for(i=0; i<5; ++i) {
1235         c1=iter1->previous(iter1);
1236         c2=iter2->previous(iter2);
1237         if(c1!=c2) {
1238             log_err("%s->previous()=U+%04x != U+%04x=%s->previous() at %d (started in middle)\n", n1, c1, c2, n2, iter1->getIndex(iter1, UITER_CURRENT));
1239             return;
1240         }
1241     }
1242 
1243     /* iterate forward from the beginning */
1244     pos1=iter1->move(iter1, 0, UITER_START);
1245     if(pos1<0) {
1246         log_err("%s->move(start) failed\n", n1);
1247         return;
1248     }
1249     if(!iter1->hasNext(iter1)) {
1250         log_err("%s->hasNext() at the start returns FALSE\n", n1);
1251         return;
1252     }
1253 
1254     pos2=iter2->move(iter2, 0, UITER_START);
1255     if(pos2<0) {
1256         log_err("%s->move(start) failed\n", n2);
1257         return;
1258     }
1259     if(!iter2->hasNext(iter2)) {
1260         log_err("%s->hasNext() at the start returns FALSE\n", n2);
1261         return;
1262     }
1263 
1264     do {
1265         c1=iter1->next(iter1);
1266         c2=iter2->next(iter2);
1267         if(c1!=c2) {
1268             log_err("%s->next()=U+%04x != U+%04x=%s->next() at %d\n", n1, c1, c2, n2, iter1->getIndex(iter1, UITER_CURRENT));
1269             return;
1270         }
1271     } while(c1>=0);
1272 
1273     if(iter1->hasNext(iter1)) {
1274         log_err("%s->hasNext() at the end returns TRUE\n", n1);
1275         return;
1276     }
1277     if(iter2->hasNext(iter2)) {
1278         log_err("%s->hasNext() at the end returns TRUE\n", n2);
1279         return;
1280     }
1281 
1282     /* back to the middle */
1283     pos1=iter1->move(iter1, middle, UITER_ZERO);
1284     if(pos1!=middle) {
1285         log_err("%s->move(from end to middle %d)=%d does not move to the middle\n", n1, middle, pos1);
1286         return;
1287     }
1288 
1289     pos2=iter2->move(iter2, middle, UITER_ZERO);
1290     if(pos2!=middle) {
1291         log_err("%s->move(from end to middle %d)=%d does not move to the middle\n", n2, middle, pos2);
1292         return;
1293     }
1294 
1295     /* move to index 1 */
1296     pos1=iter1->move(iter1, 1, UITER_ZERO);
1297     if(pos1!=1) {
1298         log_err("%s->move(from middle %d to 1)=%d does not move to 1\n", n1, middle, pos1);
1299         return;
1300     }
1301 
1302     pos2=iter2->move(iter2, 1, UITER_ZERO);
1303     if(pos2!=1) {
1304         log_err("%s->move(from middle %d to 1)=%d does not move to 1\n", n2, middle, pos2);
1305         return;
1306     }
1307 
1308     /* iterate backward from the end */
1309     pos1=iter1->move(iter1, 0, UITER_LIMIT);
1310     if(pos1<0) {
1311         log_err("%s->move(limit) failed\n", n1);
1312         return;
1313     }
1314     if(!iter1->hasPrevious(iter1)) {
1315         log_err("%s->hasPrevious() at the end returns FALSE\n", n1);
1316         return;
1317     }
1318 
1319     pos2=iter2->move(iter2, 0, UITER_LIMIT);
1320     if(pos2<0) {
1321         log_err("%s->move(limit) failed\n", n2);
1322         return;
1323     }
1324     if(!iter2->hasPrevious(iter2)) {
1325         log_err("%s->hasPrevious() at the end returns FALSE\n", n2);
1326         return;
1327     }
1328 
1329     do {
1330         c1=iter1->previous(iter1);
1331         c2=iter2->previous(iter2);
1332         if(c1!=c2) {
1333             log_err("%s->previous()=U+%04x != U+%04x=%s->previous() at %d\n", n1, c1, c2, n2, iter1->getIndex(iter1, UITER_CURRENT));
1334             return;
1335         }
1336     } while(c1>=0);
1337 
1338     if(iter1->hasPrevious(iter1)) {
1339         log_err("%s->hasPrevious() at the start returns TRUE\n", n1);
1340         return;
1341     }
1342     if(iter2->hasPrevious(iter2)) {
1343         log_err("%s->hasPrevious() at the start returns TRUE\n", n2);
1344         return;
1345     }
1346 }
1347 
1348 /*
1349  * Test the iterator's getState() and setState() functions.
1350  * iter1 and iter2 must be set up for the same iterator type and the same string
1351  * but may be physically different structs (different addresses).
1352  *
1353  * Assume that the text is not empty and that
1354  * iteration start==0 and iteration limit==length.
1355  * It must be 2<=middle<=length-2.
1356  */
1357 static void
testIteratorState(UCharIterator * iter1,UCharIterator * iter2,const char * n,int32_t middle)1358 testIteratorState(UCharIterator *iter1, UCharIterator *iter2, const char *n, int32_t middle) {
1359     UChar32 u[4];
1360 
1361     UErrorCode errorCode;
1362     UChar32 c;
1363     uint32_t state;
1364     int32_t i, j;
1365 
1366     /* get four UChars from the middle of the string */
1367     iter1->move(iter1, middle-2, UITER_ZERO);
1368     for(i=0; i<4; ++i) {
1369         c=iter1->next(iter1);
1370         if(c<0) {
1371             /* the test violates the assumptions, see comment above */
1372             log_err("test error: %s[%d]=%d\n", n, middle-2+i, c);
1373             return;
1374         }
1375         u[i]=c;
1376     }
1377 
1378     /* move to the middle and get the state */
1379     iter1->move(iter1, -2, UITER_CURRENT);
1380     state=uiter_getState(iter1);
1381 
1382     /* set the state into the second iterator and compare the results */
1383     errorCode=U_ZERO_ERROR;
1384     uiter_setState(iter2, state, &errorCode);
1385     if(U_FAILURE(errorCode)) {
1386         log_err("%s->setState(0x%x) failed: %s\n", n, state, u_errorName(errorCode));
1387         return;
1388     }
1389 
1390     c=iter2->current(iter2);
1391     if(c!=u[2]) {
1392         log_err("%s->current(at %d)=U+%04x!=U+%04x\n", n, middle, c, u[2]);
1393     }
1394 
1395     c=iter2->previous(iter2);
1396     if(c!=u[1]) {
1397         log_err("%s->previous(at %d)=U+%04x!=U+%04x\n", n, middle-1, c, u[1]);
1398     }
1399 
1400     iter2->move(iter2, 2, UITER_CURRENT);
1401     c=iter2->next(iter2);
1402     if(c!=u[3]) {
1403         log_err("%s->next(at %d)=U+%04x!=U+%04x\n", n, middle+1, c, u[3]);
1404     }
1405 
1406     iter2->move(iter2, -3, UITER_CURRENT);
1407     c=iter2->previous(iter2);
1408     if(c!=u[0]) {
1409         log_err("%s->previous(at %d)=U+%04x!=U+%04x\n", n, middle-2, c, u[0]);
1410     }
1411 
1412     /* move the second iterator back to the middle */
1413     iter2->move(iter2, 1, UITER_CURRENT);
1414     iter2->next(iter2);
1415 
1416     /* check that both are in the middle */
1417     i=iter1->getIndex(iter1, UITER_CURRENT);
1418     j=iter2->getIndex(iter2, UITER_CURRENT);
1419     if(i!=middle) {
1420         log_err("%s->getIndex(current)=%d!=%d as expected\n", n, i, middle);
1421     }
1422     if(i!=j) {
1423         log_err("%s->getIndex(current)=%d!=%d after setState()\n", n, j, i);
1424     }
1425 
1426     /* compare lengths */
1427     i=iter1->getIndex(iter1, UITER_LENGTH);
1428     j=iter2->getIndex(iter2, UITER_LENGTH);
1429     if(i!=j) {
1430         log_err("%s->getIndex(length)=%d!=%d before/after setState()\n", n, i, j);
1431     }
1432 }
1433 
1434 static void
TestUCharIterator()1435 TestUCharIterator() {
1436     static const UChar text[]={
1437         0x61, 0x62, 0x63, 0xd801, 0xdffd, 0x78, 0x79, 0x7a, 0
1438     };
1439     char bytes[40];
1440 
1441     UCharIterator iter, iter1, iter2;
1442     UConverter *cnv;
1443     UErrorCode errorCode;
1444     int32_t length;
1445 
1446     /* simple API/code coverage - test NOOP UCharIterator */
1447     uiter_setString(&iter, NULL, 0);
1448     if( iter.current(&iter)!=-1 || iter.next(&iter)!=-1 || iter.previous(&iter)!=-1 ||
1449         iter.move(&iter, 1, UITER_CURRENT) || iter.getIndex(&iter, UITER_CURRENT)!=0 ||
1450         iter.hasNext(&iter) || iter.hasPrevious(&iter)
1451     ) {
1452         log_err("NOOP UCharIterator behaves unexpectedly\n");
1453     }
1454 
1455     /* test get/set state */
1456     length=UPRV_LENGTHOF(text)-1;
1457     uiter_setString(&iter1, text, -1);
1458     uiter_setString(&iter2, text, length);
1459     testIteratorState(&iter1, &iter2, "UTF16IteratorState", length/2);
1460     testIteratorState(&iter1, &iter2, "UTF16IteratorStatePlus1", length/2+1);
1461 
1462     /* compare the same string between UTF-16 and UTF-8 UCharIterators ------ */
1463     errorCode=U_ZERO_ERROR;
1464     u_strToUTF8(bytes, sizeof(bytes), &length, text, -1, &errorCode);
1465     if(U_FAILURE(errorCode)) {
1466         log_err("u_strToUTF8() failed, %s\n", u_errorName(errorCode));
1467         return;
1468     }
1469 
1470     uiter_setString(&iter1, text, -1);
1471     uiter_setUTF8(&iter2, bytes, length);
1472     compareIterators(&iter1, "UTF16Iterator", &iter2, "UTF8Iterator");
1473 
1474     /* try again with length=-1 */
1475     uiter_setUTF8(&iter2, bytes, -1);
1476     compareIterators(&iter1, "UTF16Iterator", &iter2, "UTF8Iterator_1");
1477 
1478     /* test get/set state */
1479     length=UPRV_LENGTHOF(text)-1;
1480     uiter_setUTF8(&iter1, bytes, -1);
1481     testIteratorState(&iter1, &iter2, "UTF8IteratorState", length/2);
1482     testIteratorState(&iter1, &iter2, "UTF8IteratorStatePlus1", length/2+1);
1483 
1484     /* compare the same string between UTF-16 and UTF-16BE UCharIterators --- */
1485     errorCode=U_ZERO_ERROR;
1486     cnv=ucnv_open("UTF-16BE", &errorCode);
1487     length=ucnv_fromUChars(cnv, bytes, sizeof(bytes), text, -1, &errorCode);
1488     ucnv_close(cnv);
1489     if(U_FAILURE(errorCode)) {
1490         log_err("ucnv_fromUChars(UTF-16BE) failed, %s\n", u_errorName(errorCode));
1491         return;
1492     }
1493 
1494     /* terminate with a _pair_ of 0 bytes - a UChar NUL in UTF-16BE (length is known to be ok) */
1495     bytes[length]=bytes[length+1]=0;
1496 
1497     uiter_setString(&iter1, text, -1);
1498     uiter_setUTF16BE(&iter2, bytes, length);
1499     compareIterators(&iter1, "UTF16Iterator", &iter2, "UTF16BEIterator");
1500 
1501     /* try again with length=-1 */
1502     uiter_setUTF16BE(&iter2, bytes, -1);
1503     compareIterators(&iter1, "UTF16Iterator", &iter2, "UTF16BEIterator_1");
1504 
1505     /* try again after moving the bytes up one, and with length=-1 */
1506     memmove(bytes+1, bytes, length+2);
1507     uiter_setUTF16BE(&iter2, bytes+1, -1);
1508     compareIterators(&iter1, "UTF16Iterator", &iter2, "UTF16BEIteratorMoved1");
1509 
1510     /* ### TODO test other iterators: CharacterIterator, Replaceable */
1511 }
1512