1 /********************************************************************
2  * COPYRIGHT:
3  * Copyright (c) 1998-2014, International Business Machines Corporation and
4  * others. All Rights Reserved.
5  ********************************************************************/
6 /*
7 * File test.c
8 *
9 * Modification History:
10 *
11 *   Date          Name        Description
12 *   05/01/2000    Madhu       Creation
13 *******************************************************************************
14 */
15 
16 #include "unicode/utypes.h"
17 #include "unicode/utf16.h"
18 #include "unicode/ustring.h"
19 #include "cmemory.h"
20 #include "cstring.h"
21 #include "cintltst.h"
22 #include <stdio.h>
23 
24 static void printUChars(const UChar *uchars);
25 
26 static void TestCodeUnitValues(void);
27 static void TestCharLength(void);
28 static void TestGetChar(void);
29 static void TestNextPrevChar(void);
30 static void TestNulTerminated(void);
31 static void TestFwdBack(void);
32 static void TestSetChar(void);
33 static void TestAppendChar(void);
34 static void TestAppend(void);
35 static void TestSurrogate(void);
36 
37 void addUTF16Test(TestNode** root);
38 
39 void
addUTF16Test(TestNode ** root)40 addUTF16Test(TestNode** root)
41 {
42     addTest(root, &TestCodeUnitValues,          "utf16tst/TestCodeUnitValues");
43     addTest(root, &TestCharLength,              "utf16tst/TestCharLength");
44     addTest(root, &TestGetChar,                 "utf16tst/TestGetChar");
45     addTest(root, &TestNextPrevChar,            "utf16tst/TestNextPrevChar");
46     addTest(root, &TestNulTerminated,           "utf16tst/TestNulTerminated");
47     addTest(root, &TestFwdBack,                 "utf16tst/TestFwdBack");
48     addTest(root, &TestSetChar,                 "utf16tst/TestSetChar");
49     addTest(root, &TestAppendChar,              "utf16tst/TestAppendChar");
50     addTest(root, &TestAppend,                  "utf16tst/TestAppend");
51     addTest(root, &TestSurrogate,               "utf16tst/TestSurrogate");
52 }
53 
TestCodeUnitValues()54 static void TestCodeUnitValues()
55 {
56     static uint16_t codeunit[]={0x0000,0xe065,0x20ac,0xd7ff,0xd800,0xd841,0xd905,0xdbff,0xdc00,0xdc02,0xddee,0xdfff,0};
57 
58     int16_t i;
59     for(i=0; i<sizeof(codeunit)/sizeof(codeunit[0]); i++){
60         UChar c=codeunit[i];
61         log_verbose("Testing code unit value of %x\n", c);
62         if(i<4){
63             if(!UTF16_IS_SINGLE(c) || UTF16_IS_LEAD(c) || UTF16_IS_TRAIL(c) || !U16_IS_SINGLE(c) || U16_IS_LEAD(c) || U16_IS_TRAIL(c)){
64                 log_err("ERROR: %x is a single character\n", c);
65             }
66         }
67         if(i >= 4 && i< 8){
68             if(!UTF16_IS_LEAD(c) || UTF16_IS_SINGLE(c) || UTF16_IS_TRAIL(c) || !U16_IS_LEAD(c) || U16_IS_SINGLE(c) || U16_IS_TRAIL(c)){
69                 log_err("ERROR: %x is a first surrogate\n", c);
70             }
71         }
72         if(i >= 8 && i< 12){
73             if(!UTF16_IS_TRAIL(c) || UTF16_IS_SINGLE(c) || UTF16_IS_LEAD(c) || !U16_IS_TRAIL(c) || U16_IS_SINGLE(c) || U16_IS_LEAD(c)){
74                 log_err("ERROR: %x is a second surrogate\n", c);
75             }
76         }
77     }
78 }
79 
TestCharLength()80 static void TestCharLength()
81 {
82     static uint32_t codepoint[]={
83         1, 0x0061,
84         1, 0xe065,
85         1, 0x20ac,
86         2, 0x20402,
87         2, 0x23456,
88         2, 0x24506,
89         2, 0x20402,
90         2, 0x10402,
91         1, 0xd7ff,
92         1, 0xe000
93     };
94 
95     int16_t i;
96     UBool multiple;
97     for(i=0; i<sizeof(codepoint)/sizeof(codepoint[0]); i=(int16_t)(i+2)){
98         UChar32 c=codepoint[i+1];
99         if(UTF16_CHAR_LENGTH(c) != (uint16_t)codepoint[i] || U16_LENGTH(c) != (uint16_t)codepoint[i]){
100               log_err("The no: of code units for %lx:- Expected: %d Got: %d\n", c, codepoint[i], UTF16_CHAR_LENGTH(c));
101         }else{
102               log_verbose("The no: of code units for %lx is %d\n",c, UTF16_CHAR_LENGTH(c) );
103         }
104         multiple=(UBool)(codepoint[i] == 1 ? FALSE : TRUE);
105         if(UTF16_NEED_MULTIPLE_UCHAR(c) != multiple){
106               log_err("ERROR: UTF16_NEED_MULTIPLE_UCHAR failed for %lx\n", c);
107         }
108     }
109 }
110 
TestGetChar()111 static void TestGetChar()
112 {
113     static UChar input[]={
114     /*  code unit,*/
115         0xdc00,
116         0x20ac,
117         0xd841,
118         0x61,
119         0xd841,
120         0xdc02,
121         0xd842,
122         0xdc06,
123         0,
124         0xd842,
125         0xd7ff,
126         0xdc41,
127         0xe000,
128         0xd800
129     };
130     static UChar32 result[]={
131      /*codepoint-unsafe,  codepoint-safe(not strict)  codepoint-safe(strict)*/
132         (UChar32)0xfca10000, 0xdc00,                  UTF_ERROR_VALUE,
133         0x20ac,           0x20ac,                     0x20ac,
134         0x12861,          0xd841,                     UTF_ERROR_VALUE,
135         0x61,             0x61,                       0x61,
136         0x20402,          0x20402,                    0x20402,
137         0x20402,          0x20402,                    0x20402,
138         0x20806,          0x20806,                    0x20806,
139         0x20806,          0x20806,                    0x20806,
140         0x00,             0x00,                       0x00,
141         0x203ff,          0xd842,                     UTF_ERROR_VALUE,
142         0xd7ff,           0xd7ff,                     0xd7ff,
143         0xfc41,           0xdc41,                     UTF_ERROR_VALUE,
144         0xe000,           0xe000,                     0xe000,
145         0x11734,          0xd800,                     UTF_ERROR_VALUE
146     };
147     uint16_t i=0;
148     UChar32 c;
149     uint16_t offset=0;
150     for(offset=0; offset<sizeof(input)/U_SIZEOF_UCHAR; offset++) {
151         if(0<offset && offset<sizeof(input)/U_SIZEOF_UCHAR-1){
152             UTF16_GET_CHAR_UNSAFE(input, offset, c);
153             if(c != result[i]){
154                 log_err("ERROR: UTF16_GET_CHAR_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i], c);
155             }
156 
157             U16_GET_UNSAFE(input, offset, c);
158             if(c != result[i]){
159                 log_err("ERROR: U16_GET_CHAR_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i], c);
160             }
161         }
162 
163         UTF16_GET_CHAR_SAFE(input, 0, offset, sizeof(input)/U_SIZEOF_UCHAR, c, FALSE);
164         if(c != result[i+1]){
165             log_err("ERROR: UTF16_GET_CHAR_SAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i+1], c);
166         }
167 
168         U16_GET(input, 0, offset, sizeof(input)/U_SIZEOF_UCHAR, c);
169         if(c != result[i+1]){
170             log_err("ERROR: U16_GET failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i+1], c);
171         }
172 
173         UTF16_GET_CHAR_SAFE(input, 0, offset, sizeof(input)/U_SIZEOF_UCHAR, c, TRUE);
174         if(c != result[i+2]){
175             log_err("ERROR: UTF16_GET_CHAR_SAFE(strict) failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i+2], c);
176         }
177         i=(uint16_t)(i+3);
178     }
179 
180 }
181 
TestNextPrevChar()182 static void TestNextPrevChar(){
183 
184     static UChar input[]={0x0061, 0xd800, 0xdc00, 0xdbff, 0xdfff, 0x0062, 0xd841, 0xd7ff, 0xd841, 0xdc41, 0xdc00, 0x0000};
185     static UChar32 result[]={
186     /*next_unsafe    next_safe_ns  next_safe_s       prev_unsafe   prev_safe_ns     prev_safe_s*/
187         0x0061,        0x0061,       0x0061,           0x0000,       0x0000,          0x0000,
188         0x10000,       0x10000,      0x10000,          0x120400,     0xdc00,          UTF_ERROR_VALUE,
189         0xdc00,        0xdc00,       UTF_ERROR_VALUE,  0x20441,      0x20441,         0x20441,
190         0x10ffff,      0x10ffff,     0x10ffff,         0xd841,       0xd841,          UTF_ERROR_VALUE,
191         0xdfff,        0xdfff,       UTF_ERROR_VALUE,  0xd7ff,       0xd7ff,          0xd7ff,
192         0x0062,        0x0062,       0x0062,           0xd841,       0xd841,          UTF_ERROR_VALUE,
193         0x1ffff,       0xd841,       UTF_ERROR_VALUE,  0x0062,       0x0062,          0x0062,
194         0xd7ff,        0xd7ff,       0xd7ff,           0x10ffff,     0x10ffff,        0x10ffff,
195         0x20441,       0x20441,      0x20441,          0xdbff,       0xdbff,          UTF_ERROR_VALUE,
196         0xdc41,        0xdc41,       UTF_ERROR_VALUE,  0x10000,      0x10000,         0x10000,
197         0xdc00,        0xdc00,       UTF_ERROR_VALUE,  0xd800,       0xd800,          UTF_ERROR_VALUE,
198         0x0000,        0x0000,       0x0000,           0x0061,       0x0061,          0x0061
199     };
200     static uint16_t movedOffset[]={
201    /*next_unsafe    next_safe_ns  next_safe_s       prev_unsafe   prev_safe_ns     prev_safe_s*/
202         1,            1,           1,                11,           11,               11,
203         3,            3,           3,                9,            10 ,              10,
204         3,            3,           3,                8,            8,                8,
205         5,            5,           4,                8,            8,                8,
206         5,            5,           5,                7,            7,                7,
207         6,            6,           6,                6,            6,                6,
208         8,            7,           7,                5,            5,                5,
209         8,            8,           8,                3,            3,                3,
210         10,           10,          10,               3,            3,                3,
211         10,           10,          10,               1,            1,                1,
212         11,           11,          11,               1,            1,                1,
213         12,           12,          12,               0,            0,                0,
214     };
215 
216 
217     UChar32 c=0x0000;
218     uint16_t i=0;
219     uint16_t offset=0, setOffset=0;
220     for(offset=0; offset<sizeof(input)/U_SIZEOF_UCHAR; offset++){
221          setOffset=offset;
222          UTF16_NEXT_CHAR_UNSAFE(input, setOffset, c);
223          if(setOffset != movedOffset[i]){
224              log_err("ERROR: UTF16_NEXT_CHAR_UNSAFE failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n",
225                  offset, movedOffset[i], setOffset);
226          }
227          if(c != result[i]){
228              log_err("ERROR: UTF16_NEXT_CHAR_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i], c);
229          }
230 
231          setOffset=offset;
232          U16_NEXT_UNSAFE(input, setOffset, c);
233          if(setOffset != movedOffset[i]){
234              log_err("ERROR: U16_NEXT_CHAR_UNSAFE failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n",
235                  offset, movedOffset[i], setOffset);
236          }
237          if(c != result[i]){
238              log_err("ERROR: U16_NEXT_CHAR_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i], c);
239          }
240 
241          setOffset=offset;
242          UTF16_NEXT_CHAR_SAFE(input, setOffset, sizeof(input)/U_SIZEOF_UCHAR, c, FALSE);
243          if(setOffset != movedOffset[i+1]){
244              log_err("ERROR: UTF16_NEXT_CHAR_SAFE failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n",
245                  offset, movedOffset[i+1], setOffset);
246          }
247          if(c != result[i+1]){
248              log_err("ERROR: UTF16_NEXT_CHAR_SAFE failed for input=%ld. Expected:%lx Got:%lx\n", offset, result[i+1], c);
249          }
250 
251          setOffset=offset;
252          U16_NEXT(input, setOffset, sizeof(input)/U_SIZEOF_UCHAR, c);
253          if(setOffset != movedOffset[i+1]){
254              log_err("ERROR: U16_NEXT failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n",
255                  offset, movedOffset[i+1], setOffset);
256          }
257          if(c != result[i+1]){
258              log_err("ERROR: U16_NEXT failed for input=%ld. Expected:%lx Got:%lx\n", offset, result[i+1], c);
259          }
260 
261          setOffset=offset;
262          UTF16_NEXT_CHAR_SAFE(input, setOffset, sizeof(input)/U_SIZEOF_UCHAR, c, TRUE);
263          if(setOffset != movedOffset[i+1]){
264              log_err("ERROR: UTF16_NEXT_CHAR_SAFE(strict) failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n",
265                  offset, movedOffset[i+2], setOffset);
266          }
267          if(c != result[i+2]){
268              log_err("ERROR: UTF16_NEXT_CHAR_SAFE(strict) failed for input=%ld. Expected:%lx Got:%lx\n", offset, result[i+2], c);
269          }
270 
271          i=(uint16_t)(i+6);
272     }
273     i=0;
274     for(offset=(uint16_t)sizeof(input)/U_SIZEOF_UCHAR; offset > 0; --offset){
275          setOffset=offset;
276          UTF16_PREV_CHAR_UNSAFE(input, setOffset, c);
277          if(setOffset != movedOffset[i+3]){
278              log_err("ERROR: UTF16_PREV_CHAR_UNSAFE failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n",
279                  offset, movedOffset[i+3], setOffset);
280          }
281          if(c != result[i+3]){
282              log_err("ERROR: UTF16_PREV_CHAR_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i+3], c);
283          }
284 
285          setOffset=offset;
286          U16_PREV_UNSAFE(input, setOffset, c);
287          if(setOffset != movedOffset[i+3]){
288              log_err("ERROR: U16_PREV_CHAR_UNSAFE failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n",
289                  offset, movedOffset[i+3], setOffset);
290          }
291          if(c != result[i+3]){
292              log_err("ERROR: U16_PREV_CHAR_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, result[i+3], c);
293          }
294 
295          setOffset=offset;
296          UTF16_PREV_CHAR_SAFE(input, 0, setOffset, c, FALSE);
297          if(setOffset != movedOffset[i+4]){
298              log_err("ERROR: UTF16_PREV_CHAR_SAFE failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n",
299                  offset, movedOffset[i+4], setOffset);
300          }
301          if(c != result[i+4]){
302              log_err("ERROR: UTF16_PREV_CHAR_SAFE failed for input=%ld. Expected:%lx Got:%lx\n", offset, result[i+4], c);
303          }
304 
305          setOffset=offset;
306          U16_PREV(input, 0, setOffset, c);
307          if(setOffset != movedOffset[i+4]){
308              log_err("ERROR: U16_PREV failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n",
309                  offset, movedOffset[i+4], setOffset);
310          }
311          if(c != result[i+4]){
312              log_err("ERROR: U16_PREV failed for input=%ld. Expected:%lx Got:%lx\n", offset, result[i+4], c);
313          }
314 
315          setOffset=offset;
316          UTF16_PREV_CHAR_SAFE(input, 0,  setOffset, c, TRUE);
317          if(setOffset != movedOffset[i+5]){
318              log_err("ERROR: UTF16_PREV_CHAR_SAFE(strict) failed to move the offset correctly at %d\n ExpectedOffset:%d Got %d\n",
319                  offset, movedOffset[i+5], setOffset);
320          }
321          if(c != result[i+5]){
322              log_err("ERROR: UTF16_PREV_CHAR_SAFE(strict) failed for input=%ld. Expected:%lx Got:%lx\n", offset, result[i+5], c);
323          }
324 
325          i=(uint16_t)(i+6);
326     }
327 
328 }
329 
330 /* keep this in sync with utf8tst.c's TestNulTerminated() */
TestNulTerminated()331 static void TestNulTerminated() {
332     static const UChar input[]={
333         /*  0 */  0x61,
334         /*  1 */  0xd801, 0xdc01,
335         /*  3 */  0xdc01,
336         /*  4 */  0x62,
337         /*  5 */  0xd801,
338         /*  6 */  0x00
339         /*  7 */
340     };
341     static const UChar32 result[]={
342         0x61,
343         0x10401,
344         0xdc01,
345         0x62,
346         0xd801,
347         0
348     };
349 
350     UChar32 c, c2;
351     int32_t i0, i=0, j, k, expectedIndex;
352     int32_t cpIndex=0;
353     do {
354         i0=i;
355         U16_NEXT(input, i, -1, c);
356         if(c!=result[cpIndex]) {
357             log_err("U16_NEXT(from %d)=U+%04x != U+%04x\n", i0, c, result[cpIndex]);
358         }
359         j=i0;
360         U16_FWD_1(input, j, -1);
361         if(j!=i) {
362             log_err("U16_FWD_1() moved to index %d but U16_NEXT() moved to %d\n", j, i);
363         }
364         ++cpIndex;
365         /*
366          * Move by this many code points from the start.
367          * U16_FWD_N() stops at the end of the string, that is, at the NUL if necessary.
368          */
369         expectedIndex= (c==0) ? i-1 : i;
370         k=0;
371         U16_FWD_N(input, k, -1, cpIndex);
372         if(k!=expectedIndex) {
373             log_err("U16_FWD_N(code points from 0) moved to index %d but expected %d\n", k, expectedIndex);
374         }
375     } while(c!=0);
376 
377     i=0;
378     do {
379         j=i0=i;
380         U16_NEXT(input, i, -1, c);
381         do {
382             U16_GET(input, 0, j, -1, c2);
383             if(c2!=c) {
384                 log_err("U16_NEXT(from %d)=U+%04x != U+%04x=U16_GET(at %d)\n", i0, c, c2, j);
385             }
386             /* U16_SET_CP_LIMIT moves from a non-lead byte to the limit of the code point */
387             k=j+1;
388             U16_SET_CP_LIMIT(input, 0, k, -1);
389             if(k!=i) {
390                 log_err("U16_NEXT() moved to %d but U16_SET_CP_LIMIT(%d) moved to %d\n", i, j+1, k);
391             }
392         } while(++j<i);
393     } while(c!=0);
394 }
395 
TestFwdBack()396 static void TestFwdBack(){
397     static UChar input[]={0x0061, 0xd800, 0xdc00, 0xdbff, 0xdfff, 0x0062, 0xd841, 0xd7ff, 0xd841, 0xdc41, 0xdc00, 0x0000};
398     static uint16_t fwd_unsafe[] ={1, 3, 5, 6,  8, 10, 11, 12};
399     static uint16_t fwd_safe[]   ={1, 3, 5, 6, 7, 8, 10, 11, 12};
400     static uint16_t back_unsafe[]={11, 9, 8, 7, 6, 5, 3, 1, 0};
401     static uint16_t back_safe[]  ={11, 10, 8, 7, 6, 5, 3, 1, 0};
402 
403     static uint16_t Nvalue[]= {0, 1, 2, 3, 1, 2, 1};
404     static uint16_t fwd_N_unsafe[] ={0, 1, 5, 10, 11};
405     static uint16_t fwd_N_safe[]   ={0, 1, 5, 8, 10, 12, 12}; /*safe macro keeps it at the end of the string */
406     static uint16_t back_N_unsafe[]={12, 11, 8, 5, 3};
407     static uint16_t back_N_safe[]  ={12, 11, 8, 5, 3, 0, 0};
408 
409     uint16_t offunsafe=0, offsafe=0;
410     uint16_t i=0;
411     while(offunsafe < sizeof(input)/U_SIZEOF_UCHAR){
412         UTF16_FWD_1_UNSAFE(input, offunsafe);
413         if(offunsafe != fwd_unsafe[i]){
414             log_err("ERROR: Forward_unsafe offset expected:%d, Got:%d\n", fwd_unsafe[i], offunsafe);
415         }
416         i++;
417     }
418 
419     offunsafe=0, offsafe=0;
420     i=0;
421     while(offunsafe < sizeof(input)/U_SIZEOF_UCHAR){
422         U16_FWD_1_UNSAFE(input, offunsafe);
423         if(offunsafe != fwd_unsafe[i]){
424             log_err("ERROR: U16_FWD_1_UNSAFE offset expected:%d, Got:%d\n", fwd_unsafe[i], offunsafe);
425         }
426         i++;
427     }
428 
429     i=0;
430     while(offsafe < sizeof(input)/U_SIZEOF_UCHAR){
431         UTF16_FWD_1_SAFE(input, offsafe, sizeof(input)/U_SIZEOF_UCHAR);
432         if(offsafe != fwd_safe[i]){
433             log_err("ERROR: Forward_safe offset expected:%d, Got:%d\n", fwd_safe[i], offsafe);
434         }
435         i++;
436     }
437 
438     i=0;
439     while(offsafe < sizeof(input)/U_SIZEOF_UCHAR){
440         U16_FWD_1(input, offsafe, sizeof(input)/U_SIZEOF_UCHAR);
441         if(offsafe != fwd_safe[i]){
442             log_err("ERROR: U16_FWD_1 offset expected:%d, Got:%d\n", fwd_safe[i], offsafe);
443         }
444         i++;
445     }
446 
447     offunsafe=sizeof(input)/U_SIZEOF_UCHAR;
448     offsafe=sizeof(input)/U_SIZEOF_UCHAR;
449     i=0;
450     while(offunsafe > 0){
451         UTF16_BACK_1_UNSAFE(input, offunsafe);
452         if(offunsafe != back_unsafe[i]){
453             log_err("ERROR: Backward_unsafe offset expected:%d, Got:%d\n", back_unsafe[i], offunsafe);
454         }
455         i++;
456     }
457 
458     offunsafe=sizeof(input)/U_SIZEOF_UCHAR;
459     offsafe=sizeof(input)/U_SIZEOF_UCHAR;
460     i=0;
461     while(offunsafe > 0){
462         U16_BACK_1_UNSAFE(input, offunsafe);
463         if(offunsafe != back_unsafe[i]){
464             log_err("ERROR: U16_BACK_1_UNSAFE offset expected:%d, Got:%d\n", back_unsafe[i], offunsafe);
465         }
466         i++;
467     }
468 
469     i=0;
470     while(offsafe > 0){
471         UTF16_BACK_1_SAFE(input,0,  offsafe);
472         if(offsafe != back_safe[i]){
473             log_err("ERROR: Backward_safe offset expected:%d, Got:%d\n", back_unsafe[i], offsafe);
474         }
475         i++;
476     }
477 
478     i=0;
479     while(offsafe > 0){
480         U16_BACK_1(input,0,  offsafe);
481         if(offsafe != back_safe[i]){
482             log_err("ERROR: U16_BACK_1 offset expected:%d, Got:%d\n", back_unsafe[i], offsafe);
483         }
484         i++;
485     }
486 
487     offunsafe=0;
488     offsafe=0;
489     for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0])-2; i++){  /*didn't want it to fail(we assume 0<i<length)*/
490         UTF16_FWD_N_UNSAFE(input, offunsafe, Nvalue[i]);
491         if(offunsafe != fwd_N_unsafe[i]){
492             log_err("ERROR: Forward_N_unsafe offset expected:%d, Got:%d\n", fwd_N_unsafe[i], offunsafe);
493         }
494     }
495 
496     offunsafe=0;
497     for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0])-2; i++){  /*didn't want it to fail(we assume 0<i<length)*/
498         U16_FWD_N_UNSAFE(input, offunsafe, Nvalue[i]);
499         if(offunsafe != fwd_N_unsafe[i]){
500             log_err("ERROR: U16_FWD_N_UNSAFE offset expected:%d, Got:%d\n", fwd_N_unsafe[i], offunsafe);
501         }
502     }
503 
504     offsafe=0;
505     for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0]); i++){
506         UTF16_FWD_N_SAFE(input, offsafe, sizeof(input)/U_SIZEOF_UCHAR, Nvalue[i]);
507         if(offsafe != fwd_N_safe[i]){
508             log_err("ERROR: Forward_N_safe offset expected:%d, Got:%d\n", fwd_N_safe[i], offsafe);
509         }
510 
511     }
512 
513     offsafe=0;
514     for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0]); i++){
515         U16_FWD_N(input, offsafe, sizeof(input)/U_SIZEOF_UCHAR, Nvalue[i]);
516         if(offsafe != fwd_N_safe[i]){
517             log_err("ERROR: U16_FWD_N offset expected:%d, Got:%d\n", fwd_N_safe[i], offsafe);
518         }
519 
520     }
521 
522     offunsafe=sizeof(input)/U_SIZEOF_UCHAR;
523     for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0])-2; i++){
524         UTF16_BACK_N_UNSAFE(input, offunsafe, Nvalue[i]);
525         if(offunsafe != back_N_unsafe[i]){
526             log_err("ERROR: backward_N_unsafe offset expected:%d, Got:%d\n", back_N_unsafe[i], offunsafe);
527         }
528     }
529 
530     offunsafe=sizeof(input)/U_SIZEOF_UCHAR;
531     for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0])-2; i++){
532         U16_BACK_N_UNSAFE(input, offunsafe, Nvalue[i]);
533         if(offunsafe != back_N_unsafe[i]){
534             log_err("ERROR: U16_BACK_N_UNSAFE offset expected:%d, Got:%d\n", back_N_unsafe[i], offunsafe);
535         }
536     }
537 
538     offsafe=sizeof(input)/U_SIZEOF_UCHAR;
539     for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0]); i++){
540         UTF16_BACK_N_SAFE(input, 0, offsafe, Nvalue[i]);
541         if(offsafe != back_N_safe[i]){
542             log_err("ERROR: backward_N_safe offset expected:%d, Got:%d\n", back_N_safe[i], offsafe);
543         }
544     }
545 
546     offsafe=sizeof(input)/U_SIZEOF_UCHAR;
547     for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0]); i++){
548         U16_BACK_N(input, 0, offsafe, Nvalue[i]);
549         if(offsafe != back_N_safe[i]){
550             log_err("ERROR: U16_BACK_N offset expected:%d, Got:%d\n", back_N_safe[i], offsafe);
551         }
552     }
553 }
554 
TestSetChar()555 static void TestSetChar(){
556     static UChar input[]={0x0061, 0xd800, 0xdc00, 0xdbff, 0xdfff, 0x0062, 0xd841, 0xd7ff, 0xd841, 0xdc41, 0xdc00, 0x0000};
557     static uint16_t start_unsafe[]={0, 1, 1, 3, 3, 5, 6, 7, 8, 8, 9, 11};
558     static uint16_t start_safe[]  ={0, 1, 1, 3, 3, 5, 6, 7, 8, 8, 10, 11};
559     static uint16_t limit_unsafe[]={0, 1, 3, 3, 5, 5, 6, 8, 8, 10, 10, 11};
560     static uint16_t limit_safe[]  ={0, 1, 3, 3, 5, 5, 6, 7, 8, 10, 10, 11};
561 
562     uint16_t i=0;
563     uint16_t offset=0, setOffset=0;
564     for(offset=0; offset<sizeof(input)/U_SIZEOF_UCHAR; offset++){
565          setOffset=offset;
566          UTF16_SET_CHAR_START_UNSAFE(input, setOffset);
567          if(setOffset != start_unsafe[i]){
568              log_err("ERROR: UTF16_SET_CHAR_START_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, start_unsafe[i], setOffset);
569          }
570 
571          setOffset=offset;
572          U16_SET_CP_START_UNSAFE(input, setOffset);
573          if(setOffset != start_unsafe[i]){
574              log_err("ERROR: U16_SET_CHAR_START_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, start_unsafe[i], setOffset);
575          }
576 
577          setOffset=offset;
578          UTF16_SET_CHAR_START_SAFE(input, 0, setOffset);
579          if(setOffset != start_safe[i]){
580              log_err("ERROR: UTF16_SET_CHAR_START_SAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, start_safe[i], setOffset);
581          }
582 
583          setOffset=offset;
584          U16_SET_CP_START(input, 0, setOffset);
585          if(setOffset != start_safe[i]){
586              log_err("ERROR: U16_SET_CHAR_START failed for offset=%ld. Expected:%lx Got:%lx\n", offset, start_safe[i], setOffset);
587          }
588 
589          if (offset > 0) {
590              setOffset=offset;
591              UTF16_SET_CHAR_LIMIT_UNSAFE(input, setOffset);
592              if(setOffset != limit_unsafe[i]){
593                  log_err("ERROR: UTF16_SET_CHAR_LIMIT_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, limit_unsafe[i], setOffset);
594              }
595 
596              setOffset=offset;
597              U16_SET_CP_LIMIT_UNSAFE(input, setOffset);
598              if(setOffset != limit_unsafe[i]){
599                  log_err("ERROR: U16_SET_CHAR_LIMIT_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, limit_unsafe[i], setOffset);
600              }
601          }
602 
603          setOffset=offset;
604          U16_SET_CP_LIMIT(input,0, setOffset, sizeof(input)/U_SIZEOF_UCHAR);
605          if(setOffset != limit_safe[i]){
606              log_err("ERROR: U16_SET_CHAR_LIMIT failed for offset=%ld. Expected:%lx Got:%lx\n", offset, limit_safe[i], setOffset);
607          }
608 
609          i++;
610     }
611 }
612 
TestAppendChar()613 static void TestAppendChar(){
614     static UChar s[5]={0x0061, 0x0062, 0x0063, 0x0064, 0x0000};
615     static uint32_t test[]={
616      /*append-position(unsafe),  CHAR to be appended  */
617         0,                        0x20441,
618         2,                        0x0028,
619         2,                        0xdc00,
620         3,                        0xd800,
621         1,                        0x20402,
622 
623     /*append-position(safe),     CHAR to be appended */
624         0,                        0x20441,
625         2,                        0xdc00,
626         3,                        0xd800,
627         1,                        0x20402,
628         3,                        0x20402,
629         3,                        0x10402,
630         2,                        0x10402,
631 
632     };
633     static uint16_t movedOffset[]={
634         /*offset-moved-to(unsafe)*/
635           2,              /*for append-pos: 0 , CHAR 0x20441*/
636           3,
637           3,
638           4,
639           3,
640           /*offse-moved-to(safe)*/
641           2,              /*for append-pos: 0, CHAR  0x20441*/
642           3,
643           4,
644           3,
645           4,
646           4,
647           4
648     };
649 
650     static UChar result[][5]={
651         /*unsafe*/
652         {0xd841, 0xdc41, 0x0063, 0x0064, 0x0000},
653         {0x0061, 0x0062, 0x0028, 0x0064, 0x0000},
654         {0x0061, 0x0062, 0xdc00, 0x0064, 0x0000},
655         {0x0061, 0x0062, 0x0063, 0xd800, 0x0000},
656         {0x0061, 0xd841, 0xdc02, 0x0064, 0x0000},
657 
658         /*safe*/
659         {0xd841, 0xdc41, 0x0063, 0x0064, 0x0000},
660         {0x0061, 0x0062, 0xdc00, 0x0064, 0x0000},
661         {0x0061, 0x0062, 0x0063, 0xd800, 0x0000},
662         {0x0061, 0xd841, 0xdc02, 0x0064, 0x0000},
663         {0x0061, 0x0062, 0x0063, UTF_ERROR_VALUE, 0x0000},
664         {0x0061, 0x0062, 0x0063, UTF_ERROR_VALUE, 0x0000},
665         {0x0061, 0x0062, 0xd801, 0xdc02, 0x0000},
666 
667 
668     };
669     uint16_t i, count=0;
670     UChar *str=(UChar*)malloc(sizeof(UChar) * (u_strlen(s)+1));
671     uint16_t offset;
672     for(i=0; i<sizeof(test)/sizeof(test[0]); i=(uint16_t)(i+2)){
673         if(count<5){
674             u_strcpy(str, s);
675             offset=(uint16_t)test[i];
676             UTF16_APPEND_CHAR_UNSAFE(str, offset, test[i+1]);
677             if(offset != movedOffset[count]){
678                 log_err("ERROR: UTF16_APPEND_CHAR_UNSAFE failed to move the offset correctly for count=%d.\nExpectedOffset=%d  currentOffset=%d\n",
679                     count, movedOffset[count], offset);
680 
681             }
682             if(u_strcmp(str, result[count]) !=0){
683                 log_err("ERROR: UTF16_APPEND_CHAR_UNSAFE failed for count=%d. Expected:", count);
684                 printUChars(result[count]);
685                 printf("\nGot:");
686                 printUChars(str);
687                 printf("\n");
688             }
689         }else{
690             u_strcpy(str, s);
691             offset=(uint16_t)test[i];
692             UTF16_APPEND_CHAR_SAFE(str, offset, (uint16_t)u_strlen(str), test[i+1]);
693             if(offset != movedOffset[count]){
694                 log_err("ERROR: UTF16_APPEND_CHAR_SAFE failed to move the offset correctly for count=%d.\nExpectedOffset=%d  currentOffset=%d\n",
695                     count, movedOffset[count], offset);
696 
697             }
698             if(u_strcmp(str, result[count]) !=0){
699                 log_err("ERROR: UTF16_APPEND_CHAR_SAFE failed for count=%d. Expected:", count);
700                 printUChars(result[count]);
701                 printf("\nGot:");
702                 printUChars(str);
703                 printf("\n");
704             }
705         }
706         count++;
707     }
708     free(str);
709 
710 }
711 
TestAppend()712 static void TestAppend() {
713     static const UChar32 codePoints[]={
714         0x61, 0xdf, 0x901, 0x3040,
715         0xac00, 0xd800, 0xdbff, 0xdcde,
716         0xdffd, 0xe000, 0xffff, 0x10000,
717         0x12345, 0xe0021, 0x10ffff, 0x110000,
718         0x234567, 0x7fffffff, -1, -1000,
719         0, 0x400
720     };
721     static const UChar expectUnsafe[]={
722         0x61, 0xdf, 0x901, 0x3040,
723         0xac00, 0xd800, 0xdbff, 0xdcde,
724         0xdffd, 0xe000, 0xffff, 0xd800, 0xdc00,
725         0xd808, 0xdf45, 0xdb40, 0xdc21, 0xdbff, 0xdfff, /* not 0x110000 */
726         /* none from this line */
727         0, 0x400
728     }, expectSafe[]={
729         0x61, 0xdf, 0x901, 0x3040,
730         0xac00, 0xd800, 0xdbff, 0xdcde,
731         0xdffd, 0xe000, 0xffff, 0xd800, 0xdc00,
732         0xd808, 0xdf45, 0xdb40, 0xdc21, 0xdbff, 0xdfff, /* not 0x110000 */
733         /* none from this line */
734         0, 0x400
735     };
736 
737     UChar buffer[100];
738     UChar32 c;
739     int32_t i, length;
740     UBool isError, expectIsError, wrongIsError;
741 
742     length=0;
743     for(i=0; i<UPRV_LENGTHOF(codePoints); ++i) {
744         c=codePoints[i];
745         if(c<0 || 0x10ffff<c) {
746             continue; /* skip non-code points for U16_APPEND_UNSAFE */
747         }
748 
749         U16_APPEND_UNSAFE(buffer, length, c);
750     }
751     if(length!=UPRV_LENGTHOF(expectUnsafe) || 0!=memcmp(buffer, expectUnsafe, length*U_SIZEOF_UCHAR)) {
752         log_err("U16_APPEND_UNSAFE did not generate the expected output\n");
753     }
754 
755     length=0;
756     wrongIsError=FALSE;
757     for(i=0; i<UPRV_LENGTHOF(codePoints); ++i) {
758         c=codePoints[i];
759         expectIsError= c<0 || 0x10ffff<c; /* || U_IS_SURROGATE(c); */ /* surrogates in UTF-32 shouldn't be used, but it's okay to pass them around internally. */
760         isError=FALSE;
761 
762         U16_APPEND(buffer, length, UPRV_LENGTHOF(buffer), c, isError);
763         wrongIsError|= isError!=expectIsError;
764     }
765     if(wrongIsError) {
766         log_err("U16_APPEND did not set isError correctly\n");
767     }
768     if(length!=UPRV_LENGTHOF(expectSafe) || 0!=memcmp(buffer, expectSafe, length*U_SIZEOF_UCHAR)) {
769         log_err("U16_APPEND did not generate the expected output\n");
770     }
771 }
772 
TestSurrogate()773 static void TestSurrogate(){
774     static UChar32 s[] = {0x10000, 0x10ffff, 0x50000, 0x100000, 0x1abcd};
775     int i = 0;
776     while (i < 5) {
777         UChar first  = UTF_FIRST_SURROGATE(s[i]);
778         UChar second = UTF_SECOND_SURROGATE(s[i]);
779         /* algorithm from the Unicode consortium */
780         UChar firstresult  = (UChar)(((s[i] - 0x10000) / 0x400) + 0xD800);
781         UChar secondresult = (UChar)(((s[i] - 0x10000) % 0x400) + 0xDC00);
782 
783         if (first != UTF16_LEAD(s[i]) || first != U16_LEAD(s[i]) || first != firstresult) {
784             log_err("Failure in first surrogate in 0x%x expected to be 0x%x\n",
785                     s[i], firstresult);
786         }
787         if (second != UTF16_TRAIL(s[i]) || second != U16_TRAIL(s[i]) || second != secondresult) {
788             log_err("Failure in second surrogate in 0x%x expected to be 0x%x\n",
789                     s[i], secondresult);
790         }
791         i ++;
792     }
793 }
794 
printUChars(const UChar * uchars)795 static void printUChars(const UChar *uchars){
796     int16_t i=0;
797     for(i=0; i<u_strlen(uchars); i++){
798         printf("%x ", *(uchars+i));
799     }
800 }
801