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
24static void printUChars(const UChar *uchars);
25
26static void TestCodeUnitValues(void);
27static void TestCharLength(void);
28static void TestGetChar(void);
29static void TestNextPrevChar(void);
30static void TestNulTerminated(void);
31static void TestFwdBack(void);
32static void TestSetChar(void);
33static void TestAppendChar(void);
34static void TestAppend(void);
35static void TestSurrogate(void);
36
37void addUTF16Test(TestNode** root);
38
39void
40addUTF16Test(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
54static 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
80static 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
111static 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
182static 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() */
331static 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
396static 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
555static 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
613static 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
712static 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
773static 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
795static 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