1/********************************************************************
2 * COPYRIGHT:
3 * Copyright (c) 1998-2001, 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 TestFwdBack(void);
33static void TestSetChar(void);
34static void TestAppendChar(void);
35static void TestAppend(void);
36static void TestSurrogate(void);
37
38void addUTF16Test(TestNode** root);
39
40void
41addUTF16Test(TestNode** root)
42{
43  addTest(root, &TestCodeUnitValues,    "utf16tst/TestCodeUnitValues");
44  addTest(root, &TestCharLength,        "utf16tst/TestCharLength"    );
45  addTest(root, &TestGetChar,           "utf16tst/TestGetChar"       );
46  addTest(root, &TestNextPrevChar,      "utf16tst/TestNextPrevChar"  );
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
330static void TestFwdBack(){
331    static UChar input[]={0x0061, 0xd800, 0xdc00, 0xdbff, 0xdfff, 0x0062, 0xd841, 0xd7ff, 0xd841, 0xdc41, 0xdc00, 0x0000};
332    static uint16_t fwd_unsafe[] ={1, 3, 5, 6,  8, 10, 11, 12};
333    static uint16_t fwd_safe[]   ={1, 3, 5, 6, 7, 8, 10, 11, 12};
334    static uint16_t back_unsafe[]={11, 9, 8, 7, 6, 5, 3, 1, 0};
335    static uint16_t back_safe[]  ={11, 10, 8, 7, 6, 5, 3, 1, 0};
336
337    static uint16_t Nvalue[]= {0, 1, 2, 3, 1, 2, 1};
338    static uint16_t fwd_N_unsafe[] ={0, 1, 5, 10, 11};
339    static uint16_t fwd_N_safe[]   ={0, 1, 5, 8, 10, 12, 12}; /*safe macro keeps it at the end of the string */
340    static uint16_t back_N_unsafe[]={12, 11, 8, 5, 3};
341    static uint16_t back_N_safe[]  ={12, 11, 8, 5, 3, 0, 0};
342
343    uint16_t offunsafe=0, offsafe=0;
344    uint16_t i=0;
345    while(offunsafe < sizeof(input)/U_SIZEOF_UCHAR){
346        UTF16_FWD_1_UNSAFE(input, offunsafe);
347        if(offunsafe != fwd_unsafe[i]){
348            log_err("ERROR: Forward_unsafe offset expected:%d, Got:%d\n", fwd_unsafe[i], offunsafe);
349        }
350        i++;
351    }
352
353    offunsafe=0, offsafe=0;
354    i=0;
355    while(offunsafe < sizeof(input)/U_SIZEOF_UCHAR){
356        U16_FWD_1_UNSAFE(input, offunsafe);
357        if(offunsafe != fwd_unsafe[i]){
358            log_err("ERROR: U16_FWD_1_UNSAFE offset expected:%d, Got:%d\n", fwd_unsafe[i], offunsafe);
359        }
360        i++;
361    }
362
363    i=0;
364    while(offsafe < sizeof(input)/U_SIZEOF_UCHAR){
365        UTF16_FWD_1_SAFE(input, offsafe, sizeof(input)/U_SIZEOF_UCHAR);
366        if(offsafe != fwd_safe[i]){
367            log_err("ERROR: Forward_safe offset expected:%d, Got:%d\n", fwd_safe[i], offsafe);
368        }
369        i++;
370    }
371
372    i=0;
373    while(offsafe < sizeof(input)/U_SIZEOF_UCHAR){
374        U16_FWD_1(input, offsafe, sizeof(input)/U_SIZEOF_UCHAR);
375        if(offsafe != fwd_safe[i]){
376            log_err("ERROR: U16_FWD_1 offset expected:%d, Got:%d\n", fwd_safe[i], offsafe);
377        }
378        i++;
379    }
380
381    offunsafe=sizeof(input)/U_SIZEOF_UCHAR;
382    offsafe=sizeof(input)/U_SIZEOF_UCHAR;
383    i=0;
384    while(offunsafe > 0){
385        UTF16_BACK_1_UNSAFE(input, offunsafe);
386        if(offunsafe != back_unsafe[i]){
387            log_err("ERROR: Backward_unsafe offset expected:%d, Got:%d\n", back_unsafe[i], offunsafe);
388        }
389        i++;
390    }
391
392    offunsafe=sizeof(input)/U_SIZEOF_UCHAR;
393    offsafe=sizeof(input)/U_SIZEOF_UCHAR;
394    i=0;
395    while(offunsafe > 0){
396        U16_BACK_1_UNSAFE(input, offunsafe);
397        if(offunsafe != back_unsafe[i]){
398            log_err("ERROR: U16_BACK_1_UNSAFE offset expected:%d, Got:%d\n", back_unsafe[i], offunsafe);
399        }
400        i++;
401    }
402
403    i=0;
404    while(offsafe > 0){
405        UTF16_BACK_1_SAFE(input,0,  offsafe);
406        if(offsafe != back_safe[i]){
407            log_err("ERROR: Backward_safe offset expected:%d, Got:%d\n", back_unsafe[i], offsafe);
408        }
409        i++;
410    }
411
412    i=0;
413    while(offsafe > 0){
414        U16_BACK_1(input,0,  offsafe);
415        if(offsafe != back_safe[i]){
416            log_err("ERROR: U16_BACK_1 offset expected:%d, Got:%d\n", back_unsafe[i], offsafe);
417        }
418        i++;
419    }
420
421    offunsafe=0;
422    offsafe=0;
423    for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0])-2; i++){  /*didn't want it to fail(we assume 0<i<length)*/
424        UTF16_FWD_N_UNSAFE(input, offunsafe, Nvalue[i]);
425        if(offunsafe != fwd_N_unsafe[i]){
426            log_err("ERROR: Forward_N_unsafe offset expected:%d, Got:%d\n", fwd_N_unsafe[i], offunsafe);
427        }
428    }
429
430    offunsafe=0;
431    for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0])-2; i++){  /*didn't want it to fail(we assume 0<i<length)*/
432        U16_FWD_N_UNSAFE(input, offunsafe, Nvalue[i]);
433        if(offunsafe != fwd_N_unsafe[i]){
434            log_err("ERROR: U16_FWD_N_UNSAFE offset expected:%d, Got:%d\n", fwd_N_unsafe[i], offunsafe);
435        }
436    }
437
438    offsafe=0;
439    for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0]); i++){
440        UTF16_FWD_N_SAFE(input, offsafe, sizeof(input)/U_SIZEOF_UCHAR, Nvalue[i]);
441        if(offsafe != fwd_N_safe[i]){
442            log_err("ERROR: Forward_N_safe offset expected:%d, Got:%d\n", fwd_N_safe[i], offsafe);
443        }
444
445    }
446
447    offsafe=0;
448    for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0]); i++){
449        U16_FWD_N(input, offsafe, sizeof(input)/U_SIZEOF_UCHAR, Nvalue[i]);
450        if(offsafe != fwd_N_safe[i]){
451            log_err("ERROR: U16_FWD_N offset expected:%d, Got:%d\n", fwd_N_safe[i], offsafe);
452        }
453
454    }
455
456    offunsafe=sizeof(input)/U_SIZEOF_UCHAR;
457    for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0])-2; i++){
458        UTF16_BACK_N_UNSAFE(input, offunsafe, Nvalue[i]);
459        if(offunsafe != back_N_unsafe[i]){
460            log_err("ERROR: backward_N_unsafe offset expected:%d, Got:%d\n", back_N_unsafe[i], offunsafe);
461        }
462    }
463
464    offunsafe=sizeof(input)/U_SIZEOF_UCHAR;
465    for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0])-2; i++){
466        U16_BACK_N_UNSAFE(input, offunsafe, Nvalue[i]);
467        if(offunsafe != back_N_unsafe[i]){
468            log_err("ERROR: U16_BACK_N_UNSAFE offset expected:%d, Got:%d\n", back_N_unsafe[i], offunsafe);
469        }
470    }
471
472    offsafe=sizeof(input)/U_SIZEOF_UCHAR;
473    for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0]); i++){
474        UTF16_BACK_N_SAFE(input, 0, offsafe, Nvalue[i]);
475        if(offsafe != back_N_safe[i]){
476            log_err("ERROR: backward_N_safe offset expected:%d, Got:%d\n", back_N_safe[i], offsafe);
477        }
478    }
479
480    offsafe=sizeof(input)/U_SIZEOF_UCHAR;
481    for(i=0; i<sizeof(Nvalue)/sizeof(Nvalue[0]); i++){
482        U16_BACK_N(input, 0, offsafe, Nvalue[i]);
483        if(offsafe != back_N_safe[i]){
484            log_err("ERROR: U16_BACK_N offset expected:%d, Got:%d\n", back_N_safe[i], offsafe);
485        }
486    }
487}
488
489static void TestSetChar(){
490    static UChar input[]={0x0061, 0xd800, 0xdc00, 0xdbff, 0xdfff, 0x0062, 0xd841, 0xd7ff, 0xd841, 0xdc41, 0xdc00, 0x0000};
491    static uint16_t start_unsafe[]={0, 1, 1, 3, 3, 5, 6, 7, 8, 8, 9, 11};
492    static uint16_t start_safe[]  ={0, 1, 1, 3, 3, 5, 6, 7, 8, 8, 10, 11};
493    static uint16_t limit_unsafe[]={0, 1, 3, 3, 5, 5, 6, 8, 8, 10, 10, 11};
494    static uint16_t limit_safe[]  ={0, 1, 3, 3, 5, 5, 6, 7, 8, 10, 10, 11};
495
496    uint16_t i=0;
497    uint16_t offset=0, setOffset=0;
498    for(offset=0; offset<sizeof(input)/U_SIZEOF_UCHAR; offset++){
499         setOffset=offset;
500         UTF16_SET_CHAR_START_UNSAFE(input, setOffset);
501         if(setOffset != start_unsafe[i]){
502             log_err("ERROR: UTF16_SET_CHAR_START_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, start_unsafe[i], setOffset);
503         }
504
505         setOffset=offset;
506         U16_SET_CP_START_UNSAFE(input, setOffset);
507         if(setOffset != start_unsafe[i]){
508             log_err("ERROR: U16_SET_CHAR_START_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, start_unsafe[i], setOffset);
509         }
510
511         setOffset=offset;
512         UTF16_SET_CHAR_START_SAFE(input, 0, setOffset);
513         if(setOffset != start_safe[i]){
514             log_err("ERROR: UTF16_SET_CHAR_START_SAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, start_safe[i], setOffset);
515         }
516
517         setOffset=offset;
518         U16_SET_CP_START(input, 0, setOffset);
519         if(setOffset != start_safe[i]){
520             log_err("ERROR: U16_SET_CHAR_START failed for offset=%ld. Expected:%lx Got:%lx\n", offset, start_safe[i], setOffset);
521         }
522
523         if (offset > 0) {
524             setOffset=offset;
525             UTF16_SET_CHAR_LIMIT_UNSAFE(input, setOffset);
526             if(setOffset != limit_unsafe[i]){
527                 log_err("ERROR: UTF16_SET_CHAR_LIMIT_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, limit_unsafe[i], setOffset);
528             }
529
530             setOffset=offset;
531             U16_SET_CP_LIMIT_UNSAFE(input, setOffset);
532             if(setOffset != limit_unsafe[i]){
533                 log_err("ERROR: U16_SET_CHAR_LIMIT_UNSAFE failed for offset=%ld. Expected:%lx Got:%lx\n", offset, limit_unsafe[i], setOffset);
534             }
535         }
536
537         setOffset=offset;
538         U16_SET_CP_LIMIT(input,0, setOffset, sizeof(input)/U_SIZEOF_UCHAR);
539         if(setOffset != limit_safe[i]){
540             log_err("ERROR: U16_SET_CHAR_LIMIT failed for offset=%ld. Expected:%lx Got:%lx\n", offset, limit_safe[i], setOffset);
541         }
542
543         i++;
544    }
545}
546
547static void TestAppendChar(){
548    static UChar s[5]={0x0061, 0x0062, 0x0063, 0x0064, 0x0000};
549    static uint32_t test[]={
550     /*append-position(unsafe),  CHAR to be appended  */
551        0,                        0x20441,
552        2,                        0x0028,
553        2,                        0xdc00,
554        3,                        0xd800,
555        1,                        0x20402,
556
557    /*append-position(safe),     CHAR to be appended */
558        0,                        0x20441,
559        2,                        0xdc00,
560        3,                        0xd800,
561        1,                        0x20402,
562        3,                        0x20402,
563        3,                        0x10402,
564        2,                        0x10402,
565
566    };
567    static uint16_t movedOffset[]={
568        /*offset-moved-to(unsafe)*/
569          2,              /*for append-pos: 0 , CHAR 0x20441*/
570          3,
571          3,
572          4,
573          3,
574          /*offse-moved-to(safe)*/
575          2,              /*for append-pos: 0, CHAR  0x20441*/
576          3,
577          4,
578          3,
579          4,
580          4,
581          4
582    };
583
584    static UChar result[][5]={
585        /*unsafe*/
586        {0xd841, 0xdc41, 0x0063, 0x0064, 0x0000},
587        {0x0061, 0x0062, 0x0028, 0x0064, 0x0000},
588        {0x0061, 0x0062, 0xdc00, 0x0064, 0x0000},
589        {0x0061, 0x0062, 0x0063, 0xd800, 0x0000},
590        {0x0061, 0xd841, 0xdc02, 0x0064, 0x0000},
591
592        /*safe*/
593        {0xd841, 0xdc41, 0x0063, 0x0064, 0x0000},
594        {0x0061, 0x0062, 0xdc00, 0x0064, 0x0000},
595        {0x0061, 0x0062, 0x0063, 0xd800, 0x0000},
596        {0x0061, 0xd841, 0xdc02, 0x0064, 0x0000},
597        {0x0061, 0x0062, 0x0063, UTF_ERROR_VALUE, 0x0000},
598        {0x0061, 0x0062, 0x0063, UTF_ERROR_VALUE, 0x0000},
599        {0x0061, 0x0062, 0xd801, 0xdc02, 0x0000},
600
601
602    };
603    uint16_t i, count=0;
604    UChar *str=(UChar*)malloc(sizeof(UChar) * (u_strlen(s)+1));
605    uint16_t offset;
606    for(i=0; i<sizeof(test)/sizeof(test[0]); i=(uint16_t)(i+2)){
607        if(count<5){
608            u_strcpy(str, s);
609            offset=(uint16_t)test[i];
610            UTF16_APPEND_CHAR_UNSAFE(str, offset, test[i+1]);
611            if(offset != movedOffset[count]){
612                log_err("ERROR: UTF16_APPEND_CHAR_UNSAFE failed to move the offset correctly for count=%d.\nExpectedOffset=%d  currentOffset=%d\n",
613                    count, movedOffset[count], offset);
614
615            }
616            if(u_strcmp(str, result[count]) !=0){
617                log_err("ERROR: UTF16_APPEND_CHAR_UNSAFE failed for count=%d. Expected:", count);
618                printUChars(result[count]);
619                printf("\nGot:");
620                printUChars(str);
621                printf("\n");
622            }
623        }else{
624            u_strcpy(str, s);
625            offset=(uint16_t)test[i];
626            UTF16_APPEND_CHAR_SAFE(str, offset, (uint16_t)u_strlen(str), test[i+1]);
627            if(offset != movedOffset[count]){
628                log_err("ERROR: UTF16_APPEND_CHAR_SAFE failed to move the offset correctly for count=%d.\nExpectedOffset=%d  currentOffset=%d\n",
629                    count, movedOffset[count], offset);
630
631            }
632            if(u_strcmp(str, result[count]) !=0){
633                log_err("ERROR: UTF16_APPEND_CHAR_SAFE failed for count=%d. Expected:", count);
634                printUChars(result[count]);
635                printf("\nGot:");
636                printUChars(str);
637                printf("\n");
638            }
639        }
640        count++;
641    }
642    free(str);
643
644}
645
646static void TestAppend() {
647    static const UChar32 codePoints[]={
648        0x61, 0xdf, 0x901, 0x3040,
649        0xac00, 0xd800, 0xdbff, 0xdcde,
650        0xdffd, 0xe000, 0xffff, 0x10000,
651        0x12345, 0xe0021, 0x10ffff, 0x110000,
652        0x234567, 0x7fffffff, -1, -1000,
653        0, 0x400
654    };
655    static const UChar expectUnsafe[]={
656        0x61, 0xdf, 0x901, 0x3040,
657        0xac00, 0xd800, 0xdbff, 0xdcde,
658        0xdffd, 0xe000, 0xffff, 0xd800, 0xdc00,
659        0xd808, 0xdf45, 0xdb40, 0xdc21, 0xdbff, 0xdfff, /* not 0x110000 */
660        /* none from this line */
661        0, 0x400
662    }, expectSafe[]={
663        0x61, 0xdf, 0x901, 0x3040,
664        0xac00, 0xd800, 0xdbff, 0xdcde,
665        0xdffd, 0xe000, 0xffff, 0xd800, 0xdc00,
666        0xd808, 0xdf45, 0xdb40, 0xdc21, 0xdbff, 0xdfff, /* not 0x110000 */
667        /* none from this line */
668        0, 0x400
669    };
670
671    UChar buffer[100];
672    UChar32 c;
673    int32_t i, length;
674    UBool isError, expectIsError, wrongIsError;
675
676    length=0;
677    for(i=0; i<LENGTHOF(codePoints); ++i) {
678        c=codePoints[i];
679        if(c<0 || 0x10ffff<c) {
680            continue; /* skip non-code points for U16_APPEND_UNSAFE */
681        }
682
683        U16_APPEND_UNSAFE(buffer, length, c);
684    }
685    if(length!=LENGTHOF(expectUnsafe) || 0!=memcmp(buffer, expectUnsafe, length*U_SIZEOF_UCHAR)) {
686        log_err("U16_APPEND_UNSAFE did not generate the expected output\n");
687    }
688
689    length=0;
690    wrongIsError=FALSE;
691    for(i=0; i<LENGTHOF(codePoints); ++i) {
692        c=codePoints[i];
693        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. */
694        isError=FALSE;
695
696        U16_APPEND(buffer, length, LENGTHOF(buffer), c, isError);
697        wrongIsError|= isError!=expectIsError;
698    }
699    if(wrongIsError) {
700        log_err("U16_APPEND did not set isError correctly\n");
701    }
702    if(length!=LENGTHOF(expectSafe) || 0!=memcmp(buffer, expectSafe, length*U_SIZEOF_UCHAR)) {
703        log_err("U16_APPEND did not generate the expected output\n");
704    }
705}
706
707static void TestSurrogate(){
708    static UChar32 s[] = {0x10000, 0x10ffff, 0x50000, 0x100000, 0x1abcd};
709    int i = 0;
710    while (i < 5) {
711        UChar first  = UTF_FIRST_SURROGATE(s[i]);
712        UChar second = UTF_SECOND_SURROGATE(s[i]);
713        /* algorithm from the Unicode consortium */
714        UChar firstresult  = (UChar)(((s[i] - 0x10000) / 0x400) + 0xD800);
715        UChar secondresult = (UChar)(((s[i] - 0x10000) % 0x400) + 0xDC00);
716
717        if (first != UTF16_LEAD(s[i]) || first != U16_LEAD(s[i]) || first != firstresult) {
718            log_err("Failure in first surrogate in 0x%x expected to be 0x%x\n",
719                    s[i], firstresult);
720        }
721        if (second != UTF16_TRAIL(s[i]) || second != U16_TRAIL(s[i]) || second != secondresult) {
722            log_err("Failure in second surrogate in 0x%x expected to be 0x%x\n",
723                    s[i], secondresult);
724        }
725        i ++;
726    }
727}
728
729static void printUChars(const UChar *uchars){
730    int16_t i=0;
731    for(i=0; i<u_strlen(uchars); i++){
732        printf("%x ", *(uchars+i));
733    }
734}
735