]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-52_1/main/tests/core/src/com/ibm/icu/dev/test/lang/UTF16Test.java
Added flags.
[Dictionary.git] / jars / icu4j-52_1 / main / tests / core / src / com / ibm / icu / dev / test / lang / UTF16Test.java
1 /*
2 *******************************************************************************
3 * Copyright (C) 1996-2010, International Business Machines Corporation and    *
4 * others. All Rights Reserved.                                                *
5 *******************************************************************************
6 */
7
8 package com.ibm.icu.dev.test.lang;
9
10 import com.ibm.icu.dev.test.TestFmwk;
11 import com.ibm.icu.dev.test.UTF16Util;
12 import com.ibm.icu.impl.Utility;
13 import com.ibm.icu.lang.UCharacter;
14 import com.ibm.icu.text.ReplaceableString;
15 import com.ibm.icu.text.UTF16;
16
17 /**
18 * Testing class for UTF16
19 * @author Syn Wee Quek
20 * @since feb 09 2001
21 */
22 public final class UTF16Test extends TestFmwk
23 {
24     // constructor ===================================================
25
26     /**
27      * Constructor
28      */
29     public UTF16Test()
30     {
31     }
32
33     // public methods ================================================
34
35     /**
36      * Testing UTF16 class methods append
37      */
38     public void TestAppend()
39     {
40           StringBuffer strbuff = new StringBuffer("this is a string ");
41           char array[] = new char[UCharacter.MAX_VALUE >> 2];
42           int strsize = strbuff.length();
43           int arraysize = strsize;
44
45           if (0 != strsize) {
46             strbuff.getChars(0, strsize, array, 0);
47         }
48           for (int i = 1; i < UCharacter.MAX_VALUE; i += 100) {
49         UTF16.append(strbuff, i);
50         arraysize = UTF16.append(array, arraysize, i);
51
52         String arraystr = new String(array, 0, arraysize);
53         if (!arraystr.equals(strbuff.toString())) {
54         errln("FAIL Comparing char array append and string append " +
55               "with 0x" + Integer.toHexString(i));
56         }
57
58         // this is to cater for the combination of 0xDBXX 0xDC50 which
59         // forms a supplementary character
60         if (i == 0xDC51) {
61         strsize --;
62         }
63
64         if (UTF16.countCodePoint(strbuff) != strsize + (i / 100) + 1) {
65         errln("FAIL Counting code points in string appended with " +
66               " 0x" + Integer.toHexString(i));
67         break;
68         }
69     }
70
71     // coverage for new 1.5 - cover only so no real test
72     strbuff = new StringBuffer();
73     UTF16.appendCodePoint(strbuff, 0x10000);
74     if (strbuff.length() != 2) {
75         errln("fail appendCodePoint");
76     }
77     }
78
79     /**
80      * Testing UTF16 class methods bounds
81      */
82     public void TestBounds()
83     {
84           StringBuffer strbuff =
85                         //0     12345     6     7     8     9
86         new StringBuffer("\udc000123\ud800\udc00\ud801\udc01\ud802");
87           String str = strbuff.toString();
88           char array[] = str.toCharArray();
89           int boundtype[] = {UTF16.SINGLE_CHAR_BOUNDARY,
90                UTF16.SINGLE_CHAR_BOUNDARY,
91                UTF16.SINGLE_CHAR_BOUNDARY,
92                UTF16.SINGLE_CHAR_BOUNDARY,
93                UTF16.SINGLE_CHAR_BOUNDARY,
94                UTF16.LEAD_SURROGATE_BOUNDARY,
95                UTF16.TRAIL_SURROGATE_BOUNDARY,
96                UTF16.LEAD_SURROGATE_BOUNDARY,
97                UTF16.TRAIL_SURROGATE_BOUNDARY,
98                UTF16.SINGLE_CHAR_BOUNDARY};
99           int length = str.length();
100           for (int i = 0; i < length; i ++) {
101         if (UTF16.bounds(str, i) != boundtype[i]) {
102                   errln("FAIL checking bound type at index " + i);
103         }
104         if (UTF16.bounds(strbuff, i) != boundtype[i]) {
105                   errln("FAIL checking bound type at index " + i);
106         }
107         if (UTF16.bounds(array, 0, length, i) != boundtype[i]) {
108                   errln("FAIL checking bound type at index " + i);
109         }
110           }
111           // does not straddle between supplementary character
112           int start = 4;
113           int limit = 9;
114           int subboundtype1[] = {UTF16.SINGLE_CHAR_BOUNDARY,
115                    UTF16.LEAD_SURROGATE_BOUNDARY,
116                    UTF16.TRAIL_SURROGATE_BOUNDARY,
117                    UTF16.LEAD_SURROGATE_BOUNDARY,
118                    UTF16.TRAIL_SURROGATE_BOUNDARY};
119           try {
120         UTF16.bounds(array, start, limit, -1);
121         errln("FAIL Out of bounds index in bounds should fail");
122           } catch (Exception e) {
123         // getting rid of warnings
124         System.out.print("");
125           }
126
127           for (int i = 0; i < limit - start; i ++) {
128         if (UTF16.bounds(array, start, limit, i) != subboundtype1[i]) {
129                   errln("FAILED Subarray bounds in [" + start + ", " + limit +
130               "] expected " + subboundtype1[i] + " at offset " + i);
131         }
132           }
133
134           // starts from the mid of a supplementary character
135           int subboundtype2[] = {UTF16.SINGLE_CHAR_BOUNDARY,
136                    UTF16.LEAD_SURROGATE_BOUNDARY,
137                    UTF16.TRAIL_SURROGATE_BOUNDARY};
138
139           start = 6;
140           limit = 9;
141           for (int i = 0; i < limit - start; i ++) {
142         if (UTF16.bounds(array, start, limit, i) != subboundtype2[i]) {
143                   errln("FAILED Subarray bounds in [" + start + ", " + limit +
144               "] expected " + subboundtype2[i] + " at offset " + i);
145         }
146           }
147
148           // ends in the mid of a supplementary character
149           int subboundtype3[] = {UTF16.LEAD_SURROGATE_BOUNDARY,
150                    UTF16.TRAIL_SURROGATE_BOUNDARY,
151                    UTF16.SINGLE_CHAR_BOUNDARY};
152           start = 5;
153           limit = 8;
154           for (int i = 0; i < limit - start; i ++) {
155         if (UTF16.bounds(array, start, limit, i) != subboundtype3[i]) {
156                   errln("FAILED Subarray bounds in [" + start + ", " + limit +
157               "] expected " + subboundtype3[i] + " at offset " + i);
158         }
159           }
160     }
161
162     /**
163      * Testing UTF16 class methods charAt and charAtCodePoint
164      */
165     public void TestCharAt()
166     {
167           StringBuffer strbuff =
168         new StringBuffer("12345\ud800\udc0167890\ud800\udc02");
169           if (UTF16.charAt(strbuff, 0) != '1' || UTF16.charAt(strbuff, 2) != '3'
170               || UTF16.charAt(strbuff, 5) != 0x10001 ||
171         UTF16.charAt(strbuff, 6) != 0x10001 ||
172         UTF16.charAt(strbuff, 12) != 0x10002 ||
173         UTF16.charAt(strbuff, 13) != 0x10002) {
174         errln("FAIL Getting character from string buffer error" );
175           }
176           String str = strbuff.toString();
177           if (UTF16.charAt(str, 0) != '1' || UTF16.charAt(str, 2) != '3' ||
178         UTF16.charAt(str, 5) != 0x10001 || UTF16.charAt(str, 6) != 0x10001
179         || UTF16.charAt(str, 12) != 0x10002 ||
180         UTF16.charAt(str, 13) != 0x10002)
181         {
182               errln("FAIL Getting character from string error" );
183         }
184           char array[] = str.toCharArray();
185           int start = 0;
186           int limit = str.length();
187           if (UTF16.charAt(array, start, limit, 0) != '1' ||
188         UTF16.charAt(array, start, limit, 2) != '3' ||
189         UTF16.charAt(array, start, limit, 5) != 0x10001 ||
190         UTF16.charAt(array, start, limit, 6) != 0x10001 ||
191         UTF16.charAt(array, start, limit, 12) != 0x10002 ||
192         UTF16.charAt(array, start, limit, 13) != 0x10002) {
193         errln("FAIL Getting character from array error" );
194           }
195           // check the sub array here.
196           start = 6;
197           limit = 13;
198           try {
199         UTF16.charAt(array, start, limit, -1);
200         errln("FAIL out of bounds error expected");
201           } catch (Exception e) {
202         System.out.print("");
203           }
204           try {
205         UTF16.charAt(array, start, limit, 8);
206         errln("FAIL out of bounds error expected");
207           } catch (Exception e) {
208         System.out.print("");
209           }
210           if (UTF16.charAt(array, start, limit, 0) != 0xdc01) {
211         errln("FAIL Expected result in subarray 0xdc01");
212           }
213           if (UTF16.charAt(array, start, limit, 6) != 0xd800) {
214         errln("FAIL Expected result in subarray 0xd800");
215           }
216           ReplaceableString replaceable = new ReplaceableString(str);
217           if (UTF16.charAt(replaceable, 0) != '1' ||
218               UTF16.charAt(replaceable, 2) != '3' ||
219         UTF16.charAt(replaceable, 5) != 0x10001 ||
220         UTF16.charAt(replaceable, 6) != 0x10001 ||
221         UTF16.charAt(replaceable, 12) != 0x10002 ||
222         UTF16.charAt(replaceable, 13) != 0x10002) {
223         errln("FAIL Getting character from replaceable error" );
224           }
225           
226           StringBuffer strbuffer = new StringBuffer("0xD805");
227           UTF16.charAt((CharSequence)strbuffer, 0);
228     }
229
230     /**
231      * Testing UTF16 class methods countCodePoint
232      */
233     public void TestCountCodePoint()
234     {
235         StringBuffer strbuff = new StringBuffer("");
236         char         array[] = null;
237         if (UTF16.countCodePoint(strbuff) != 0 ||
238         UTF16.countCodePoint("") != 0 ||
239         UTF16.countCodePoint(array,0 ,0) != 0) {
240         errln("FAIL Counting code points for empty strings");
241         }
242
243         strbuff = new StringBuffer("this is a string ");
244         String str = strbuff.toString();
245         array = str.toCharArray();
246         int size = str.length();
247
248         if (UTF16.countCodePoint(array, 0, 0) != 0) {
249         errln("FAIL Counting code points for 0 offset array");
250         }
251
252         if (UTF16.countCodePoint(str) != size ||
253         UTF16.countCodePoint(strbuff) != size ||
254         UTF16.countCodePoint(array, 0, size) != size) {
255         errln("FAIL Counting code points");
256         }
257
258         UTF16.append(strbuff, 0x10000);
259         str = strbuff.toString();
260         array = str.toCharArray();
261         if (UTF16.countCodePoint(str) != size + 1 ||
262         UTF16.countCodePoint(strbuff) != size + 1 ||
263         UTF16.countCodePoint(array, 0, size + 1) != size + 1 ||
264         UTF16.countCodePoint(array, 0, size + 2) != size + 1) {
265         errln("FAIL Counting code points");
266         }
267         UTF16.append(strbuff, 0x61);
268         str = strbuff.toString();
269         array = str.toCharArray();
270         if (UTF16.countCodePoint(str) != size + 2 ||
271         UTF16.countCodePoint(strbuff) != size + 2 ||
272         UTF16.countCodePoint(array, 0, size + 1) != size + 1 ||
273         UTF16.countCodePoint(array, 0, size + 2) != size + 1 ||
274         UTF16.countCodePoint(array, 0, size + 3) != size + 2) {
275         errln("FAIL Counting code points");
276         }
277     }
278
279     /**
280      * Testing UTF16 class methods delete
281      */
282     public void TestDelete()
283     {                                        //01234567890123456
284         StringBuffer strbuff = new StringBuffer("these are strings");
285         int size = strbuff.length();
286         char array[] = strbuff.toString().toCharArray();
287
288         UTF16.delete(strbuff, 3);
289         UTF16.delete(strbuff, 3);
290         UTF16.delete(strbuff, 3);
291         UTF16.delete(strbuff, 3);
292         UTF16.delete(strbuff, 3);
293         UTF16.delete(strbuff, 3);
294         try {
295         UTF16.delete(strbuff, strbuff.length());
296         errln("FAIL deleting out of bounds character should fail");
297         } catch (Exception e) {
298         System.out.print("");
299         }
300         UTF16.delete(strbuff, strbuff.length() - 1);
301         if (!strbuff.toString().equals("the string")) {
302         errln("FAIL expected result after deleting characters is " +
303           "\"the string\"");
304         }
305
306         size = UTF16.delete(array, size, 3);
307         size = UTF16.delete(array, size, 3);
308         size = UTF16.delete(array, size, 3);
309         size = UTF16.delete(array, size, 3);
310         size = UTF16.delete(array, size, 3);
311         size = UTF16.delete(array, size, 3);
312         try {
313         UTF16.delete(array, size, size);
314         errln("FAIL deleting out of bounds character should fail");
315         } catch (Exception e) {
316         System.out.print("");
317         }
318         size = UTF16.delete(array, size, size - 1);
319         String str = new String(array, 0, size);
320         if (!str.equals("the string")) {
321         errln("FAIL expected result after deleting characters is " +
322           "\"the string\"");
323         }
324     //012345678     9     01     2      3     4
325         strbuff = new StringBuffer("string: \ud800\udc00 \ud801\udc01 \ud801\udc01");
326         size = strbuff.length();
327         array = strbuff.toString().toCharArray();
328
329         UTF16.delete(strbuff, 8);
330         UTF16.delete(strbuff, 8);
331         UTF16.delete(strbuff, 9);
332         UTF16.delete(strbuff, 8);
333         UTF16.delete(strbuff, 9);
334         UTF16.delete(strbuff, 6);
335         UTF16.delete(strbuff, 6);
336         if (!strbuff.toString().equals("string")) {
337         errln("FAIL expected result after deleting characters is \"string\"");
338         }
339
340         size = UTF16.delete(array, size, 8);
341         size = UTF16.delete(array, size, 8);
342         size = UTF16.delete(array, size, 9);
343         size = UTF16.delete(array, size, 8);
344         size = UTF16.delete(array, size, 9);
345         size = UTF16.delete(array, size, 6);
346         size = UTF16.delete(array, size, 6);
347         str = new String(array, 0, size);
348         if (!str.equals("string")) {
349         errln("FAIL expected result after deleting characters is \"string\"");
350         }
351     }
352
353     /**
354      * Testing findOffsetFromCodePoint and findCodePointOffset
355      */
356     public void TestfindOffset()
357     {
358         // jitterbug 47
359         String str = "a\uD800\uDC00b";
360         StringBuffer strbuff = new StringBuffer(str);
361         char array[] = str.toCharArray();
362         int limit = str.length();
363         if (UTF16.findCodePointOffset(str, 0) != 0 ||
364         UTF16.findOffsetFromCodePoint(str, 0) != 0 ||
365         UTF16.findCodePointOffset(strbuff, 0) != 0 ||
366         UTF16.findOffsetFromCodePoint(strbuff, 0) != 0 ||
367         UTF16.findCodePointOffset(array, 0, limit, 0) != 0 ||
368         UTF16.findOffsetFromCodePoint(array, 0, limit, 0) != 0) {
369         errln("FAIL Getting the first codepoint offset to a string with " +
370           "supplementary characters");
371         }
372         if (UTF16.findCodePointOffset(str, 1) != 1 ||
373         UTF16.findOffsetFromCodePoint(str, 1) != 1 ||
374         UTF16.findCodePointOffset(strbuff, 1) != 1 ||
375         UTF16.findOffsetFromCodePoint(strbuff, 1) != 1 ||
376         UTF16.findCodePointOffset(array, 0, limit, 1) != 1 ||
377         UTF16.findOffsetFromCodePoint(array, 0, limit, 1) != 1) {
378         errln("FAIL Getting the second codepoint offset to a string with " +
379           "supplementary characters");
380         }
381         if (UTF16.findCodePointOffset(str, 2) != 1 ||
382         UTF16.findOffsetFromCodePoint(str, 2) != 3 ||
383         UTF16.findCodePointOffset(strbuff, 2) != 1 ||
384         UTF16.findOffsetFromCodePoint(strbuff, 2) != 3 ||
385         UTF16.findCodePointOffset(array, 0, limit, 2) != 1 ||
386         UTF16.findOffsetFromCodePoint(array, 0, limit, 2) != 3) {
387         errln("FAIL Getting the third codepoint offset to a string with " +
388           "supplementary characters");
389         }
390         if (UTF16.findCodePointOffset(str, 3) != 2 ||
391         UTF16.findOffsetFromCodePoint(str, 3) != 4 ||
392         UTF16.findCodePointOffset(strbuff, 3) != 2 ||
393         UTF16.findOffsetFromCodePoint(strbuff, 3) != 4 ||
394         UTF16.findCodePointOffset(array, 0, limit, 3) != 2 ||
395         UTF16.findOffsetFromCodePoint(array, 0, limit, 3) != 4) {
396         errln("FAIL Getting the last codepoint offset to a string with " +
397           "supplementary characters");
398         }
399         if (UTF16.findCodePointOffset(str, 4) != 3 ||
400         UTF16.findCodePointOffset(strbuff, 4) != 3 ||
401         UTF16.findCodePointOffset(array, 0, limit, 4) != 3) {
402         errln("FAIL Getting the length offset to a string with " +
403           "supplementary characters");
404         }
405         try {
406         UTF16.findCodePointOffset(str, 5);
407         errln("FAIL Getting the a non-existence codepoint to a string " +
408           "with supplementary characters");
409         } catch (Exception e) {
410         // this is a success
411         logln("Passed out of bounds codepoint offset");
412         }
413         try {
414         UTF16.findOffsetFromCodePoint(str, 4);
415         errln("FAIL Getting the a non-existence codepoint to a string " +
416           "with supplementary characters");
417         } catch (Exception e) {
418         // this is a success
419         logln("Passed out of bounds codepoint offset");
420         }
421         try {
422         UTF16.findCodePointOffset(strbuff, 5);
423         errln("FAIL Getting the a non-existence codepoint to a string " +
424           "with supplementary characters");
425         } catch (Exception e) {
426         // this is a success
427         logln("Passed out of bounds codepoint offset");
428         }
429         try {
430         UTF16.findOffsetFromCodePoint(strbuff, 4);
431         errln("FAIL Getting the a non-existence codepoint to a string " +
432           "with supplementary characters");
433         } catch (Exception e) {
434         // this is a success
435         logln("Passed out of bounds codepoint offset");
436         }
437         try {
438         UTF16.findCodePointOffset(array, 0, limit, 5);
439         errln("FAIL Getting the a non-existence codepoint to a string " +
440           "with supplementary characters");
441         } catch (Exception e) {
442         // this is a success
443         logln("Passed out of bounds codepoint offset");
444         }
445         try {
446         UTF16.findOffsetFromCodePoint(array, 0, limit, 4);
447         errln("FAIL Getting the a non-existence codepoint to a string " +
448           "with supplementary characters");
449         } catch (Exception e) {
450         // this is a success
451         logln("Passed out of bounds codepoint offset");
452         }
453
454         if (UTF16.findCodePointOffset(array, 1, 3, 0) != 0 ||
455         UTF16.findOffsetFromCodePoint(array, 1, 3, 0) != 0 ||
456         UTF16.findCodePointOffset(array, 1, 3, 1) != 0 ||
457         UTF16.findCodePointOffset(array, 1, 3, 2) != 1 ||
458         UTF16.findOffsetFromCodePoint(array, 1, 3, 1) != 2) {
459         errln("FAIL Getting valid codepoint offset in sub array");
460         }
461     }
462
463     /**
464      * Testing UTF16 class methods getCharCount, *Surrogate
465      */
466     public void TestGetCharCountSurrogate()
467     {
468         if (UTF16.getCharCount(0x61) != 1 ||
469         UTF16.getCharCount(0x10000) != 2) {
470         errln("FAIL getCharCount result failure");
471         }
472         if (UTF16.getLeadSurrogate(0x61) != 0 ||
473         UTF16.getTrailSurrogate(0x61) != 0x61 ||
474         UTF16.isLeadSurrogate((char)0x61) ||
475         UTF16.isTrailSurrogate((char)0x61) ||
476         UTF16.getLeadSurrogate(0x10000) != 0xd800 ||
477         UTF16.getTrailSurrogate(0x10000) != 0xdc00 ||
478         UTF16.isLeadSurrogate((char)0xd800) != true ||
479         UTF16.isTrailSurrogate((char)0xd800) ||
480         UTF16.isLeadSurrogate((char)0xdc00) ||
481         UTF16.isTrailSurrogate((char)0xdc00) != true) {
482         errln("FAIL *Surrogate result failure");
483         }
484
485         if (UTF16.isSurrogate((char)0x61) || !UTF16.isSurrogate((char)0xd800)
486             || !UTF16.isSurrogate((char)0xdc00)) {
487         errln("FAIL isSurrogate result failure");
488         }
489     }
490
491     /**
492      * Testing UTF16 class method insert
493      */
494     public void TestInsert()
495     {
496         StringBuffer strbuff = new StringBuffer("0123456789");
497         char array[] = new char[128];
498         int srcEnd = strbuff.length();
499         if (0 != srcEnd) {
500             strbuff.getChars(0, srcEnd, array, 0);
501         }
502         int length = 10;
503         UTF16.insert(strbuff, 5, 't');
504         UTF16.insert(strbuff, 5, 's');
505         UTF16.insert(strbuff, 5, 'e');
506         UTF16.insert(strbuff, 5, 't');
507         if (!(strbuff.toString().equals("01234test56789"))) {
508         errln("FAIL inserting \"test\"");
509         }
510         length = UTF16.insert(array, length, 5, 't');
511         length = UTF16.insert(array, length, 5, 's');
512         length = UTF16.insert(array, length, 5, 'e');
513         length = UTF16.insert(array, length, 5, 't');
514         String str = new String(array, 0, length);
515         if (!(str.equals("01234test56789"))) {
516         errln("FAIL inserting \"test\"");
517         }
518         UTF16.insert(strbuff, 0, 0x10000);
519         UTF16.insert(strbuff, 11, 0x10000);
520         UTF16.insert(strbuff, strbuff.length(), 0x10000);
521         if (!(strbuff.toString().equals(
522                     "\ud800\udc0001234test\ud800\udc0056789\ud800\udc00"))) {
523         errln("FAIL inserting supplementary characters");
524         }
525         length = UTF16.insert(array, length, 0, 0x10000);
526         length = UTF16.insert(array, length, 11, 0x10000);
527         length = UTF16.insert(array, length, length, 0x10000);
528         str = new String(array, 0, length);
529         if (!(str.equals(
530              "\ud800\udc0001234test\ud800\udc0056789\ud800\udc00"))) {
531         errln("FAIL inserting supplementary characters");
532         }
533
534         try {
535         UTF16.insert(strbuff, -1, 0);
536         errln("FAIL invalid insertion offset");
537         } catch (Exception e) {
538         System.out.print("");
539         }
540         try {
541         UTF16.insert(strbuff, 64, 0);
542         errln("FAIL invalid insertion offset");
543         } catch (Exception e) {
544         System.out.print("");
545         }
546         try {
547         UTF16.insert(array, length, -1, 0);
548         errln("FAIL invalid insertion offset");
549         } catch (Exception e) {
550         System.out.print("");
551         }
552         try {
553         UTF16.insert(array, length, 64, 0);
554         errln("FAIL invalid insertion offset");
555         } catch (Exception e) {
556         System.out.print("");
557         }
558         try {
559         // exceeded array size
560         UTF16.insert(array, array.length, 64, 0);
561         errln("FAIL invalid insertion offset");
562         } catch (Exception e) {
563         System.out.print("");
564         }
565     }
566
567     /*
568      * Testing moveCodePointOffset APIs
569      */
570
571     //
572     //   checkMoveCodePointOffset
573     //      Run a single test case through each of the moveCodePointOffset() functions.
574     //          Parameters -
575     //              s               The string to work in.
576     //              startIdx        The starting position within the string.
577     //              amount          The number of code points to move.
578     //              expectedResult  The string index after the move, or -1 if the
579     //                              function should throw an exception.
580     private void checkMoveCodePointOffset(String s, int startIdx, int amount, int expectedResult) {
581         // Test with the String flavor of moveCodePointOffset
582         try {
583             int result = UTF16.moveCodePointOffset(s, startIdx, amount);
584             if (result != expectedResult) {
585                 errln("FAIL: UTF16.moveCodePointOffset(String \"" + s + "\", " + startIdx + ", " + amount + ")" +
586                         " returned "  + result + ", expected result was " +
587                         (expectedResult==-1 ? "exception" : Integer.toString(expectedResult)));
588             }
589         }
590         catch (IndexOutOfBoundsException e) {
591             if (expectedResult != -1) {
592                 errln("FAIL: UTF16.moveCodePointOffset(String \"" + s + "\", " + startIdx + ", " + amount + ")" +
593                         " returned exception" + ", expected result was " + expectedResult);
594             }
595         }
596
597         // Test with the StringBuffer flavor of moveCodePointOffset
598         StringBuffer sb = new StringBuffer(s);
599         try {
600             int result = UTF16.moveCodePointOffset(sb, startIdx, amount);
601             if (result != expectedResult) {
602                 errln("FAIL: UTF16.moveCodePointOffset(StringBuffer \"" + s + "\", " + startIdx + ", " + amount + ")" +
603                         " returned "  + result + ", expected result was " +
604                         (expectedResult==-1 ? "exception" : Integer.toString(expectedResult)));
605             }
606         }
607         catch (IndexOutOfBoundsException e) {
608             if (expectedResult != -1) {
609                 errln("FAIL: UTF16.moveCodePointOffset(StringBuffer \"" + s + "\", " + startIdx + ", " + amount + ")" +
610                         " returned exception" + ", expected result was " + expectedResult);
611             }
612         }
613
614         // Test with the char[] flavor of moveCodePointOffset
615         char ca[] = s.toCharArray();
616         try {
617             int result = UTF16.moveCodePointOffset(ca, 0, s.length(), startIdx, amount);
618             if (result != expectedResult) {
619                 errln("FAIL: UTF16.moveCodePointOffset(char[] \"" + s + "\", 0, " + s.length()
620                         + ", " + startIdx + ", " + amount + ")" +
621                         " returned "  + result + ", expected result was " +
622                         (expectedResult==-1 ? "exception" : Integer.toString(expectedResult)));
623             }
624         }
625         catch (IndexOutOfBoundsException e) {
626             if (expectedResult != -1) {
627                 errln("FAIL: UTF16.moveCodePointOffset(char[] \"" + s + "\", 0, " + s.length()
628                         + ", " + startIdx + ", " + amount + ")" +
629                         " returned exception" + ", expected result was " + expectedResult);
630             }
631         }
632
633         // Put the test string into the interior of a char array,
634         //   run test on the subsection of the array.
635         char ca2[] = new char[s.length()+2];
636         ca2[0] = (char)0xd800;
637         ca2[s.length()+1] = (char)0xd8ff;
638         s.getChars(0, s.length(), ca2, 1);
639         try {
640             int result = UTF16.moveCodePointOffset(ca2, 1, s.length()+1, startIdx, amount);
641             if (result != expectedResult) {
642                 errln("UTF16.moveCodePointOffset(char[] \"" + "." + s + ".\", 1, " + (s.length()+1)
643                         + ", " + startIdx + ", " + amount + ")" +
644                          " returned "  + result + ", expected result was " +
645                         (expectedResult==-1 ? "exception" : Integer.toString(expectedResult)));
646             }
647         }
648         catch (IndexOutOfBoundsException e) {
649             if (expectedResult != -1) {
650                 errln("UTF16.moveCodePointOffset(char[] \"" + "." + s + ".\", 1, " + (s.length()+1)
651                         + ", " + startIdx + ", " + amount + ")" +
652                         " returned exception" + ", expected result was " + expectedResult);
653             }
654         }
655
656     }
657
658
659     public void TestMoveCodePointOffset()
660     {
661         // checkMoveCodePointOffset(String, startIndex, amount, expected );  expected=-1 for exception.
662
663         // No Supplementary chars
664         checkMoveCodePointOffset("abc", 1,  1, 2);
665         checkMoveCodePointOffset("abc", 1, -1, 0);
666         checkMoveCodePointOffset("abc", 1, -2, -1);
667         checkMoveCodePointOffset("abc", 1,  2, 3);
668         checkMoveCodePointOffset("abc", 1,  3, -1);
669         checkMoveCodePointOffset("abc", 1,  0, 1);
670
671         checkMoveCodePointOffset("abc", 3, 0, 3);
672         checkMoveCodePointOffset("abc", 4, 0, -1);
673         checkMoveCodePointOffset("abc", 0, 0, 0);
674         checkMoveCodePointOffset("abc", -1, 0, -1);
675
676         checkMoveCodePointOffset("", 0, 0, 0);
677         checkMoveCodePointOffset("", 0, -1, -1);
678         checkMoveCodePointOffset("", 0, 1, -1);
679
680         checkMoveCodePointOffset("a", 0, 0, 0);
681         checkMoveCodePointOffset("a", 1, 0, 1);
682         checkMoveCodePointOffset("a", 0, 1, 1);
683         checkMoveCodePointOffset("a", 1, -1, 0);
684
685
686         // Supplementary in middle of string
687         checkMoveCodePointOffset("a\ud800\udc00b", 0, 1, 1);
688         checkMoveCodePointOffset("a\ud800\udc00b", 0, 2, 3);
689         checkMoveCodePointOffset("a\ud800\udc00b", 0, 3, 4);
690         checkMoveCodePointOffset("a\ud800\udc00b", 0, 4, -1);
691
692         checkMoveCodePointOffset("a\ud800\udc00b", 4, -1, 3);
693         checkMoveCodePointOffset("a\ud800\udc00b", 4, -2, 1);
694         checkMoveCodePointOffset("a\ud800\udc00b", 4, -3, 0);
695         checkMoveCodePointOffset("a\ud800\udc00b", 4, -4, -1);
696
697         // Supplementary at start of string
698         checkMoveCodePointOffset("\ud800\udc00ab", 0, 1, 2);
699         checkMoveCodePointOffset("\ud800\udc00ab", 1, 1, 2);
700         checkMoveCodePointOffset("\ud800\udc00ab", 2, 1, 3);
701         checkMoveCodePointOffset("\ud800\udc00ab", 2, -1, 0);
702         checkMoveCodePointOffset("\ud800\udc00ab", 1, -1, 0);
703         checkMoveCodePointOffset("\ud800\udc00ab", 0, -1, -1);
704
705
706         // Supplementary at end of string
707         checkMoveCodePointOffset("ab\ud800\udc00", 1, 1, 2);
708         checkMoveCodePointOffset("ab\ud800\udc00", 2, 1, 4);
709         checkMoveCodePointOffset("ab\ud800\udc00", 3, 1, 4);
710         checkMoveCodePointOffset("ab\ud800\udc00", 4, 1, -1);
711
712         checkMoveCodePointOffset("ab\ud800\udc00", 5, -2, -1);
713         checkMoveCodePointOffset("ab\ud800\udc00", 4, -1, 2);
714         checkMoveCodePointOffset("ab\ud800\udc00", 3, -1, 2);
715         checkMoveCodePointOffset("ab\ud800\udc00", 2, -1, 1);
716         checkMoveCodePointOffset("ab\ud800\udc00", 1, -1, 0);
717
718         // Unpaired surrogate in middle
719         checkMoveCodePointOffset("a\ud800b", 0, 1, 1);
720         checkMoveCodePointOffset("a\ud800b", 1, 1, 2);
721         checkMoveCodePointOffset("a\ud800b", 2, 1, 3);
722
723         checkMoveCodePointOffset("a\udc00b", 0, 1, 1);
724         checkMoveCodePointOffset("a\udc00b", 1, 1, 2);
725         checkMoveCodePointOffset("a\udc00b", 2, 1, 3);
726
727         checkMoveCodePointOffset("a\udc00\ud800b", 0, 1, 1);
728         checkMoveCodePointOffset("a\udc00\ud800b", 1, 1, 2);
729         checkMoveCodePointOffset("a\udc00\ud800b", 2, 1, 3);
730         checkMoveCodePointOffset("a\udc00\ud800b", 3, 1, 4);
731
732         checkMoveCodePointOffset("a\ud800b", 1, -1, 0);
733         checkMoveCodePointOffset("a\ud800b", 2, -1, 1);
734         checkMoveCodePointOffset("a\ud800b", 3, -1, 2);
735
736         checkMoveCodePointOffset("a\udc00b", 1, -1, 0);
737         checkMoveCodePointOffset("a\udc00b", 2, -1, 1);
738         checkMoveCodePointOffset("a\udc00b", 3, -1, 2);
739
740         checkMoveCodePointOffset("a\udc00\ud800b", 1, -1, 0);
741         checkMoveCodePointOffset("a\udc00\ud800b", 2, -1, 1);
742         checkMoveCodePointOffset("a\udc00\ud800b", 3, -1, 2);
743         checkMoveCodePointOffset("a\udc00\ud800b", 4, -1, 3);
744
745         // Unpaired surrogate at start
746         checkMoveCodePointOffset("\udc00ab", 0, 1, 1);
747         checkMoveCodePointOffset("\ud800ab", 0, 2, 2);
748         checkMoveCodePointOffset("\ud800\ud800ab", 0, 3, 3);
749         checkMoveCodePointOffset("\udc00\udc00ab", 0, 4, 4);
750
751         checkMoveCodePointOffset("\udc00ab", 2, -1, 1);
752         checkMoveCodePointOffset("\ud800ab", 1, -1, 0);
753         checkMoveCodePointOffset("\ud800ab", 1, -2, -1);
754         checkMoveCodePointOffset("\ud800\ud800ab", 2, -1, 1);
755         checkMoveCodePointOffset("\udc00\udc00ab", 2, -2, 0);
756         checkMoveCodePointOffset("\udc00\udc00ab", 2, -3, -1);
757
758         // Unpaired surrogate at end
759         checkMoveCodePointOffset("ab\udc00\udc00ab", 3, 1, 4);
760         checkMoveCodePointOffset("ab\udc00\udc00ab", 2, 1, 3);
761         checkMoveCodePointOffset("ab\udc00\udc00ab", 1, 1, 2);
762
763         checkMoveCodePointOffset("ab\udc00\udc00ab", 4, -1, 3);
764         checkMoveCodePointOffset("ab\udc00\udc00ab", 3, -1, 2);
765         checkMoveCodePointOffset("ab\udc00\udc00ab", 2, -1, 1);
766
767
768                                //01234567890     1     2     3     45678901234
769         String str = new String("0123456789\ud800\udc00\ud801\udc010123456789");
770         int move1[] = { 1,  2,  3,  4,  5,  6,  7,  8,  9, 10,
771                        12, 12, 14, 14, 15, 16, 17, 18, 19, 20,
772                        21, 22, 23, 24};
773         int move2[] = { 2,  3,  4,  5,  6,  7,  8,  9, 10, 12,
774                        14, 14, 15, 15, 16, 17, 18, 19, 20, 21,
775                        22, 23, 24, -1};
776         int move3[] = { 3,  4,  5,  6,  7,  8,  9, 10, 12, 14,
777                        15, 15, 16, 16, 17, 18, 19, 20, 21, 22,
778                        23, 24, -1, -1};
779         int size = str.length();
780         for (int i = 0; i < size; i ++) {
781             checkMoveCodePointOffset(str, i, 1, move1[i]);
782             checkMoveCodePointOffset(str, i, 2, move2[i]);
783             checkMoveCodePointOffset(str, i, 3, move3[i]);
784         }
785
786         char strarray[] = str.toCharArray();
787         if (UTF16.moveCodePointOffset(strarray, 9, 13, 0, 2) != 3) {
788             errln("FAIL: Moving offset 0 by 2 codepoint in subarray [9, 13] " +
789             "expected result 3");
790         }
791         if (UTF16.moveCodePointOffset(strarray, 9, 13, 1, 2) != 4) {
792             errln("FAIL: Moving offset 1 by 2 codepoint in subarray [9, 13] " +
793             "expected result 4");
794         }
795         if (UTF16.moveCodePointOffset(strarray, 11, 14, 0, 2) != 3) {
796             errln("FAIL: Moving offset 0 by 2 codepoint in subarray [11, 14] "
797                     + "expected result 3");
798         }
799     }
800
801     /**
802      * Testing UTF16 class methods setCharAt
803      */
804     public void TestSetCharAt()
805     {
806         StringBuffer strbuff = new StringBuffer("012345");
807         char array[] = new char[128];
808         int srcEnd = strbuff.length();
809         if (0 != srcEnd) {
810             strbuff.getChars(0, srcEnd, array, 0);
811         }
812         int length = 6;
813         for (int i = 0; i < length; i ++) {
814         UTF16.setCharAt(strbuff, i, '0');
815         UTF16.setCharAt(array, length, i, '0');
816         }
817         String str = new String(array, 0, length);
818         if (!(strbuff.toString().equals("000000")) ||
819         !(str.equals("000000"))) {
820         errln("FAIL: setChar to '0' failed");
821         }
822         UTF16.setCharAt(strbuff, 0, 0x10000);
823         UTF16.setCharAt(strbuff, 4, 0x10000);
824         UTF16.setCharAt(strbuff, 7, 0x10000);
825         if (!(strbuff.toString().equals(
826                     "\ud800\udc0000\ud800\udc000\ud800\udc00"))) {
827         errln("FAIL: setChar to 0x10000 failed");
828         }
829         length = UTF16.setCharAt(array, length, 0, 0x10000);
830         length = UTF16.setCharAt(array, length, 4, 0x10000);
831         length = UTF16.setCharAt(array, length, 7, 0x10000);
832         str = new String(array, 0, length);
833         if (!(str.equals("\ud800\udc0000\ud800\udc000\ud800\udc00"))) {
834         errln("FAIL: setChar to 0x10000 failed");
835         }
836         UTF16.setCharAt(strbuff, 0, '0');
837         UTF16.setCharAt(strbuff, 1, '1');
838         UTF16.setCharAt(strbuff, 2, '2');
839         UTF16.setCharAt(strbuff, 4, '3');
840         UTF16.setCharAt(strbuff, 4, '4');
841         UTF16.setCharAt(strbuff, 5, '5');
842         if (!strbuff.toString().equals("012345")) {
843         errln("Fail converting supplementaries in StringBuffer to BMP " +
844           "characters");
845         }
846         length = UTF16.setCharAt(array, length, 0, '0');
847         length = UTF16.setCharAt(array, length, 1, '1');
848         length = UTF16.setCharAt(array, length, 2, '2');
849         length = UTF16.setCharAt(array, length, 4, '3');
850         length = UTF16.setCharAt(array, length, 4, '4');
851         length = UTF16.setCharAt(array, length, 5, '5');
852         str = new String(array, 0, length);
853         if (!str.equals("012345")) {
854         errln("Fail converting supplementaries in array to BMP " +
855           "characters");
856         }
857         try {
858         UTF16.setCharAt(strbuff, -1, 0);
859         errln("FAIL: setting character at invalid offset");
860         } catch (Exception e) {
861         System.out.print("");
862         }
863         try {
864         UTF16.setCharAt(array, length, -1, 0);
865         errln("FAIL: setting character at invalid offset");
866         } catch (Exception e) {
867         System.out.print("");
868         }
869         try {
870         UTF16.setCharAt(strbuff, length, 0);
871         errln("FAIL: setting character at invalid offset");
872         } catch (Exception e) {
873         System.out.print("");
874         }
875         try {
876         UTF16.setCharAt(array, length, length, 0);
877         errln("FAIL: setting character at invalid offset");
878         } catch (Exception e) {
879         System.out.print("");
880         }
881     }
882
883     /**
884      * Testing UTF16 valueof APIs
885      */
886     public void TestValueOf()
887     {
888         if(UCharacter.getCodePoint('\ud800','\udc00')!=0x10000){
889             errln("FAIL: getCodePoint('\ud800','\udc00')");
890         }
891         if (!UTF16.valueOf(0x61).equals("a") ||
892         !UTF16.valueOf(0x10000).equals("\ud800\udc00")) {
893         errln("FAIL: valueof(char32)");
894         }
895         String str = new String("01234\ud800\udc0056789");
896         StringBuffer strbuff = new StringBuffer(str);
897         char array[] = str.toCharArray();
898         int length = str.length();
899
900         String expected[] = {"0", "1", "2", "3", "4", "\ud800\udc00",
901                  "\ud800\udc00", "5", "6", "7", "8", "9"};
902         for (int i = 0; i < length; i ++) {
903         if (!UTF16.valueOf(str, i).equals(expected[i]) ||
904                 !UTF16.valueOf(strbuff, i).equals(expected[i]) ||
905                 !UTF16.valueOf(array, 0, length, i).equals(expected[i])) {
906                 errln("FAIL: valueOf() expected " + expected[i]);
907         }
908         }
909         try {
910         UTF16.valueOf(str, -1);
911         errln("FAIL: out of bounds error expected");
912         } catch (Exception e) {
913         System.out.print("");
914         }
915         try {
916         UTF16.valueOf(strbuff, -1);
917         errln("FAIL: out of bounds error expected");
918         } catch (Exception e) {
919         System.out.print("");
920         }
921         try {
922         UTF16.valueOf(array, 0, length, -1);
923         errln("FAIL: out of bounds error expected");
924         } catch (Exception e) {
925         System.out.print("");
926         }
927         try {
928         UTF16.valueOf(str, length);
929         errln("FAIL: out of bounds error expected");
930         } catch (Exception e) {
931         System.out.print("");
932         }
933         try {
934         UTF16.valueOf(strbuff, length);
935         errln("FAIL: out of bounds error expected");
936         } catch (Exception e) {
937         System.out.print("");
938         }
939         try {
940         UTF16.valueOf(array, 0, length, length);
941         errln("FAIL: out of bounds error expected");
942         } catch (Exception e) {
943         System.out.print("");
944         }
945         if (!UTF16.valueOf(array, 6, length, 0).equals("\udc00") ||
946         !UTF16.valueOf(array, 0, 6, 5).equals("\ud800")) {
947         errln("FAIL: error getting partial supplementary character");
948         }
949         try {
950         UTF16.valueOf(array, 3, 5, -1);
951         errln("FAIL: out of bounds error expected");
952         } catch (Exception e) {
953         System.out.print("");
954         }
955         try {
956         UTF16.valueOf(array, 3, 5, 3);
957         errln("FAIL: out of bounds error expected");
958         } catch (Exception e) {
959         System.out.print("");
960         }
961     }
962
963     public void TestIndexOf()
964     {
965     //012345678901234567890123456789012345
966         String test1     = "test test ttest tetest testesteststt";
967         String test2     = "test";
968         int    testChar1 = 0x74;
969         int    testChar2 = 0x20402;
970         // int    testChar3 = 0xdc02;
971         // int    testChar4 = 0xd841;
972         String test3     = "\ud841\udc02\u0071\udc02\ud841\u0071\ud841\udc02\u0071\u0072\ud841\udc02\u0071\ud841\udc02\u0071\udc02\ud841\u0073";
973         String test4     = UCharacter.toString(testChar2);
974
975         if (UTF16.indexOf(test1, test2) != 0 ||
976             UTF16.indexOf(test1, test2, 0) != 0) {
977             errln("indexOf failed: expected to find '" + test2 +
978                   "' at position 0 in text '" + test1 + "'");
979         }
980         if (UTF16.indexOf(test1, testChar1) != 0 ||
981             UTF16.indexOf(test1, testChar1, 0) != 0) {
982             errln("indexOf failed: expected to find 0x" +
983                   Integer.toHexString(testChar1) +
984                   " at position 0 in text '" + test1 + "'");
985         }
986         if (UTF16.indexOf(test3, testChar2) != 0 ||
987             UTF16.indexOf(test3, testChar2, 0) != 0) {
988             errln("indexOf failed: expected to find 0x" +
989                   Integer.toHexString(testChar2) +
990                   " at position 0 in text '" + Utility.hex(test3) + "'");
991         }
992         String test5 = "\ud841\ud841\udc02";
993         if (UTF16.indexOf(test5, testChar2) != 1 ||
994             UTF16.indexOf(test5, testChar2, 0) != 1) {
995             errln("indexOf failed: expected to find 0x" +
996                   Integer.toHexString(testChar2) +
997                   " at position 0 in text '" + Utility.hex(test3) + "'");
998         }
999         if (UTF16.lastIndexOf(test1, test2) != 29 ||
1000             UTF16.lastIndexOf(test1, test2, test1.length()) != 29) {
1001             errln("lastIndexOf failed: expected to find '" + test2 +
1002                   "' at position 29 in text '" + test1 + "'");
1003         }
1004         if (UTF16.lastIndexOf(test1, testChar1) != 35 ||
1005             UTF16.lastIndexOf(test1, testChar1, test1.length()) != 35) {
1006             errln("lastIndexOf failed: expected to find 0x" +
1007                   Integer.toHexString(testChar1) +
1008                   " at position 35 in text '" + test1 + "'");
1009         }
1010         if (UTF16.lastIndexOf(test3, testChar2) != 13 ||
1011             UTF16.lastIndexOf(test3, testChar2, test3.length()) != 13) {
1012             errln("indexOf failed: expected to find 0x" +
1013                   Integer.toHexString(testChar2) +
1014                   " at position 13 in text '" + Utility.hex(test3) + "'");
1015         }
1016         int occurrences = 0;
1017         for (int startPos = 0; startPos != -1 && startPos < test1.length();)
1018         {
1019         startPos = UTF16.indexOf(test1, test2, startPos);
1020         if (startPos >= 0) {
1021             ++ occurrences;
1022             startPos += 4;
1023         }
1024         }
1025         if (occurrences != 6) {
1026             errln("indexOf failed: expected to find 6 occurrences, found "
1027                   + occurrences);
1028         }
1029
1030         occurrences = 0;
1031         for (int startPos = 10; startPos != -1 && startPos < test1.length();)
1032         {
1033         startPos = UTF16.indexOf(test1, test2, startPos);
1034         if (startPos >= 0) {
1035             ++ occurrences;
1036             startPos += 4;
1037         }
1038         }
1039         if (occurrences != 4) {
1040             errln("indexOf with starting offset failed: expected to find 4 occurrences, found "
1041                   + occurrences);
1042         }
1043
1044         occurrences = 0;
1045         for (int startPos = 0;
1046          startPos != -1 && startPos < test3.length();) {
1047             startPos = UTF16.indexOf(test3, test4, startPos);
1048             if (startPos != -1) {
1049                 ++ occurrences;
1050                 startPos += 2;
1051             }
1052         }
1053         if (occurrences != 4) {
1054             errln("indexOf failed: expected to find 4 occurrences, found "
1055           + occurrences);
1056         }
1057
1058         occurrences = 0;
1059         for (int startPos = 10;
1060              startPos != -1 && startPos < test3.length();) {
1061             startPos = UTF16.indexOf(test3, test4, startPos);
1062             if (startPos != -1) {
1063                 ++ occurrences;
1064                 startPos += 2;
1065             }
1066         }
1067         if (occurrences != 2) {
1068             errln("indexOf failed: expected to find 2 occurrences, found "
1069                   + occurrences);
1070         }
1071
1072         occurrences = 0;
1073         for (int startPos = 0;
1074          startPos != -1 && startPos < test1.length();) {
1075             startPos = UTF16.indexOf(test1, testChar1, startPos);
1076             if (startPos != -1) {
1077                 ++ occurrences;
1078                 startPos += 1;
1079             }
1080         }
1081         if (occurrences != 16) {
1082             errln("indexOf with character failed: expected to find 16 occurrences, found "
1083                   + occurrences);
1084         }
1085
1086         occurrences = 0;
1087         for (int startPos = 10;
1088          startPos != -1 && startPos < test1.length();) {
1089             startPos = UTF16.indexOf(test1, testChar1, startPos);
1090             if (startPos != -1) {
1091                 ++ occurrences;
1092                 startPos += 1;
1093             }
1094         }
1095         if (occurrences != 12) {
1096             errln("indexOf with character & start offset failed: expected to find 12 occurrences, found "
1097           + occurrences);
1098         }
1099
1100         occurrences = 0;
1101         for (int startPos = 0;
1102          startPos != -1 && startPos < test3.length();) {
1103             startPos = UTF16.indexOf(test3, testChar2, startPos);
1104             if (startPos != -1) {
1105                 ++ occurrences;
1106                 startPos += 1;
1107             }
1108         }
1109         if (occurrences != 4) {
1110             errln("indexOf failed: expected to find 4 occurrences, found "
1111                   + occurrences);
1112         }
1113
1114         occurrences = 0;
1115         for (int startPos = 5; startPos != -1 && startPos < test3.length();) {
1116             startPos = UTF16.indexOf(test3, testChar2, startPos);
1117             if (startPos != -1) {
1118                 ++ occurrences;
1119                 startPos += 1;
1120             }
1121         }
1122         if (occurrences != 3) {
1123             errln("indexOf with character & start & end offsets failed: expected to find 2 occurrences, found "
1124           + occurrences);
1125         }
1126         occurrences = 0;
1127         for (int startPos = 32; startPos != -1;) {
1128             startPos = UTF16.lastIndexOf(test1, test2, startPos);
1129             if (startPos != -1) {
1130                 ++ occurrences;
1131                 startPos -= 5;
1132             }
1133         }
1134         if (occurrences != 6) {
1135             errln("lastIndexOf with starting and ending offsets failed: expected to find 4 occurrences, found "
1136                   + occurrences);
1137         }
1138         occurrences = 0;
1139         for (int startPos = 32; startPos != -1;) {
1140             startPos = UTF16.lastIndexOf(test1, testChar1, startPos);
1141             if (startPos != -1) {
1142                 ++ occurrences;
1143                 startPos -= 5;
1144             }
1145         }
1146         if (occurrences != 7) {
1147             errln("lastIndexOf with character & start & end offsets failed: expected to find 11 occurrences, found "
1148           + occurrences);
1149         }
1150
1151         //testing UChar32
1152         occurrences = 0;
1153         for (int startPos = test3.length(); startPos != -1;) {
1154             startPos = UTF16.lastIndexOf(test3, testChar2, startPos - 5);
1155             if (startPos != -1) {
1156                 ++ occurrences;
1157             }
1158         }
1159         if (occurrences != 3) {
1160             errln("lastIndexOf with character & start & end offsets failed: expected to find 3 occurrences, found "
1161           + occurrences);
1162         }
1163
1164         // testing supplementary
1165         for (int i = 0; i < INDEXOF_SUPPLEMENTARY_CHAR_.length; i ++) {
1166         int ch = INDEXOF_SUPPLEMENTARY_CHAR_[i];
1167         for (int j = 0; j < INDEXOF_SUPPLEMENTARY_CHAR_INDEX_[i].length;
1168          j ++) {
1169         int index = 0;
1170         int expected = INDEXOF_SUPPLEMENTARY_CHAR_INDEX_[i][j];
1171         if  (j > 0) {
1172             index = INDEXOF_SUPPLEMENTARY_CHAR_INDEX_[i][j - 1] + 1;
1173         }
1174         if (UTF16.indexOf(INDEXOF_SUPPLEMENTARY_STRING_, ch, index) !=
1175             expected ||
1176             UTF16.indexOf(INDEXOF_SUPPLEMENTARY_STRING_,
1177                   UCharacter.toString(ch), index) !=
1178             expected) {
1179             errln("Failed finding index for supplementary 0x" +
1180               Integer.toHexString(ch));
1181         }
1182         index = INDEXOF_SUPPLEMENTARY_STRING_.length();
1183         if (j < INDEXOF_SUPPLEMENTARY_CHAR_INDEX_[i].length - 1) {
1184             index = INDEXOF_SUPPLEMENTARY_CHAR_INDEX_[i][j + 1] - 1;
1185         }
1186         if (UTF16.lastIndexOf(INDEXOF_SUPPLEMENTARY_STRING_, ch,
1187                       index) != expected ||
1188             UTF16.lastIndexOf(INDEXOF_SUPPLEMENTARY_STRING_,
1189                       UCharacter.toString(ch), index)
1190             != expected)
1191             {
1192             errln("Failed finding last index for supplementary 0x" +
1193                   Integer.toHexString(ch));
1194             }
1195         }
1196         }
1197
1198         for (int i = 0; i < INDEXOF_SUPPLEMENTARY_STR_INDEX_.length; i ++) {
1199         int index = 0;
1200         int expected = INDEXOF_SUPPLEMENTARY_STR_INDEX_[i];
1201         if  (i > 0) {
1202         index = INDEXOF_SUPPLEMENTARY_STR_INDEX_[i - 1] + 1;
1203         }
1204         if (UTF16.indexOf(INDEXOF_SUPPLEMENTARY_STRING_,
1205                   INDEXOF_SUPPLEMENTARY_STR_, index) != expected) {
1206         errln("Failed finding index for supplementary string " +
1207               hex(INDEXOF_SUPPLEMENTARY_STRING_));
1208         }
1209         index = INDEXOF_SUPPLEMENTARY_STRING_.length();
1210         if (i < INDEXOF_SUPPLEMENTARY_STR_INDEX_.length - 1) {
1211         index = INDEXOF_SUPPLEMENTARY_STR_INDEX_[i + 1] - 1;
1212         }
1213         if (UTF16.lastIndexOf(INDEXOF_SUPPLEMENTARY_STRING_,
1214                               INDEXOF_SUPPLEMENTARY_STR_, index) != expected) {
1215         errln("Failed finding last index for supplementary string " +
1216               hex(INDEXOF_SUPPLEMENTARY_STRING_));
1217         }
1218         }
1219     }
1220
1221     public void TestReplace()
1222     {
1223         String test1 = "One potato, two potato, three potato, four\n";
1224         String test2 = "potato";
1225         String test3 = "MISSISSIPPI";
1226
1227         String result = UTF16.replace(test1, test2, test3);
1228         String expectedValue =
1229             "One MISSISSIPPI, two MISSISSIPPI, three MISSISSIPPI, four\n";
1230         if (!result.equals(expectedValue)) {
1231             errln("findAndReplace failed: expected \"" + expectedValue +
1232                   "\", got \"" + test1 + "\".");
1233         }
1234         result = UTF16.replace(test1, test3, test2);
1235         expectedValue = test1;
1236         if (!result.equals(expectedValue)) {
1237             errln("findAndReplace failed: expected \"" + expectedValue +
1238                   "\", got \"" + test1 + "\".");
1239         }
1240
1241         result = UTF16.replace(test1, ',', 'e');
1242         expectedValue = "One potatoe two potatoe three potatoe four\n";
1243         if (!result.equals(expectedValue)) {
1244             errln("findAndReplace failed: expected \"" + expectedValue +
1245                   "\", got \"" + test1 + "\".");
1246         }
1247
1248         result = UTF16.replace(test1, ',', 0x10000);
1249         expectedValue = "One potato\ud800\udc00 two potato\ud800\udc00 three potato\ud800\udc00 four\n";
1250         if (!result.equals(expectedValue)) {
1251             errln("findAndReplace failed: expected \"" + expectedValue +
1252                   "\", got \"" + test1 + "\".");
1253         }
1254
1255         result = UTF16.replace(test1, "potato", "\ud800\udc00\ud801\udc01");
1256         expectedValue = "One \ud800\udc00\ud801\udc01, two \ud800\udc00\ud801\udc01, three \ud800\udc00\ud801\udc01, four\n";
1257         if (!result.equals(expectedValue)) {
1258             errln("findAndReplace failed: expected \"" + expectedValue +
1259                   "\", got \"" + test1 + "\".");
1260         }
1261
1262         String test4 = "\ud800\ud800\udc00\ud800\udc00\udc00\ud800\ud800\udc00\ud800\udc00\udc00";
1263         result = UTF16.replace(test4, 0xd800, 'A');
1264         expectedValue = "A\ud800\udc00\ud800\udc00\udc00A\ud800\udc00\ud800\udc00\udc00";
1265         if (!result.equals(expectedValue)) {
1266             errln("findAndReplace failed: expected \"" + expectedValue +
1267                   "\", got \"" + test1 + "\".");
1268         }
1269
1270         result = UTF16.replace(test4, 0xdC00, 'A');
1271         expectedValue = "\ud800\ud800\udc00\ud800\udc00A\ud800\ud800\udc00\ud800\udc00A";
1272         if (!result.equals(expectedValue)) {
1273             errln("findAndReplace failed: expected \"" + expectedValue +
1274                   "\", got \"" + test1 + "\".");
1275         }
1276
1277         result = UTF16.replace(test4, 0x10000, 'A');
1278         expectedValue = "\ud800AA\udc00\ud800AA\udc00";
1279         if (!result.equals(expectedValue)) {
1280             errln("findAndReplace failed: expected \"" + expectedValue +
1281                   "\", got \"" + test1 + "\".");
1282         }
1283     }
1284
1285     public void TestReverse()
1286     {
1287         StringBuffer test = new StringBuffer(
1288                          "backwards words say to used I");
1289
1290         StringBuffer result = UTF16.reverse(test);
1291         if (!result.toString().equals("I desu ot yas sdrow sdrawkcab")) {
1292             errln("reverse() failed:  Expected \"I desu ot yas sdrow sdrawkcab\",\n got \""
1293           + result + "\"");
1294         }
1295         StringBuffer testbuffer = new StringBuffer();
1296         UTF16.append(testbuffer, 0x2f999);
1297         UTF16.append(testbuffer, 0x1d15f);
1298         UTF16.append(testbuffer, 0x00c4);
1299         UTF16.append(testbuffer, 0x1ed0);
1300         result = UTF16.reverse(testbuffer);
1301         if (result.charAt(0) != 0x1ed0 ||
1302             result.charAt(1) != 0xc4 ||
1303             UTF16.charAt(result, 2) != 0x1d15f ||
1304             UTF16.charAt(result, 4)!=0x2f999) {
1305             errln("reverse() failed with supplementary characters");
1306         }
1307     }
1308
1309     /**
1310      * Testing the setter and getter apis for StringComparator
1311      */
1312     public void TestStringComparator()
1313     {
1314         UTF16.StringComparator compare = new UTF16.StringComparator();
1315         if (compare.getCodePointCompare() != false) {
1316             errln("Default string comparator should be code unit compare");
1317         }
1318         if (compare.getIgnoreCase() != false) {
1319             errln("Default string comparator should be case sensitive compare");
1320         }
1321         if (compare.getIgnoreCaseOption()
1322             != UTF16.StringComparator.FOLD_CASE_DEFAULT) {
1323             errln("Default string comparator should have fold case default compare");
1324         }
1325         compare.setCodePointCompare(true);
1326         if (compare.getCodePointCompare() != true) {
1327             errln("Error setting code point compare");
1328         }
1329         compare.setCodePointCompare(false);
1330         if (compare.getCodePointCompare() != false) {
1331             errln("Error setting code point compare");
1332         }
1333         compare.setIgnoreCase(true, UTF16.StringComparator.FOLD_CASE_DEFAULT);
1334         if (compare.getIgnoreCase() != true
1335             || compare.getIgnoreCaseOption()
1336         != UTF16.StringComparator.FOLD_CASE_DEFAULT) {
1337             errln("Error setting ignore case and options");
1338         }
1339         compare.setIgnoreCase(false, UTF16.StringComparator.FOLD_CASE_EXCLUDE_SPECIAL_I);
1340         if (compare.getIgnoreCase() != false
1341             || compare.getIgnoreCaseOption()
1342         != UTF16.StringComparator.FOLD_CASE_EXCLUDE_SPECIAL_I) {
1343             errln("Error setting ignore case and options");
1344         }
1345         compare.setIgnoreCase(true, UTF16.StringComparator.FOLD_CASE_EXCLUDE_SPECIAL_I);
1346         if (compare.getIgnoreCase() != true
1347             || compare.getIgnoreCaseOption()
1348         != UTF16.StringComparator.FOLD_CASE_EXCLUDE_SPECIAL_I) {
1349             errln("Error setting ignore case and options");
1350         }
1351         compare.setIgnoreCase(false, UTF16.StringComparator.FOLD_CASE_DEFAULT);
1352         if (compare.getIgnoreCase() != false
1353             || compare.getIgnoreCaseOption()
1354         != UTF16.StringComparator.FOLD_CASE_DEFAULT) {
1355             errln("Error setting ignore case and options");
1356         }
1357     }
1358
1359     public void TestCodePointCompare()
1360     {
1361         // these strings are in ascending order
1362         String str[] = {"\u0061", "\u20ac\ud801", "\u20ac\ud800\udc00",
1363                         "\ud800", "\ud800\uff61", "\udfff",
1364                         "\uff61\udfff", "\uff61\ud800\udc02", "\ud800\udc02",
1365                         "\ud84d\udc56"};
1366         UTF16.StringComparator cpcompare
1367             = new UTF16.StringComparator(true, false,
1368                      UTF16.StringComparator.FOLD_CASE_DEFAULT);
1369         UTF16.StringComparator cucompare
1370             = new UTF16.StringComparator();
1371         for (int i = 0; i < str.length - 1; ++ i) {
1372             if (cpcompare.compare(str[i], str[i + 1]) >= 0) {
1373                 errln("error: compare() in code point order fails for string "
1374                       + Utility.hex(str[i]) + " and "
1375                       + Utility.hex(str[i + 1]));
1376             }
1377             // test code unit compare
1378             if (cucompare.compare(str[i], str[i + 1])
1379                 != str[i].compareTo(str[i + 1])) {
1380                 errln("error: compare() in code unit order fails for string "
1381                       + Utility.hex(str[i]) + " and "
1382                       + Utility.hex(str[i + 1]));
1383             }
1384         }
1385     }
1386
1387     public void TestCaseCompare()
1388     {
1389         String mixed = "\u0061\u0042\u0131\u03a3\u00df\ufb03\ud93f\udfff";
1390         String otherDefault = "\u0041\u0062\u0131\u03c3\u0073\u0053\u0046\u0066\u0049\ud93f\udfff";
1391         String otherExcludeSpecialI = "\u0041\u0062\u0131\u03c3\u0053\u0073\u0066\u0046\u0069\ud93f\udfff";
1392         String different = "\u0041\u0062\u0131\u03c3\u0073\u0053\u0046\u0066\u0049\ud93f\udffd";
1393
1394         UTF16.StringComparator compare = new UTF16.StringComparator();
1395         compare.setIgnoreCase(true, UTF16.StringComparator.FOLD_CASE_DEFAULT);
1396         // test u_strcasecmp()
1397         int result = compare.compare(mixed, otherDefault);
1398         if (result != 0) {
1399             errln("error: default compare(mixed, other) = " + result
1400                   + " instead of 0");
1401         }
1402
1403         // test u_strcasecmp() - exclude special i
1404         compare.setIgnoreCase(true,
1405                   UTF16.StringComparator.FOLD_CASE_EXCLUDE_SPECIAL_I);
1406         result = compare.compare(mixed, otherExcludeSpecialI);
1407         if (result != 0) {
1408             errln("error: exclude_i compare(mixed, other) = " + result
1409                   + " instead of 0");
1410         }
1411
1412         // test u_strcasecmp()
1413         compare.setIgnoreCase(true,
1414                               UTF16.StringComparator.FOLD_CASE_DEFAULT);
1415         result = compare.compare(mixed, different);
1416         if (result <= 0) {
1417             errln("error: default compare(mixed, different) = " + result
1418                   + " instead of positive");
1419         }
1420
1421         // test substrings - stop before the sharp s (U+00df)
1422         compare.setIgnoreCase(true,
1423                               UTF16.StringComparator.FOLD_CASE_DEFAULT);
1424         result = compare.compare(mixed.substring(0, 4),
1425                                  different.substring(0, 4));
1426         if (result != 0) {
1427             errln("error: default compare(mixed substring, different substring) = "
1428           + result + " instead of 0");
1429         }
1430         // test substrings - stop in the middle of the sharp s (U+00df)
1431         compare.setIgnoreCase(true,
1432                               UTF16.StringComparator.FOLD_CASE_DEFAULT);
1433         result = compare.compare(mixed.substring(0, 5),
1434                                  different.substring(0, 5));
1435         if (result <= 0) {
1436             errln("error: default compare(mixed substring, different substring) = "
1437           + result + " instead of positive");
1438         }
1439     }
1440
1441     public void TestHasMoreCodePointsThan()
1442     {
1443         String str = "\u0061\u0062\ud800\udc00\ud801\udc01\u0063\ud802\u0064"
1444         + "\udc03\u0065\u0066\ud804\udc04\ud805\udc05\u0067";
1445         int length = str.length();
1446         while (length >= 0) {
1447             for (int i = 0; i <= length; ++ i) {
1448                 String s = str.substring(0, i);
1449                 for (int number = -1; number <= ((length - i) + 2); ++ number) {
1450                     boolean flag = UTF16.hasMoreCodePointsThan(s, number);
1451                     if (flag != (UTF16.countCodePoint(s) > number)) {
1452                         errln("hasMoreCodePointsThan(" + Utility.hex(s)
1453                               + ", " + number + ") = " + flag + " is wrong");
1454                     }
1455                 }
1456             }
1457             -- length;
1458         }
1459
1460         // testing for null bad input
1461         for(length = -1; length <= 1; ++ length) {
1462             for (int i = 0; i <= length; ++ i) {
1463                 for (int number = -2; number <= 2; ++ number) {
1464                     boolean flag = UTF16.hasMoreCodePointsThan((String)null,
1465                                                                number);
1466                     if (flag != (UTF16.countCodePoint((String)null) > number)) {
1467                         errln("hasMoreCodePointsThan(null, " + number + ") = "
1468                   + flag + " is wrong");
1469                     }
1470                 }
1471             }
1472         }
1473
1474         length = str.length();
1475         while (length >= 0) {
1476             for (int i = 0; i <= length; ++ i) {
1477                 StringBuffer s = new StringBuffer(str.substring(0, i));
1478                 for (int number = -1; number <= ((length - i) + 2); ++ number) {
1479                     boolean flag = UTF16.hasMoreCodePointsThan(s, number);
1480                     if (flag != (UTF16.countCodePoint(s) > number)) {
1481                         errln("hasMoreCodePointsThan(" + Utility.hex(s)
1482                               + ", " + number + ") = " + flag + " is wrong");
1483                     }
1484                 }
1485             }
1486             -- length;
1487         }
1488
1489         // testing for null bad input
1490         for (length = -1; length <= 1; ++ length) {
1491             for (int i = 0; i <= length; ++ i) {
1492                 for (int number = -2; number <= 2; ++ number) {
1493                     boolean flag = UTF16.hasMoreCodePointsThan(
1494                                    (StringBuffer)null, number);
1495                     if (flag
1496                         != (UTF16.countCodePoint((StringBuffer)null) > number))
1497             {
1498                 errln("hasMoreCodePointsThan(null, " + number + ") = "
1499                   + flag + " is wrong");
1500             }
1501                 }
1502             }
1503         }
1504
1505         char strarray[] = str.toCharArray();
1506         while (length >= 0) {
1507             for (int limit = 0; limit <= length; ++ limit) {
1508                 for (int start = 0; start <= limit; ++ start) {
1509                     for (int number = -1; number <= ((limit - start) + 2);
1510                          ++ number) {
1511                         boolean flag = UTF16.hasMoreCodePointsThan(strarray,
1512                                    start, limit, number);
1513                         if (flag != (UTF16.countCodePoint(strarray, start,
1514                                                           limit) > number)) {
1515                             errln("hasMoreCodePointsThan("
1516                                   + Utility.hex(str.substring(start, limit))
1517                                   + ", " + start + ", " + limit + ", " + number
1518                                   + ") = " + flag + " is wrong");
1519                         }
1520                     }
1521                 }
1522             }
1523             -- length;
1524         }
1525
1526         // testing for null bad input
1527         for (length = -1; length <= 1; ++ length) {
1528             for (int i = 0; i <= length; ++ i) {
1529                 for (int number = -2; number <= 2; ++ number) {
1530                     boolean flag = UTF16.hasMoreCodePointsThan(
1531                                    (StringBuffer)null, number);
1532                     if (flag
1533                         != (UTF16.countCodePoint((StringBuffer)null) > number))
1534             {
1535                 errln("hasMoreCodePointsThan(null, " + number + ") = "
1536                   + flag + " is wrong");
1537             }
1538                 }
1539             }
1540         }
1541
1542         // bad input
1543         try {
1544             UTF16.hasMoreCodePointsThan(strarray, -2, -1, 5);
1545             errln("hasMoreCodePointsThan(chararray) with negative indexes has to throw an exception");
1546         } catch (Exception e) {
1547             logln("PASS: UTF16.hasMoreCodePointsThan failed as expected");
1548         }
1549         try {
1550             UTF16.hasMoreCodePointsThan(strarray, 5, 2, 5);
1551             errln("hasMoreCodePointsThan(chararray) with limit less than start index has to throw an exception");
1552         } catch (Exception e) {
1553             logln("PASS: UTF16.hasMoreCodePointsThan failed as expected");
1554         }
1555         try {
1556             if (UTF16.hasMoreCodePointsThan(strarray, -2, 2, 5)) {
1557                 errln("hasMoreCodePointsThan(chararray) with negative start indexes can't return true");
1558             }
1559         } catch (Exception e) {
1560         }
1561     }
1562
1563     public void TestNewString() {
1564     final int[] codePoints = {
1565         UCharacter.toCodePoint(UCharacter.MIN_HIGH_SURROGATE, UCharacter.MAX_LOW_SURROGATE),
1566         UCharacter.toCodePoint(UCharacter.MAX_HIGH_SURROGATE, UCharacter.MIN_LOW_SURROGATE),
1567         UCharacter.MAX_HIGH_SURROGATE,
1568         'A',
1569         -1,
1570     };
1571
1572     final String cpString = "" +
1573         UCharacter.MIN_HIGH_SURROGATE +
1574         UCharacter.MAX_LOW_SURROGATE +
1575         UCharacter.MAX_HIGH_SURROGATE +
1576         UCharacter.MIN_LOW_SURROGATE +
1577         UCharacter.MAX_HIGH_SURROGATE +
1578         'A';
1579
1580     final int[][] tests = {
1581         { 0, 1, 0, 2 },
1582         { 0, 2, 0, 4 },
1583         { 1, 1, 2, 2 },
1584         { 1, 2, 2, 3 },
1585         { 1, 3, 2, 4 },
1586         { 2, 2, 4, 2 },
1587         { 2, 3, 0, -1 },
1588         { 4, 5, 0, -1 },
1589         { 3, -1, 0, -1 }
1590     };
1591
1592      for (int i = 0; i < tests.length; ++i) {
1593         int[] t = tests[i];
1594         int s = t[0];
1595         int c = t[1];
1596         int rs = t[2];
1597         int rc = t[3];
1598
1599         Exception e = null;
1600         try {
1601         String str = UTF16.newString(codePoints, s, c);
1602         if (rc == -1 || !str.equals(cpString.substring(rs, rs+rc))) {
1603             errln("failed codePoints iter: " + i + " start: " + s + " len: " + c);
1604         }
1605         continue;
1606         }
1607         catch (IndexOutOfBoundsException e1) {
1608         e = e1;
1609         }
1610         catch (IllegalArgumentException e2) {
1611         e = e2;
1612         }
1613         if (rc != -1) {
1614         errln(e.getMessage());
1615         }
1616     }
1617     }
1618
1619     public static void main(String[] arg)
1620     {
1621         try
1622         {
1623         UTF16Test test = new UTF16Test();
1624         test.run(arg);
1625         // test.TestCaseCompare();
1626         }
1627         catch (Exception e)
1628         {
1629         e.printStackTrace();
1630         }
1631     }
1632
1633
1634     // private data members ----------------------------------------------
1635
1636     private final static String INDEXOF_SUPPLEMENTARY_STRING_ =
1637         "\ud841\udc02\u0071\udc02\ud841\u0071\ud841\udc02\u0071\u0072" +
1638         "\ud841\udc02\u0071\ud841\udc02\u0071\udc02\ud841\u0073";
1639     private final static int INDEXOF_SUPPLEMENTARY_CHAR_[] =
1640     {0x71, 0xd841, 0xdc02,
1641      UTF16Util.getRawSupplementary((char)0xd841,
1642                  (char)0xdc02)};
1643     private final static int INDEXOF_SUPPLEMENTARY_CHAR_INDEX_[][] =
1644     {{2, 5, 8, 12, 15},
1645      {4, 17},
1646      {3, 16},
1647      {0, 6, 10, 13}
1648     };
1649     private final static String INDEXOF_SUPPLEMENTARY_STR_ = "\udc02\ud841";
1650     private final static int INDEXOF_SUPPLEMENTARY_STR_INDEX_[] =
1651     {3, 16};
1652
1653     // private methods ---------------------------------------------------
1654 }
1655