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