1 /*
2  * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 /*
25  * @test
26  * @bug 6850113 8032446
27  * @summary confirm the behavior of new Bidi implementation. (Backward compatibility)
28  * @modules java.desktop
29  */
30 
31 import java.awt.font.NumericShaper;
32 import java.awt.font.TextAttribute;
33 import java.text.AttributedString;
34 import java.text.Bidi;
35 import java.util.Arrays;
36 
37 public class BidiConformance {
38 
39     /* internal flags */
40     private static boolean error = false;
41     private static boolean verbose = false;
42     private static boolean abort = false;
43 
44     private static final byte MAX_EXPLICIT_LEVEL = 125;
45 
main(String[] args)46     public static void main(String[] args) {
47         for (int i = 0; i < args.length; i++) {
48             String arg = args[i];
49             if (arg.equals("-verbose")) {
50                 verbose = true;
51             } else if (arg.equals("-abort")) {
52                 abort = true;
53             }
54         }
55 
56         BidiConformance bc = new BidiConformance();
57         bc.test();
58 
59         if (error) {
60             throw new RuntimeException("Failed.");
61         } else {
62             System.out.println("Passed.");
63         }
64     }
65 
test()66     private void test() {
67         testConstants();
68         testConstructors();
69         testMethods();
70 
71         testMethods4Constructor1();  // Bidi(AttributedCharacterIterator)
72         testMethods4Constructor2();  // Bidi(String, int)
73         testMethods4Constructor3();  // Bidi(char[], ...)
74     }
75 
testConstants()76     private void testConstants() {
77         System.out.println("*** Test constants");
78 
79         checkResult("Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT",
80                      -2, Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT);
81         checkResult("Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT",
82                      -1, Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT);
83         checkResult("Bidi.DIRECTION_LEFT_TO_RIGHT",
84                      0, Bidi.DIRECTION_LEFT_TO_RIGHT);
85         checkResult("Bidi.DIRECTION_RIGHT_TO_LEFT",
86                      1, Bidi.DIRECTION_RIGHT_TO_LEFT);
87     }
88 
testConstructors()89     private void testConstructors() {
90         System.out.println("*** Test constructors");
91 
92         testConstructor1();  // Bidi(AttributedCharacterIterator)
93         testConstructor2();  // Bidi(String, int)
94         testConstructor3();  // Bidi(char[], ...)
95     }
96 
testMethods()97     private void testMethods() {
98         System.out.println("*** Test methods");
99 
100         testMethod_createLineBidi1();
101         testMethod_createLineBidi2();
102         testMethod_getLevelAt();
103         testMethod_getRunLevel();
104         testMethod_getRunLimit();
105         testMethod_getRunStart();
106         testMethod_reorderVisually1();
107         testMethod_reorderVisually2();
108         testMethod_requiresBidi();
109     }
110 
testMethods4Constructor1()111     private void testMethods4Constructor1() {
112         System.out.println("*** Test methods for constructor 1");
113 
114         String paragraph;
115         Bidi bidi;
116         NumericShaper ns = NumericShaper.getShaper(NumericShaper.ARABIC);
117 
118         for (int textNo = 0; textNo < data4Constructor1.length; textNo++) {
119             paragraph = data4Constructor1[textNo][0];
120             int start = paragraph.indexOf('<')+1;
121             int limit = paragraph.indexOf('>');
122             int testNo;
123 
124             System.out.println("*** Test textNo=" + textNo +
125                 ": Bidi(AttributedCharacterIterator\"" +
126                 toReadableString(paragraph) + "\") " +
127                 "  start=" + start + ", limit=" + limit);
128 
129             // Test 0
130             testNo = 0;
131             System.out.println(" Test#" + testNo +": RUN_DIRECTION_LTR");
132             AttributedString astr = new AttributedString(paragraph);
133             astr.addAttribute(TextAttribute.RUN_DIRECTION,
134                               TextAttribute.RUN_DIRECTION_LTR);
135             bidi = new Bidi(astr.getIterator());
136 
137             callTestEachMethod4Constructor1(textNo, testNo, bidi);
138 
139             // Test 1
140             ++testNo;
141             System.out.println(" Test#" + testNo +
142                 ": RUN_DIRECTION_LTR, BIDI_EMBEDDING(1)");
143             astr = new AttributedString(paragraph);
144             astr.addAttribute(TextAttribute.RUN_DIRECTION,
145                               TextAttribute.RUN_DIRECTION_LTR);
146             astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(1),
147                               start, limit);
148             bidi = new Bidi(astr.getIterator());
149             callTestEachMethod4Constructor1(textNo, testNo, bidi);
150 
151             // Test 2
152             ++testNo;
153             System.out.println(" Test#" + testNo +
154                 ": RUN_DIERCTION_LTR, BIDI_EMBEDDING(2)");
155             astr = new AttributedString(paragraph);
156             astr.addAttribute(TextAttribute.RUN_DIRECTION,
157                               TextAttribute.RUN_DIRECTION_LTR);
158             astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(2),
159                               start, limit);
160             bidi = new Bidi(astr.getIterator());
161             callTestEachMethod4Constructor1(textNo, testNo, bidi);
162 
163             // Test 3
164             ++testNo;
165             System.out.println(" Test#" + testNo +
166                 ": RUN_DIRECTIOIN_LTR, BIDI_EMBEDDING(-3)");
167             astr = new AttributedString(paragraph);
168             astr.addAttribute(TextAttribute.RUN_DIRECTION,
169                               TextAttribute.RUN_DIRECTION_LTR);
170             astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(-3),
171                               start, limit);
172             bidi = new Bidi(astr.getIterator());
173             callTestEachMethod4Constructor1(textNo, testNo, bidi);
174 
175             // Test 4
176             ++testNo;
177             System.out.println(" Test#" + testNo +
178                 ": RUN_DIRECTION_LTR, BIDI_EMBEDDING(-4)");
179             astr = new AttributedString(paragraph);
180             astr.addAttribute(TextAttribute.RUN_DIRECTION,
181                               TextAttribute.RUN_DIRECTION_LTR);
182             astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(-4),
183                               start, limit);
184             bidi = new Bidi(astr.getIterator());
185             callTestEachMethod4Constructor1(textNo, testNo, bidi);
186 
187             // Test 5
188             ++testNo;
189             System.out.println(" Test#" + testNo + ": RUN_DIRECTION_RTL");
190             astr = new AttributedString(paragraph);
191             astr.addAttribute(TextAttribute.RUN_DIRECTION,
192                               TextAttribute.RUN_DIRECTION_RTL);
193             bidi = new Bidi(astr.getIterator());
194             callTestEachMethod4Constructor1(textNo, testNo, bidi);
195 
196             // Test 6
197             ++testNo;
198             System.out.println(" Test#" + testNo +
199                 ": RUN_DIRECTION_RTL, BIDI_EMBEDDING(1)");
200             astr = new AttributedString(paragraph);
201             astr.addAttribute(TextAttribute.RUN_DIRECTION,
202                               TextAttribute.RUN_DIRECTION_RTL);
203             astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(1),
204                               start, limit);
205             try {
206                 bidi = new Bidi(astr.getIterator());
207                 callTestEachMethod4Constructor1(textNo, testNo, bidi);
208             }
209             catch (IllegalArgumentException e) {
210                 errorHandling("  Unexpected exception: " + e);
211             }
212 
213             // Test 7
214             ++testNo;
215             System.out.println(" Test#" + testNo +
216                 ": RUN_DIRECTION_RTL, BIDI_EMBEDDING(2)");
217             astr = new AttributedString(paragraph);
218             astr.addAttribute(TextAttribute.RUN_DIRECTION,
219                               TextAttribute.RUN_DIRECTION_RTL);
220             astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(2),
221                               start, limit);
222             try {
223                 bidi = new Bidi(astr.getIterator());
224                 callTestEachMethod4Constructor1(textNo, testNo, bidi);
225             }
226             catch (IllegalArgumentException e) {
227                 errorHandling("  Unexpected exception: " + e);
228             }
229 
230             // Test 8
231             ++testNo;
232             System.out.println(" Test#" + testNo +
233                 ": RUN_DIRECTION_RTL, BIDI_EMBEDDING(-3)");
234             astr = new AttributedString(paragraph);
235             astr.addAttribute(TextAttribute.RUN_DIRECTION,
236                               TextAttribute.RUN_DIRECTION_RTL);
237             astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(-3),
238                               start, limit);
239             try {
240                 bidi = new Bidi(astr.getIterator());
241                 callTestEachMethod4Constructor1(textNo, testNo, bidi);
242             }
243             catch (IllegalArgumentException e) {
244                 errorHandling("  Unexpected exception: " + e);
245             }
246 
247             // Test 9
248             ++testNo;
249             System.out.println(" Test#" + testNo +
250                 ": RUN_DIRECTION_RTL, BIDI_EMBEDDING(-4)");
251             astr = new AttributedString(paragraph);
252             astr.addAttribute(TextAttribute.RUN_DIRECTION,
253                               TextAttribute.RUN_DIRECTION_RTL);
254             astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(-4),
255                               start, limit);
256             try {
257                 bidi = new Bidi(astr.getIterator());
258                 callTestEachMethod4Constructor1(textNo, testNo, bidi);
259             }
260             catch (IllegalArgumentException e) {
261                 errorHandling("  Unexpected exception: " + e);
262             }
263 
264             // Test 10
265             ++testNo;
266             System.out.println(" Test#" + testNo +
267                 ": TextAttribute not specified");
268             astr = new AttributedString(paragraph);
269             bidi = new Bidi(astr.getIterator());
270             callTestEachMethod4Constructor1(textNo, testNo, bidi);
271 
272             // Test 11
273             ++testNo;
274             System.out.println(" Test#" + testNo +
275                 ": RUN_DIRECTION_LTR, NUMERIC_SHAPING(ARABIC)");
276             astr = new AttributedString(paragraph);
277             astr.addAttribute(TextAttribute.RUN_DIRECTION,
278                               TextAttribute.RUN_DIRECTION_LTR);
279             astr.addAttribute(TextAttribute.NUMERIC_SHAPING, ns);
280             bidi = new Bidi(astr.getIterator());
281             callTestEachMethod4Constructor1(textNo, testNo, bidi);
282 
283             // Test 12
284             ++testNo;
285             System.out.println(" Test#" + testNo +
286                  ": RUN_DIRECTION_RTL, NUMERIC_SHAPING(ARABIC)");
287             astr = new AttributedString(paragraph);
288             astr.addAttribute(TextAttribute.RUN_DIRECTION,
289                               TextAttribute.RUN_DIRECTION_RTL);
290             astr.addAttribute(TextAttribute.NUMERIC_SHAPING, ns);
291             bidi = new Bidi(astr.getIterator());
292             callTestEachMethod4Constructor1(textNo, testNo, bidi);
293         }
294     }
295 
testMethods4Constructor2()296     private void testMethods4Constructor2() {
297         System.out.println("*** Test methods for constructor 2");
298 
299         String paragraph;
300         Bidi bidi;
301 
302         for (int textNo = 0; textNo < data4Constructor2.length; textNo++) {
303             paragraph = data4Constructor2[textNo][0];
304             for (int flagNo = 0; flagNo < FLAGS.length; flagNo++) {
305                 int flag = FLAGS[flagNo];
306 
307                 System.out.println("*** Test textNo=" + textNo +
308                     ": Bidi(\"" + toReadableString(paragraph) +
309                     "\", " + getFlagName(flag) + ")");
310 
311                 bidi = new Bidi(paragraph, flag);
312                 callTestEachMethod4Constructor2(textNo, flagNo, bidi);
313             }
314         }
315     }
316 
testMethods4Constructor3()317     private void testMethods4Constructor3() {
318         System.out.println("*** Test methods for constructor 3");
319 
320         String paragraph;
321         Bidi bidi;
322 
323         for (int textNo = 0; textNo < data4Constructor3.length; textNo++) {
324             paragraph = data4Constructor3[textNo][0];
325             char[] c = paragraph.toCharArray();
326             int start = paragraph.indexOf('<')+1;
327             byte[][] embeddings = (c.length < emb4Constructor3[1][0].length) ?
328                                   emb4Constructor3[0] : emb4Constructor3[1];
329             for (int flagNo = 0; flagNo < FLAGS.length; flagNo++) {
330                 int flag = FLAGS[flagNo];
331                 for (int embNo = 0; embNo < embeddings.length; embNo++) {
332                     int dataNo = flagNo * FLAGS.length + embNo;
333 
334                     System.out.println("*** Test textNo=" + textNo +
335                         ": Bidi(char[]\"" + toReadableString(paragraph) +
336                         "\", 0, embeddings={" + toString(embeddings[embNo]) +
337                         "}, " + c.length + ", " +
338                        getFlagName(flag) + ")" + "  dataNo=" + dataNo);
339 
340                     try {
341                         bidi = new Bidi(c, 0, embeddings[embNo], 0,
342                                         c.length, flag);
343                         callTestEachMethod4Constructor3(textNo, dataNo, bidi);
344                     }
345                     catch (Exception e) {
346                         errorHandling("  Unexpected exception: " + e);
347                     }
348                 }
349             }
350         }
351     }
352 
testConstructor1()353     private void testConstructor1() {
354         Bidi bidi;
355 
356         try {
357             bidi = new Bidi(null);
358             errorHandling("Bidi((AttributedCharacterIterator)null) " +
359                 "should throw an IAE.");
360         }
361         catch (IllegalArgumentException e) {
362         }
363         catch (NullPointerException e) {
364             errorHandling("Bidi((AttributedCharacterIterator)null) " +
365                 "should not throw an NPE but an IAE.");
366         }
367 
368         String paragraph = data4Constructor1[1][0];
369         int start = paragraph.indexOf('<')+1;
370         int limit = paragraph.indexOf('>');
371         AttributedString astr = new AttributedString(paragraph);
372         astr.addAttribute(TextAttribute.RUN_DIRECTION,
373                           TextAttribute.RUN_DIRECTION_RTL);
374         astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(-MAX_EXPLICIT_LEVEL),
375                           start, limit);
376         try {
377             bidi = new Bidi(astr.getIterator());
378             for (int i = start; i < limit; i++) {
379                 if (bidi.getLevelAt(i) != MAX_EXPLICIT_LEVEL) {
380                     errorHandling("Bidi(AttributedCharacterIterator).getLevelAt(" +
381                         i + ") should not be " + bidi.getLevelAt(i) +
382                         " but MAX_EXPLICIT_LEVEL-1 when BIDI_EMBEDDING is -MAX_EXPLICIT_LEVEL.");
383                 }
384             }
385         }
386         catch (Exception e) {
387             errorHandling("  Unexpected exception: " + e);
388         }
389 
390         astr = new AttributedString(paragraph);
391         astr.addAttribute(TextAttribute.RUN_DIRECTION,
392                           TextAttribute.RUN_DIRECTION_RTL);
393         astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(-(MAX_EXPLICIT_LEVEL+1)),
394                           start, limit);
395         try {
396             bidi = new Bidi(astr.getIterator());
397             for (int i = start; i < limit; i++) {
398                 if (bidi.getLevelAt(i) != 1) {
399                     errorHandling("Bidi(AttributedCharacterIterator).getLevelAt() " +
400                         "should be 1 when BIDI_EMBEDDING is -(MAX_EXPLICIT_LEVEL+1).");
401                 }
402             }
403         }
404         catch (Exception e) {
405             errorHandling("  Unexpected exception: " + e);
406         }
407 
408         astr = new AttributedString(paragraph);
409         astr.addAttribute(TextAttribute.RUN_DIRECTION,
410                           TextAttribute.RUN_DIRECTION_RTL);
411         astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(MAX_EXPLICIT_LEVEL-1),
412                           start, limit);
413         try {
414             bidi = new Bidi(astr.getIterator());
415             for (int i = start; i < limit; i++) {
416                 if (bidi.getLevelAt(i) != MAX_EXPLICIT_LEVEL) {
417                     errorHandling("Bidi(AttributedCharacterIterator).getLevelAt() " +
418                         "should be MAX_EXPLICIT_LEVEL when BIDI_EMBEDDING is MAX_EXPLICIT_LEVEL-1.");
419                 }
420             }
421         }
422         catch (Exception e) {
423             errorHandling("  Unexpected exception: " + e);
424         }
425 
426         astr = new AttributedString(paragraph);
427         astr.addAttribute(TextAttribute.RUN_DIRECTION,
428                           TextAttribute.RUN_DIRECTION_RTL);
429         astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(MAX_EXPLICIT_LEVEL),
430                           start, limit);
431         try {
432             bidi = new Bidi(astr.getIterator());
433             for (int i = start; i < limit; i++) {
434                 if (bidi.getLevelAt(i) != MAX_EXPLICIT_LEVEL) {
435                     errorHandling("Bidi(AttributedCharacterIterator).getLevelAt(" +
436                         i + ") should not be " + bidi.getLevelAt(i) +
437                         " but MAX_EXPLICIT_LEVEL when BIDI_EMBEDDING is MAX_EXPLICIT_LEVEL.");
438                 }
439             }
440         }
441         catch (Exception e) {
442             errorHandling("  Unexpected exception: " + e);
443         }
444 
445         astr = new AttributedString(paragraph);
446         astr.addAttribute(TextAttribute.RUN_DIRECTION,
447                           TextAttribute.RUN_DIRECTION_RTL);
448         astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(MAX_EXPLICIT_LEVEL+1),
449                           start, limit);
450         try {
451             bidi = new Bidi(astr.getIterator());
452             for (int i = start; i < limit; i++) {
453                 if (bidi.getLevelAt(i) != 1) {
454                     errorHandling("Bidi(AttributedCharacterIterator).getLevelAt(" +
455                          i + ") should not be " + bidi.getLevelAt(i) +
456                         " but 1 when BIDI_EMBEDDING is MAX_EXPLICIT_LEVEL+1.");
457                 }
458             }
459         }
460         catch (Exception e) {
461             errorHandling("  Unexpected exception: " + e);
462         }
463     }
464 
testConstructor2()465     private void testConstructor2() {
466         Bidi bidi;
467 
468         try {
469             bidi = new Bidi(null, Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT);
470             errorHandling("Bidi((String)null, DIRECTION_DEFAULT_LEFT_TO_RIGHT)" +
471                 " should throw an IAE.");
472         }
473         catch (IllegalArgumentException e) {
474         }
475         catch (NullPointerException e) {
476             errorHandling("Bidi((String)null, DIRECTION_DEFAULT_LEFT_TO_RIGHT) " +
477                 "should not throw an NPE but an IAE.");
478         }
479 
480         try {
481             bidi = new Bidi("abc", -3);
482         }
483         catch (Exception e) {
484             errorHandling("Bidi(\"abc\", -3) should not throw an exception: " +
485                 e);
486         }
487 
488         try {
489             bidi = new Bidi("abc", 2);
490         }
491         catch (Exception e) {
492             errorHandling("Bidi(\"abc\", 2) should not throw an exception: " +
493                 e);
494         }
495     }
496 
testConstructor3()497     private void testConstructor3() {
498         char[] text = {'a', 'b', 'c', 'd', 'e'};
499         byte[] embeddings = {0, 0, 0, 0, 0};
500         Bidi bidi;
501 
502         try {
503             bidi = new Bidi(null, 0, embeddings, 0, 5,
504                             Bidi.DIRECTION_LEFT_TO_RIGHT);
505             errorHandling("Bidi(char[], ...) should throw an IAE " +
506                 "when text=null.");
507         }
508         catch (IllegalArgumentException e) {
509         }
510         catch (NullPointerException e) {
511             errorHandling("Bidi(char[], ...) should not throw an NPE " +
512                 "but an IAE when text=null.");
513         }
514 
515         try {
516             bidi = new Bidi(text, -1, embeddings, 0, 5,
517                             Bidi.DIRECTION_LEFT_TO_RIGHT);
518             errorHandling("Bidi(char[], ...) should throw an IAE " +
519                 "when textStart is incorrect(-1: too small).");
520         }
521         catch (IllegalArgumentException e) {
522         }
523         catch (ArrayIndexOutOfBoundsException e) {
524             errorHandling("Bidi(char[], ...) should not throw an NPE " +
525                 "but an IAE when textStart is incorrect(-1: too small).");
526         }
527 
528         try {
529             bidi = new Bidi(text, 4, embeddings, 0, 2,
530                             Bidi.DIRECTION_LEFT_TO_RIGHT);
531             errorHandling("Bidi(char[], ...) should throw an IAE " +
532                 "when textStart is incorrect(4: too large).");
533         }
534         catch (IllegalArgumentException e) {
535         }
536         catch (ArrayIndexOutOfBoundsException e) {
537             errorHandling("Bidi(char[], ...) should not throw an NPE " +
538                 "but an IAE when textStart is incorrect(4: too large).");
539         }
540 
541         byte[] actualLevels = new byte[text.length];
542         byte[] validEmbeddings1 = {0, -MAX_EXPLICIT_LEVEL, -(MAX_EXPLICIT_LEVEL-1), -2, -1};
543         byte[] expectedLevels1  = {0,  MAX_EXPLICIT_LEVEL,  MAX_EXPLICIT_LEVEL-1,  2,  1};
544         try {
545             bidi = new Bidi(text, 0, validEmbeddings1, 0, 5,
546                             Bidi.DIRECTION_LEFT_TO_RIGHT);
547             for (int i = 0; i < text.length; i++) {
548                 actualLevels[i] = (byte)bidi.getLevelAt(i);
549             }
550             if (!Arrays.equals(expectedLevels1, actualLevels)) {
551                 errorHandling("Bidi(char[], ...).getLevelAt()" +
552                     " should be {" + toString(actualLevels) +
553                     "} when embeddings are {" +
554                     toString(expectedLevels1) + "}.");
555             }
556         }
557         catch (Exception e) {
558             errorHandling("Bidi(char[], ...) should not throw an exception " +
559                 "when embeddings is valid(-MAX_EXPLICIT_LEVEL).");
560         }
561 
562         byte[] validEmbeddings2 = {0,  MAX_EXPLICIT_LEVEL,  MAX_EXPLICIT_LEVEL-1,  2,  1};
563         byte[] expectedLevels2  = {0,  MAX_EXPLICIT_LEVEL+1,  MAX_EXPLICIT_LEVEL-1,  2,  2};
564         try {
565             bidi = new Bidi(text, 0, validEmbeddings2, 0, 5,
566                             Bidi.DIRECTION_LEFT_TO_RIGHT);
567             for (int i = 0; i < text.length; i++) {
568                 actualLevels[i] = (byte)bidi.getLevelAt(i);
569             }
570             if (!Arrays.equals(expectedLevels2, actualLevels)) {
571                 errorHandling("Bidi(char[], ...).getLevelAt()" +
572                     " should be {" + toString(actualLevels) +
573                     "} when embeddings are {" +
574                     toString(expectedLevels2) + "}.");
575             }
576         }
577         catch (Exception e) {
578             errorHandling("Bidi(char[], ...) should not throw an exception " +
579                 "when embeddings is valid(MAX_EXPLICIT_LEVEL).");
580         }
581 
582         byte[] invalidEmbeddings1 = {0, -(MAX_EXPLICIT_LEVEL+1), 0, 0, 0};
583         try {
584             bidi = new Bidi(text, 0, invalidEmbeddings1, 0, 5,
585                             Bidi.DIRECTION_LEFT_TO_RIGHT);
586             if (bidi.getLevelAt(1) != 0) {
587                 errorHandling("Bidi(char[], ...).getLevelAt(1) should be 0 " +
588                     "when embeddings[1] is -(MAX_EXPLICIT_LEVEL+1).");
589             }
590         }
591         catch (Exception e) {
592             errorHandling("Bidi(char[], ...) should not throw an exception " +
593                 "even when embeddings includes -(MAX_EXPLICIT_LEVEL+1).");
594         }
595 
596         byte[] invalidEmbeddings2 = {0, MAX_EXPLICIT_LEVEL+1, 0, 0, 0};
597         try {
598             bidi = new Bidi(text, 0, invalidEmbeddings2, 0, 5,
599                             Bidi.DIRECTION_LEFT_TO_RIGHT);
600             if (bidi.getLevelAt(1) != 0) {
601                 errorHandling("Bidi(char[], ...).getLevelAt(1) should be 0 " +
602                     "when embeddings[1] is MAX_EXPLICIT_LEVEL+1.");
603             }
604         }
605         catch (Exception e) {
606             errorHandling("Bidi(char[], ...) should not throw an exception " +
607                 "even when embeddings includes MAX_EXPLICIT_LEVEL+1.");
608         }
609 
610         try {
611             bidi = new Bidi(text, 0, embeddings, 0, -1,
612                             Bidi.DIRECTION_LEFT_TO_RIGHT);
613             errorHandling("Bidi(char[], ...) should throw an IAE " +
614                 "when paragraphLength=-1(too small).");
615         }
616         catch (IllegalArgumentException e) {
617         }
618         catch (NegativeArraySizeException e) {
619             errorHandling("Bidi(char[], ...) should not throw an NASE " +
620                 "but an IAE when paragraphLength=-1(too small).");
621         }
622 
623         try {
624             bidi = new Bidi(text, 0, embeddings, 0, 6,
625                             Bidi.DIRECTION_LEFT_TO_RIGHT);
626             errorHandling("Bidi(char[], ...) should throw an IAE " +
627                 "when paragraphLength=6(too large).");
628         }
629         catch (IllegalArgumentException e) {
630         }
631         catch (ArrayIndexOutOfBoundsException e) {
632             errorHandling("Bidi(char[], ...) should not throw an AIOoBE " +
633                 "but an IAE when paragraphLength=6(too large).");
634         }
635 
636         try {
637             bidi = new Bidi(text, 0, embeddings, 0, 4, -3);
638         }
639         catch (Exception e) {
640             errorHandling("Bidi(char[], ...) should not throw an exception " +
641                 "even when flag=-3(too small).");
642         }
643 
644         try {
645             bidi = new Bidi(text, 0, embeddings, 0, 5, 2);
646         }
647         catch (Exception e) {
648             errorHandling("Bidi(char[], ...) should not throw an exception " +
649                 "even when flag=2(too large).");
650         }
651     }
652 
callTestEachMethod4Constructor1(int textNo, int testNo, Bidi bidi)653     private void callTestEachMethod4Constructor1(int textNo,
654                                                  int testNo,
655                                                  Bidi bidi) {
656         testEachMethod(bidi,
657                        data4Constructor1[textNo][0],
658                        data4Constructor1[textNo][testNo+1],
659                        baseIsLTR4Constructor1[textNo][testNo],
660                        isLTR_isRTL4Constructor1[textNo][0][testNo],
661                        isLTR_isRTL4Constructor1[textNo][1][testNo]);
662     }
663 
callTestEachMethod4Constructor2(int textNo, int flagNo, Bidi bidi)664     private void callTestEachMethod4Constructor2(int textNo,
665                                                  int flagNo,
666                                                  Bidi bidi) {
667         testEachMethod(bidi,
668                        data4Constructor2[textNo][0],
669                        data4Constructor2[textNo][flagNo+1],
670                        baseIsLTR4Constructor2[textNo][flagNo],
671                        isLTR_isRTL4Constructor2[textNo][0][flagNo],
672                        isLTR_isRTL4Constructor2[textNo][1][flagNo]);
673     }
674 
callTestEachMethod4Constructor3(int textNo, int dataNo, Bidi bidi)675     private void callTestEachMethod4Constructor3(int textNo,
676                                                  int dataNo,
677                                                  Bidi bidi) {
678         testEachMethod(bidi,
679                        data4Constructor3[textNo][0],
680                        data4Constructor3[textNo][dataNo+1],
681                        baseIsLTR4Constructor3[textNo][dataNo],
682                        isLTR_isRTL4Constructor3[textNo][0][dataNo],
683                        isLTR_isRTL4Constructor3[textNo][1][dataNo]);
684     }
685 
686     private StringBuilder sb = new StringBuilder();
testEachMethod(Bidi bidi, String text, String expectedLevels, boolean expectedBaseIsLTR, boolean expectedIsLTR, boolean expectedIsRTL )687     private void testEachMethod(Bidi bidi,
688                                 String text,
689                                 String expectedLevels,
690                                 boolean expectedBaseIsLTR,
691                                 boolean expectedIsLTR,
692                                 boolean expectedIsRTL
693                                ) {
694         /* Test baseIsLeftToRight() */
695         boolean actualBoolean = bidi.baseIsLeftToRight();
696         checkResult("baseIsLeftToRight()", expectedBaseIsLTR, actualBoolean);
697 
698         /* Test getBaseLevel() */
699         int expectedInt = (expectedBaseIsLTR) ? 0 : 1;
700         int actualInt = bidi.getBaseLevel();
701         checkResult("getBaseLevel()", expectedInt, actualInt);
702 
703         /* Test getLength() */
704         expectedInt = text.length();
705         actualInt = bidi.getLength();
706         checkResult("getLength()", expectedInt, actualInt);
707 
708         /* Test getLevelAt() */
709         sb.setLength(0);
710         for (int i = 0; i < text.length(); i++) {
711             sb.append(bidi.getLevelAt(i));
712         }
713         checkResult("getLevelAt()", expectedLevels, sb.toString());
714 
715         /* Test getRunCount() */
716         expectedInt = getRunCount(expectedLevels);
717         actualInt = bidi.getRunCount();
718         checkResult("getRunCount()", expectedInt, actualInt);
719 
720         /* Test getRunLevel(), getRunLimit() and getRunStart() */
721         if (expectedInt == actualInt) {
722             int runCount = expectedInt;
723             int[] expectedRunLevels = getRunLevels_int(runCount, expectedLevels);
724             int[] expectedRunLimits = getRunLimits(runCount, expectedLevels);
725             int[] expectedRunStarts = getRunStarts(runCount, expectedLevels);
726             int[] actualRunLevels = new int[runCount];
727             int[] actualRunLimits = new int[runCount];
728             int[] actualRunStarts = new int[runCount];
729 
730             for (int k = 0; k < runCount; k++) {
731                 actualRunLevels[k] = bidi.getRunLevel(k);
732                 actualRunLimits[k] = bidi.getRunLimit(k);
733                 actualRunStarts[k] = bidi.getRunStart(k);
734             }
735 
736             checkResult("getRunLevel()", expectedRunLevels, actualRunLevels);
737             checkResult("getRunStart()", expectedRunStarts, actualRunStarts);
738             checkResult("getRunLimit()", expectedRunLimits, actualRunLimits);
739         }
740 
741         /* Test isLeftToRight() */
742         boolean expectedBoolean = expectedIsLTR;
743         actualBoolean = bidi.isLeftToRight();
744         checkResult("isLeftToRight()", expectedBoolean, actualBoolean);
745 
746         /* Test isMixed() */
747         expectedBoolean = !(expectedIsLTR || expectedIsRTL);
748         actualBoolean = bidi.isMixed();
749         checkResult("isMixed()", expectedBoolean, actualBoolean);
750 
751         /* Test isRightToLeft() */
752         expectedBoolean = expectedIsRTL;
753         actualBoolean = bidi.isRightToLeft();
754         checkResult("isRightToLeft()", expectedBoolean, actualBoolean);
755     }
756 
getRunCount(String levels)757     private int getRunCount(String levels) {
758         int len = levels.length();
759         char c = levels.charAt(0);
760         int runCount = 1;
761 
762         for (int index = 1; index < len; index++) {
763             if (levels.charAt(index) != c) {
764                 runCount++;
765                 c = levels.charAt(index);
766             }
767         }
768 
769         return runCount;
770     }
771 
getRunLevels_int(int runCount, String levels)772     private int[] getRunLevels_int(int runCount, String levels) {
773         int[] array = new int[runCount];
774         int len = levels.length();
775         char c = levels.charAt(0);
776         int i = 0;
777         array[i++] = c - '0';
778 
779         for (int index = 1; index < len; index++) {
780             if (levels.charAt(index) != c) {
781                 c = levels.charAt(index);
782                 array[i++] = c - '0';
783             }
784         }
785 
786         return array;
787     }
788 
getRunLevels_byte(int runCount, String levels)789     private byte[] getRunLevels_byte(int runCount, String levels) {
790         byte[] array = new byte[runCount];
791         int len = levels.length();
792         char c = levels.charAt(0);
793         int i = 0;
794         array[i++] = (byte)(c - '0');
795 
796         for (int index = 1; index < len; index++) {
797             if (levels.charAt(index) != c) {
798                 c = levels.charAt(index);
799                 array[i++] = (byte)(c - '0');
800             }
801         }
802 
803         return array;
804     }
805 
getRunLimits(int runCount, String levels)806     private int[] getRunLimits(int runCount, String levels) {
807         int[] array = new int[runCount];
808         int len = levels.length();
809         char c = levels.charAt(0);
810         int i = 0;
811 
812         for (int index = 1; index < len; index++) {
813             if (levels.charAt(index) != c) {
814                 c = levels.charAt(index);
815                 array[i++] = index;
816             }
817         }
818         array[i] = len;
819 
820         return array;
821     }
822 
getRunStarts(int runCount, String levels)823     private int[] getRunStarts(int runCount, String levels) {
824         int[] array = new int[runCount];
825         int len = levels.length();
826         char c = levels.charAt(0);
827         int i = 1;
828 
829         for (int index = 1; index < len; index++) {
830             if (levels.charAt(index) != c) {
831                 c = levels.charAt(index);
832                 array[i++] = index;
833             }
834         }
835 
836         return array;
837     }
838 
getObjects(int runCount, String text, String levels)839     private String[] getObjects(int runCount, String text, String levels) {
840         String[] array = new String[runCount];
841         int[] runLimits = getRunLimits(runCount, levels);
842         int runStart = 0;
843 
844         for (int i = 0; i < runCount; i++) {
845             array[i] = text.substring(runStart, runLimits[i]);
846             runStart = runLimits[i];
847         }
848 
849         return array;
850     }
851 
testMethod_createLineBidi1()852     private void testMethod_createLineBidi1() {
853         System.out.println("*** Test createLineBidi() 1");
854 
855         String str = " ABC 123. " + HebrewABC + " " + NKo123 + ". ABC 123";
856 
857         int lineStart = str.indexOf('.') + 2;
858         int lineLimit = str.lastIndexOf('.') + 2;
859         Bidi bidi = new Bidi(str, FLAGS[0]);
860         Bidi lineBidi = bidi.createLineBidi(lineStart, lineLimit);
861 
862         checkResult("getBaseLevel()",
863             bidi.getBaseLevel(), lineBidi.getBaseLevel());
864         checkResult("getLevelAt(5)",
865             bidi.getLevelAt(lineStart+5), lineBidi.getLevelAt(5));
866     }
867 
testMethod_createLineBidi2()868     private void testMethod_createLineBidi2() {
869         System.out.println("*** Test createLineBidi() 2");
870 
871         Bidi bidi = new Bidi(data4Constructor1[0][0], FLAGS[0]);
872         int len = data4Constructor1[0][0].length();
873 
874         try {
875             Bidi lineBidi = bidi.createLineBidi(0, len);
876         }
877         catch (Exception e) {
878             errorHandling("createLineBidi(0, textLength)" +
879                 " should not throw an exception.");
880         }
881 
882         try {
883             Bidi lineBidi = bidi.createLineBidi(-1, len);
884             errorHandling("createLineBidi(-1, textLength)" +
885                 " should throw an IAE.");
886         }
887         catch (IllegalArgumentException e) {
888         }
889 
890         try {
891             Bidi lineBidi = bidi.createLineBidi(0, len+1);
892             errorHandling("createLineBidi(0, textLength+1)" +
893                 " should throw an IAE.");
894         }
895         catch (IllegalArgumentException e) {
896         }
897     }
898 
899     /*
900      * Confirm that getLevelAt() doesn't throw an exception for invalid offset
901      * unlike ICU4J.
902      */
testMethod_getLevelAt()903     private void testMethod_getLevelAt() {
904         System.out.println("*** Test getLevelAt()");
905 
906         Bidi bidi = new Bidi(data4Constructor1[1][0], FLAGS[0]);
907         int len = data4Constructor1[1][0].length();
908 
909         try {
910             int level = bidi.getLevelAt(-1);
911             if (level != bidi.getBaseLevel()) {
912                 errorHandling("getLevelAt(-1) returned a wrong level." +
913                     " Expected=" + bidi.getBaseLevel() + ", got=" + level);
914             }
915         }
916         catch (Exception e) {
917             errorHandling("getLevelAt(-1) should not throw an exception.");
918         }
919 
920         try {
921             int level = bidi.getLevelAt(len+1);
922             if (level != bidi.getBaseLevel()) {
923                 errorHandling("getLevelAt(textLength+1)" +
924                     " returned a wrong level." +
925                     " Expected=" + bidi.getBaseLevel() + ", got=" + level);
926             }
927         }
928         catch (Exception e) {
929             errorHandling("getLevelAt(-1) should not throw an exception.");
930         }
931     }
932 
testMethod_getRunLevel()933     private void testMethod_getRunLevel() {
934         System.out.println("*** Test getRunLevel()");
935 
936         String str = "ABC 123";
937         Bidi bidi = new Bidi(str, Bidi.DIRECTION_LEFT_TO_RIGHT);
938         try {
939             if (bidi.getRunLevel(-1) != 0 ||  // runCount - 2 (out of range)
940                 bidi.getRunLevel(0) != 0 ||   // runCount - 1
941                 bidi.getRunLevel(1) != 0 ||   // runCount     (out of range)
942                 bidi.getRunLevel(2) != 0) {   // runCount + 1 (out of range)
943                 errorHandling("Incorrect getRunLevel() value(s).");
944             }
945         }
946         catch (Exception e) {
947             errorHandling("getRunLevel() should not throw an exception: " + e);
948         }
949 
950         str = "ABC " + HebrewABC + " 123";
951         bidi = new Bidi(str, Bidi.DIRECTION_LEFT_TO_RIGHT);
952         try {
953             if (bidi.getRunLevel(-1) != 0 ||  // runCount - 4 (out of range)
954                 bidi.getRunLevel(0) != 0 ||   // runCount - 3
955                 bidi.getRunLevel(1) != 1 ||   // runCount - 2
956                 bidi.getRunLevel(2) != 2 ||   // runCount - 1
957                 bidi.getRunLevel(3) != 0 ||   // runCount     (out of range)
958                 bidi.getRunLevel(4) != 0) {   // runCount + 1 (out of range)
959                 errorHandling("Incorrect getRunLevel() value(s).");
960             }
961         }
962         catch (Exception e) {
963             errorHandling("getRunLevel() should not throw an exception: " + e);
964         }
965 
966         str = "ABC";
967         bidi = new Bidi(str, Bidi.DIRECTION_LEFT_TO_RIGHT);
968         try {
969             if (bidi.getRunLevel(-1) != 0 ||  // runCount - 2 (out of range)
970                 bidi.getRunLevel(0) != 0 ||   // runCount - 1
971                 bidi.getRunLevel(1) != 0 ||   // runCount     (out of range)
972                 bidi.getRunLevel(2) != 0) {   // runCount + 1 (out of range)
973                 errorHandling("Incorrect getRunLevel() value(s).");
974             }
975         }
976         catch (Exception e) {
977             errorHandling("getRunLevel() should not throw an exception: " + e);
978         }
979 
980         str = "ABC";
981         bidi = new Bidi(str, Bidi.DIRECTION_RIGHT_TO_LEFT);
982         try {
983             if (bidi.getRunLevel(-1) != 1 ||  // runCount - 2 (out of range)
984                 bidi.getRunLevel(0) != 2 ||   // runCount - 1
985                 bidi.getRunLevel(1) != 1 ||   // runCount     (out of range)
986                 bidi.getRunLevel(2) != 1) {   // runCount + 1 (out of range)
987                 errorHandling("Incorrect getRunLevel() value(s).");
988             }
989         }
990         catch (Exception e) {
991             errorHandling("getRunLevel() should not throw an exception: " + e);
992         }
993 
994         str = "ABC";
995         bidi = new Bidi(str, Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT);
996         try {
997             if (bidi.getRunLevel(-1) != 0 ||  // runCount - 2 (out of range)
998                 bidi.getRunLevel(0) != 0 ||   // runCount - 1
999                 bidi.getRunLevel(1) != 0 ||   // runCount     (out of range)
1000                 bidi.getRunLevel(2) != 0) {   // runCount + 1 (out of range)
1001                 errorHandling("Incorrect getRunLevel() value(s).");
1002             }
1003         }
1004         catch (Exception e) {
1005             errorHandling("getRunLevel() should not throw an exception: " + e);
1006         }
1007 
1008         str = "ABC";
1009         bidi = new Bidi(str, Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT);
1010         try {
1011             if (bidi.getRunLevel(-1) != 0 ||  // runCount - 2 (out of range)
1012                 bidi.getRunLevel(0) != 0 ||   // runCount - 1
1013                 bidi.getRunLevel(1) != 0 ||   // runCount     (out of range)
1014                 bidi.getRunLevel(2) != 0) {   // runCount + 1 (out of range)
1015                 errorHandling("Incorrect getRunLevel() value(s).");
1016             }
1017         }
1018         catch (Exception e) {
1019             errorHandling("getRunLevel() should not throw an exception: " + e);
1020         }
1021 
1022         str = HebrewABC;
1023         bidi = new Bidi(str, Bidi.DIRECTION_LEFT_TO_RIGHT);
1024         try {
1025             if (bidi.getRunLevel(-1) != 0 ||  // runCount - 2 (out of range)
1026                 bidi.getRunLevel(0) != 1 ||   // runCount - 1
1027                 bidi.getRunLevel(1) != 0 ||   // runCount     (out of range)
1028                 bidi.getRunLevel(2) != 0) {   // runCount + 1 (out of range)
1029                 errorHandling("Incorrect getRunLevel() value(s).");
1030             }
1031         }
1032         catch (Exception e) {
1033             errorHandling("getRunLevel() should not throw an exception: " + e);
1034         }
1035 
1036         str = HebrewABC;
1037         bidi = new Bidi(str, Bidi.DIRECTION_RIGHT_TO_LEFT);
1038         try {
1039             if (bidi.getRunLevel(-1) != 1 ||  // runCount - 2 (out of range)
1040                 bidi.getRunLevel(0) != 1 ||   // runCount - 1
1041                 bidi.getRunLevel(1) != 1 ||   // runCount     (out of range)
1042                 bidi.getRunLevel(2) != 1) {   // runCount + 1 (out of range)
1043                 errorHandling("Incorrect getRunLevel() value(s).");
1044             }
1045         }
1046         catch (Exception e) {
1047             errorHandling("getRunLevel() should not throw an exception: " + e);
1048         }
1049 
1050         str = HebrewABC;
1051         bidi = new Bidi(str, Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT);
1052         try {
1053             if (bidi.getRunLevel(-1) != 1 ||  // runCount - 2 (out of range)
1054                 bidi.getRunLevel(0) != 1 ||   // runCount - 1
1055                 bidi.getRunLevel(1) != 1 ||   // runCount     (out of range)
1056                 bidi.getRunLevel(2) != 1) {   // runCount + 1 (out of range)
1057                 errorHandling("Incorrect getRunLevel() value(s).");
1058             }
1059         }
1060         catch (Exception e) {
1061             errorHandling("getRunLevel() should not throw an exception: " + e);
1062         }
1063 
1064         str = HebrewABC;
1065         bidi = new Bidi(str, Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT);
1066         try {
1067             if (bidi.getRunLevel(-1) != 1 ||  // runCount - 2 (out of range)
1068                 bidi.getRunLevel(0) != 1 ||   // runCount - 1
1069                 bidi.getRunLevel(1) != 1 ||   // runCount     (out of range)
1070                 bidi.getRunLevel(2) != 1) {   // runCount + 1 (out of range)
1071                 errorHandling("Incorrect getRunLevel() value(s).");
1072             }
1073         }
1074         catch (Exception e) {
1075             errorHandling("getRunLevel() should not throw an exception: " + e);
1076         }
1077     }
1078 
testMethod_getRunLimit()1079     private void testMethod_getRunLimit() {
1080         System.out.println("*** Test getRunLimit()");
1081 
1082         String str = "ABC 123";
1083         int length = str.length();
1084         Bidi bidi = new Bidi(str, Bidi.DIRECTION_LEFT_TO_RIGHT);
1085 
1086         try {
1087             if (bidi.getRunLimit(-1) != length ||  // runCount - 2
1088                 bidi.getRunLimit(0) != length ||   // runCount - 1
1089                 bidi.getRunLimit(1) != length ||   // runCount
1090                 bidi.getRunLimit(2) != length) {   // runCount + 1
1091                 errorHandling("getRunLimit() should return " + length +
1092                     " when getRunCount() is 1.");
1093             }
1094         }
1095         catch (Exception e) {
1096             errorHandling("getRunLimit() should not throw an exception " +
1097                 "when getRunCount() is 1.");
1098         }
1099 
1100         str = "ABC " + ArabicABC + " 123";
1101         length = str.length();
1102         bidi = new Bidi(str, Bidi.DIRECTION_LEFT_TO_RIGHT);
1103 
1104         try {
1105             bidi.getRunLimit(-1);
1106             errorHandling("getRunLimit() should throw an AIOoBE " +
1107                 "when run is -1(too small).");
1108         }
1109         catch (ArrayIndexOutOfBoundsException e) {
1110         }
1111         catch (IllegalArgumentException e) {
1112             errorHandling("getRunLimit() should not throw an IAE " +
1113                 "but an AIOoBE when run is -1(too small).");
1114         }
1115 
1116         try {
1117             bidi.getRunLimit(0);
1118             bidi.getRunLimit(1);
1119             bidi.getRunLimit(2);
1120         }
1121         catch (ArrayIndexOutOfBoundsException e) {
1122             errorHandling("getRunLimit() should not throw an AIOOBE " +
1123                 "when run is from 0 to 2(runCount-1).");
1124         }
1125 
1126         try {
1127             bidi.getRunLimit(3);
1128             errorHandling("getRunLimit() should throw an AIOoBE " +
1129                 "when run is 3(same as runCount).");
1130         }
1131         catch (ArrayIndexOutOfBoundsException e) {
1132         }
1133         catch (IllegalArgumentException e) {
1134             errorHandling("getRunLimit() should not throw an IAE " +
1135                 "but an AIOoBE when run is 3(same as runCount).");
1136         }
1137     }
1138 
testMethod_getRunStart()1139     private void testMethod_getRunStart() {
1140         System.out.println("*** Test getRunStart()");
1141 
1142         String str = "ABC 123";
1143         int length = str.length();
1144         Bidi bidi = new Bidi(str, Bidi.DIRECTION_LEFT_TO_RIGHT);
1145 
1146         try {
1147             if (bidi.getRunStart(-1) != 0 ||  // runCount - 2
1148                 bidi.getRunStart(0) != 0 ||   // runCount - 1
1149                 bidi.getRunStart(1) != 0 ||   // runCount
1150                 bidi.getRunStart(2) != 0) {   // runCount + 1
1151                 errorHandling("getRunStart() should return 0" +
1152                     " when getRunCount() is 1.");
1153             }
1154         }
1155         catch (Exception e) {
1156             errorHandling("getRunLimit() should not throw an exception" +
1157                 " when getRunCount() is 1.");
1158         }
1159 
1160         str = "ABC " + NKoABC + " 123";
1161         length = str.length();
1162         bidi = new Bidi(str, Bidi.DIRECTION_LEFT_TO_RIGHT);
1163 
1164         try {
1165             bidi.getRunStart(-1);
1166             errorHandling("getRunStart() should throw an AIOoBE" +
1167                 " when run is -1(too small).");
1168         }
1169         catch (ArrayIndexOutOfBoundsException e) {
1170         }
1171         catch (IllegalArgumentException e) {
1172             errorHandling("getRunStart() should not throw an IAE " +
1173                 "but an AIOoBE when run is -1(too small).");
1174         }
1175 
1176         try {
1177             bidi.getRunStart(0);
1178             bidi.getRunStart(1);
1179             bidi.getRunStart(2);
1180         }
1181         catch (ArrayIndexOutOfBoundsException e) {
1182             errorHandling("getRunStart() should not throw an AIOOBE " +
1183                 "when run is from 0 to 2(runCount-1).");
1184         }
1185 
1186         try {
1187             if (bidi.getRunStart(3) != length) {
1188                 errorHandling("getRunStart() should return " + length +
1189                     " when run is 3(same as runCount).");
1190             }
1191         }
1192         catch (Exception e) {
1193             errorHandling("getRunStart() should not throw an exception " +
1194                 "when run is 3(same as runCount).");
1195         }
1196 
1197         try {
1198             bidi.getRunStart(4);
1199             errorHandling("getRunStart() should throw an AIOoBE " +
1200                 "when run is runCount+1(too large).");
1201         }
1202         catch (ArrayIndexOutOfBoundsException e) {
1203         }
1204         catch (IllegalArgumentException e) {
1205             errorHandling("getRunStart() should not throw an IAE " +
1206                 "but an AIOoBE when run is runCount+1(too large).");
1207         }
1208     }
1209 
testMethod_reorderVisually1()1210     private void testMethod_reorderVisually1() {
1211         System.out.println("*** Test reorderVisually() 1");
1212 
1213         for (int textNo = 0; textNo < data4reorderVisually.length; textNo++) {
1214             Object[] objects = data4reorderVisually[textNo][0];
1215             byte[] levels = getLevels(data4reorderVisually[textNo]);
1216             Object[] expectedObjects = data4reorderVisually[textNo][2];
1217 
1218             Bidi.reorderVisually(levels, 0, objects, 0, objects.length);
1219 
1220             checkResult("textNo=" + textNo + ": reorderVisually(levels=[" +
1221                 toString(levels) + "], objects=[" + toString(objects) + "])",
1222                 expectedObjects, objects);
1223         }
1224     }
1225 
testMethod_reorderVisually2()1226     private void testMethod_reorderVisually2() {
1227         System.out.println("*** Test reorderVisually() 2");
1228 
1229         Object[] objects = data4reorderVisually[0][0];
1230         byte[] levels = getLevels(data4reorderVisually[0]);
1231         int count = objects.length;
1232         int llen = levels.length;
1233         int olen = objects.length;
1234 
1235         try {
1236             Bidi.reorderVisually(null, 0, objects, 0, count);
1237             errorHandling("reorderVisually() should throw a NPE " +
1238                 "when levels is null.");
1239         }
1240         catch (NullPointerException e) {
1241         }
1242 
1243         try {
1244             Bidi.reorderVisually(levels, -1, objects, 0, count);
1245             errorHandling("reorderVisually() should throw an IAE " +
1246                 "when levelStart is -1.");
1247         }
1248         catch (IllegalArgumentException e) {
1249         }
1250         catch (ArrayIndexOutOfBoundsException e) {
1251             errorHandling("reorderVisually() should not throw an AIOoBE " +
1252                 "but an IAE when levelStart is -1.");
1253         }
1254 
1255         try {
1256             Bidi.reorderVisually(levels, llen, objects, 0, count);
1257             errorHandling("reorderVisually() should throw an IAE " +
1258                 "when levelStart is 6(levels.length).");
1259         }
1260         catch (IllegalArgumentException e) {
1261         }
1262         catch (ArrayIndexOutOfBoundsException e) {
1263             errorHandling("reorderVisually() should not throw an AIOoBE " +
1264                 "but an IAE when levelStart is 6(levels.length).");
1265         }
1266 
1267         try {
1268             Bidi.reorderVisually(levels, 0, null, 0, count);
1269             errorHandling("reorderVisually() should throw a NPE" +
1270                 " when objects is null.");
1271         }
1272         catch (NullPointerException e) {
1273         }
1274 
1275         try {
1276             Bidi.reorderVisually(levels, 0, objects, -1, count);
1277             errorHandling("reorderVisually() should throw an IAE" +
1278                 " when objectStart is -1.");
1279         }
1280         catch (IllegalArgumentException e) {
1281         }
1282         catch (ArrayIndexOutOfBoundsException e) {
1283             errorHandling("reorderVisually() should not throw an AIOoBE " +
1284                 "but an IAE when objectStart is -1.");
1285         }
1286 
1287         try {
1288             Bidi.reorderVisually(levels, 0, objects, 6, objects.length);
1289             errorHandling("reorderVisually() should throw an IAE " +
1290                 "when objectStart is 6(objects.length).");
1291         }
1292         catch (IllegalArgumentException e) {
1293         }
1294 
1295         try {
1296             Bidi.reorderVisually(levels, 0, objects, 0, -1);
1297             errorHandling("reorderVisually() should throw an IAE " +
1298                 "when count is -1.");
1299         }
1300         catch (IllegalArgumentException e) {
1301         }
1302         catch (NegativeArraySizeException e) {
1303             errorHandling("reorderVisually() should not throw an NASE " +
1304                 "but an IAE when count is -1.");
1305         }
1306 
1307         try {
1308             Bidi.reorderVisually(levels, 0, objects, 0, count+1);
1309             errorHandling("reorderVisually() should throw an IAE " +
1310                 "when count is 7(objects.length+1).");
1311         }
1312         catch (IllegalArgumentException e) {
1313         }
1314         catch (ArrayIndexOutOfBoundsException e) {
1315             errorHandling("reorderVisually() should not throw an AIOoBE " +
1316                 "but an IAE when count is 7(objects.length+1).");
1317         }
1318 
1319         try {
1320             Bidi.reorderVisually(levels, 0, objects, 0, 0);
1321             checkResult("reorderVisually(count=0)",
1322                 data4reorderVisually[0][0], objects);
1323         }
1324         catch (Exception e) {
1325             errorHandling("reorderVisually() should not throw an exception" +
1326                 " when count is 0.");
1327         }
1328     }
1329 
testMethod_requiresBidi()1330     private void testMethod_requiresBidi() {
1331         System.out.println("*** Test requiresBidi()");
1332 
1333         String paragraph;
1334         char[] text;
1335         Bidi bidi;
1336 
1337         for (int textNo = 0; textNo < data4Constructor2.length; textNo++) {
1338             paragraph = data4Constructor2[textNo][0];
1339             text = paragraph.toCharArray();
1340             boolean rBidi = Bidi.requiresBidi(text, 0, text.length);
1341             if (rBidi != requiresBidi4Constructor2[textNo]) {
1342                 error = true;
1343                 System.err.println("Unexpected requiresBidi() value" +
1344                     " for requiresBidi(\"" + paragraph + "\", " + 0 + ", " +
1345                     text.length + ")." +
1346                     "\n    Expected: " + requiresBidi4Constructor2[textNo] +
1347                     "\n    Got     : " + rBidi);
1348             } else if (verbose) {
1349                 System.out.println("  Okay : requiresBidi() for" +
1350                     " requiresBidi(\"" + paragraph + "\", " + 0 + ", " +
1351                     text.length + ")  Got: " + rBidi);
1352             }
1353         }
1354 
1355         char[] txt = {'A', 'B', 'C', 'D', 'E'};
1356         int textLength = txt.length;
1357 
1358         try {
1359             Bidi.requiresBidi(txt, -1, textLength);
1360             errorHandling("requiresBidi() should throw an IAE" +
1361                 " when start is -1(too small).");
1362         }
1363         catch (IllegalArgumentException e) {
1364         }
1365         catch (ArrayIndexOutOfBoundsException e) {
1366             errorHandling("requiresBidi() should not throw an AIOoBE " +
1367                 "but an IAE when start is -1(too small).");
1368         }
1369 
1370         try {
1371             Bidi.requiresBidi(txt, textLength, textLength);
1372         }
1373         catch (Exception e) {
1374             errorHandling("requiresBidi() should not throw an exception " +
1375                 "when start is textLength.");
1376         }
1377 
1378         try {
1379             Bidi.requiresBidi(txt, textLength+1, textLength);
1380             errorHandling("requiresBidi() should throw an IAE" +
1381                 " when start is textLength+1(too large).");
1382         }
1383         catch (IllegalArgumentException e) {
1384         }
1385 
1386         try {
1387             Bidi.requiresBidi(txt, 0, -1);
1388             errorHandling("requiresBidi() should throw an IAE" +
1389                 " when limit is -1(too small).");
1390         }
1391         catch (IllegalArgumentException e) {
1392         }
1393 
1394         try {
1395             Bidi.requiresBidi(txt, 0, textLength+1);
1396             errorHandling("requiresBidi() should throw an IAE" +
1397                 " when limit is textLength+1(too large).");
1398         }
1399         catch (IllegalArgumentException e) {
1400         }
1401         catch (ArrayIndexOutOfBoundsException e) {
1402             errorHandling("requiresBidi() should not throw an AIOoBE " +
1403                 "but an IAE when limit is textLength+1(too large).");
1404         }
1405     }
1406 
checkResult(String name, int expectedValue, int actualValue)1407     private void checkResult(String name,
1408                              int expectedValue,
1409                              int actualValue) {
1410         if (expectedValue != actualValue) {
1411             errorHandling("Unexpected " + name + " value." +
1412                 " Expected: " + expectedValue + " Got: " + actualValue);
1413         } else if (verbose) {
1414             System.out.println("  Okay : " + name + " = " + actualValue);
1415         }
1416     }
1417 
checkResult(String name, boolean expectedValue, boolean actualValue)1418     private void checkResult(String name,
1419                              boolean expectedValue,
1420                              boolean actualValue) {
1421         if (expectedValue != actualValue) {
1422             errorHandling("Unexpected " + name + " value." +
1423                 " Expected: " + expectedValue + " Got: " + actualValue);
1424         } else if (verbose) {
1425             System.out.println("  Okay : " + name + " = " + actualValue);
1426         }
1427     }
1428 
checkResult(String name, String expectedValue, String actualValue)1429     private void checkResult(String name,
1430                              String expectedValue,
1431                              String actualValue) {
1432         if (!expectedValue.equals(actualValue)) {
1433             errorHandling("Unexpected " + name + " value." +
1434                 "\n\tExpected: \"" + expectedValue + "\"" +
1435                 "\n\tGot:      \"" + actualValue + "\"");
1436         } else if (verbose) {
1437             System.out.println("  Okay : " + name + " = \"" +
1438                 actualValue + "\"");
1439         }
1440     }
1441 
checkResult(String name, int[] expectedValues, int[] actualValues)1442     private void checkResult(String name,
1443                              int[] expectedValues,
1444                              int[] actualValues) {
1445         if (!Arrays.equals(expectedValues, actualValues)) {
1446             errorHandling("Unexpected " + name + " value." +
1447                 "\n\tExpected: " + toString(expectedValues) + "" +
1448                 "\n\tGot:      " + toString(actualValues) + "");
1449         } else if (verbose) {
1450             System.out.println("  Okay : " + name + " = " +
1451                 toString(actualValues));
1452         }
1453     }
1454 
checkResult(String name, Object[] expectedValues, Object[] actualValues)1455     private void checkResult(String name,
1456                              Object[] expectedValues,
1457                              Object[] actualValues) {
1458         if (!Arrays.equals(expectedValues, actualValues)) {
1459             errorHandling("Unexpected " + name + " value." +
1460                 "\n\tExpected: [" + toString(expectedValues) +
1461                 "]\n\tGot:      [" + toString(actualValues) + "]");
1462         } else if (verbose) {
1463             System.out.println("  Okay : " + name + " Reordered objects = [" +
1464                 toString(actualValues) + "]");
1465         }
1466     }
1467 
errorHandling(String msg)1468     private void errorHandling(String msg) {
1469         if (abort) {
1470             throw new RuntimeException("Error: " + msg);
1471         } else {
1472             error = true;
1473             System.err.println("**Error:" + msg);
1474         }
1475     }
1476 
toString(int[] values)1477     private String toString(int[] values) {
1478         StringBuilder sb = new StringBuilder();
1479         for (int i = 0; i < values.length-1; i++) {
1480             sb.append((int)values[i]);
1481             sb.append(' ');
1482         }
1483         sb.append((int)values[values.length-1]);
1484 
1485         return sb.toString();
1486     }
1487 
toString(byte[] values)1488     private String toString(byte[] values) {
1489         StringBuilder sb = new StringBuilder();
1490         for (int i = 0; i < values.length-1; i++) {
1491             sb.append((byte)values[i]);
1492             sb.append(' ');
1493         }
1494         sb.append((byte)values[values.length-1]);
1495 
1496         return sb.toString();
1497     }
1498 
toString(Object[] values)1499     private String toString(Object[] values) {
1500         StringBuilder sb = new StringBuilder();
1501         String name;
1502 
1503         for (int i = 0; i < values.length-1; i++) {
1504             if ((name = getStringName((String)values[i])) != null) {
1505                 sb.append(name);
1506                 sb.append(", ");
1507             } else {
1508                 sb.append('"');
1509                 sb.append((String)values[i]);
1510                 sb.append("\", ");
1511             }
1512         }
1513         if ((name = getStringName((String)values[values.length-1])) != null) {
1514             sb.append(name);
1515         } else {
1516             sb.append('"');
1517             sb.append((String)values[values.length-1]);
1518             sb.append('\"');
1519         }
1520 
1521         return sb.toString();
1522     }
1523 
getStringName(String str)1524     private String getStringName(String str) {
1525         if (ArabicABC.equals(str)) return "ArabicABC";
1526         else if (Arabic123.equals(str)) return "Arabic123";
1527         else if (PArabicABC.equals(str)) return "ArabicABC(Presentation form)";
1528         else if (HebrewABC.equals(str)) return "HebrewABC";
1529         else if (KharoshthiABC.equals(str)) return "KharoshthiABC(RTL)";
1530         else if (Kharoshthi123.equals(str)) return "Kharoshthi123(RTL)";
1531         else if (NKoABC.equals(str)) return "NKoABC(RTL)";
1532         else if (NKo123.equals(str)) return "NKo123(RTL)";
1533         else if (OsmanyaABC.equals(str)) return "OsmanyaABC(LTR)";
1534         else if (Osmanya123.equals(str)) return "Osmanya123(LTR)";
1535         else return null;
1536     }
1537 
getFlagName(int flag)1538     private String getFlagName(int flag) {
1539         if (flag == -2 || flag == 0x7e) return FLAGNAMES[0];
1540         else if (flag == -1 || flag == 0x7f) return FLAGNAMES[1];
1541         else if (flag == 0) return FLAGNAMES[2];
1542         else if (flag == 1) return FLAGNAMES[3];
1543         else return "Unknown(0x" + Integer.toHexString(flag) + ")";
1544     }
1545 
toReadableString(String str)1546     private String toReadableString(String str) {
1547          String s = str;
1548 
1549          s = s.replaceAll(ArabicABC, "ArabicABC");
1550          s = s.replaceAll(Arabic123, "Arabic123");
1551          s = s.replaceAll(PArabicABC, "ArabicABC(Presentation form)");
1552          s = s.replaceAll(HebrewABC, "HebrewABC");
1553          s = s.replaceAll(KharoshthiABC, "KharoshthiABC");
1554          s = s.replaceAll(Kharoshthi123, "Kharoshthi123");
1555          s = s.replaceAll(NKoABC, "NKoABC");
1556          s = s.replaceAll(NKo123, "NKo123");
1557          s = s.replaceAll(OsmanyaABC, "OsmanyaABC");
1558          s = s.replaceAll(Osmanya123, "Osmanya123");
1559 
1560          return s;
1561     }
1562 
getLevels(Object[][] data)1563     private  byte[] getLevels(Object[][] data) {
1564         int levelLength = data[0].length;
1565         byte[] array = new byte[levelLength];
1566         int textIndex = 0;
1567 
1568         for (int i = 0; i < levelLength; i++) {
1569             array[i] = (byte)(((String)data[1][0]).charAt(textIndex) - '0');
1570             textIndex += ((String)data[0][i]).length();
1571         }
1572 
1573         return array;
1574     }
1575 
1576 
1577     /* Bidi pubilc constants */
1578     private static final int[] FLAGS = {
1579         Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT,  // -2 (0x7e in ICU4J)
1580         Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT,  // -1 (0x7f in ICU4J)
1581         Bidi.DIRECTION_LEFT_TO_RIGHT,          //  0
1582         Bidi.DIRECTION_RIGHT_TO_LEFT           //  1
1583     };
1584 
1585     /* Bidi pubilc constants names */
1586     private static final String[] FLAGNAMES = {
1587         "DIRECTION_DEFAULT_LEFT_TO_RIGHT",  // -2
1588         "DIRECTION_DEFAULT_RIGHT_TO_LEFT",  // -1
1589         "DIRECTION_LEFT_TO_RIGHT",          //  0
1590         "DIRECTION_RIGHT_TO_LEFT",          //  1
1591     };
1592 
1593     /* Bidirectional Character Types */
1594     private static final char L   = '\u200E';
1595     private static final char R   = '\u202F';
1596     private static final char LRE = '\u202A';
1597     private static final char RLE = '\u202B';
1598     private static final char PDF = '\u202C';
1599     private static final char LRO = '\u202D';
1600     private static final char RLO = '\u202E';
1601     private static final char LRI = '\u2066';
1602     private static final char RLI = '\u2067';
1603     private static final char FSI = '\u2068';
1604     private static final char PDI = '\u2069';
1605 
1606     /*
1607      *  0x05D0-0x05EA:   [R]   Hewbrew letters (Strong)
1608      *  0x0627-0x063A:   [AL]  Arabic letters (Strong)
1609      *  0x0660-0x0669:   [AN]  Arabic-Indic digits (Weak)
1610      *  0x07CA-0x07E7:   [R]   NKo letters (Strong)
1611      *  0x07C0-0x07C9:   [R]   NKo digits (Strong)
1612      *  0xFE50-0xFEFF:   [AL]  Arabic presentaion form (Strong)
1613      *  0x10480-0x1049D: [L]   Osmanya letters (Strong)
1614      *  0x104A0-0x104A9: [L]   Osmanya digits (Strong)
1615      *  0x10A10-0x10A33: [R]   Kharoshthi letters (Strong)
1616      *  0x10A40-0x10A43: [R]   Kharoshthi digits (Strong)
1617      *
1618      *  0x200E:          [L]   Left-to-right mark (Implicit, Strong)
1619      *  0x200F:          [R]   Right-to-left mark (Implicit, Strong)
1620      *  0x202A:          [LRE] Left-to-right embedding (Explicit, Strong)
1621      *  0x202B:          [RLE] Right-to-left embedding (Explicit, Strong)
1622      *  0x202C:          [PDF] Pop directional formatting (Explicit, Weak)
1623      *  0x202D:          [LRO] Left-to-right override (Explicit, Strong)
1624      *  0x202E:          [RLO] Right-to-left override (Explicit, Strong)
1625      */
1626 
1627     /* Right-to-left */
1628     private static String ArabicABC = "\u0627\u0628\u0629";
1629     private static String Arabic123 = "\u0661\u0662\u0663";
1630     private static String PArabicABC = "\uFE97\uFE92\uFE8E";
1631     private static String HebrewABC = "\u05D0\u05D1\u05D2";
1632     private static String KharoshthiABC =
1633         new String(Character.toChars(0x10A10)) +
1634         new String(Character.toChars(0x10A11)) +
1635         new String(Character.toChars(0x10A12));
1636     private static String Kharoshthi123 =
1637         new String(Character.toChars(0x10A40)) +
1638         new String(Character.toChars(0x10A41)) +
1639         new String(Character.toChars(0x10A42));
1640     private static String NKoABC = "\u07CA\u07CB\u07CC";
1641     private static String NKo123 = "\u07C1\u07C2\u07C3";
1642 
1643     /* Left-to-right */
1644     private static String OsmanyaABC =
1645         new String(Character.toChars(0x10480)) +
1646         new String(Character.toChars(0x10481)) +
1647         new String(Character.toChars(0x10482));
1648     private static String Osmanya123 =
1649         new String(Character.toChars(0x104A0)) +
1650         new String(Character.toChars(0x104A1)) +
1651         new String(Character.toChars(0x104A2));
1652 
1653     /* --------------------------------------------------------------------- */
1654 
1655     /*
1656      * Test data for Bidi(char[], ...) constructor and methods
1657      */
1658 
1659     /* Text for Bidi processing and its levels */
1660     private static String[][] data4Constructor1 = {
1661         /* For Text #0 */
1662         {"abc <ABC XYZ> xyz.",
1663              "000000000000000000", "000002222222000000", "000000000000000000",
1664              "000003333333000000", "000000000000000000",
1665              "222222222222222221", "222222222222222221", "222222222222222221",
1666              "222113333333112221", "222224444444222221",
1667              "000000000000000000", "000000000000000000", "222222222222222221"},
1668 
1669         /* For Text #1 */
1670         {"ABC <" + HebrewABC + " " + NKo123 + "> XYZ.",
1671              "000001111111000000", "000001111111000000", "000003333333000000",
1672              "000003333333000000", "000000000000000000",
1673              "222111111111112221", "222111111111112221", "222223333333222221",
1674              "222113333333112221", "222224444444222221",
1675              "000001111111000000", "000001111111000000", "222111111111112221"},
1676 
1677         /* For Text #2 */
1678         {NKoABC + " <ABC XYZ> " + NKo123 + ".",
1679              "111000000000001110", "111112222222111110", "111002222222001110",
1680              "111113333333111110", "111004444444001110",
1681              "111112222222111111", "111112222222111111", "111112222222111111",
1682              "111111111111111111", "111114444444111111",
1683              "111112222222111111", "111000000000001110", "111112222222111111"},
1684 
1685         /* For Text #3 */
1686         {HebrewABC + " <" + ArabicABC + " " + Arabic123 + "> " + NKo123 + ".",
1687              "111111111222111110", "111111111222111110", "111003333444001110",
1688              "111113333333111110", "111004444444001110",
1689              "111111111222111111", "111111111222111111", "111113333444111111",
1690              "111111111111111111", "111114444444111111",
1691              "111111111222111111", "111111111222111110", "111111111222111111"},
1692 
1693         /* For Text #4 */
1694         {"abc <" + NKoABC + " 123> xyz.",
1695              "000001111222000000", "000001111222000000", "000003333444000000",
1696              "000003333333000000", "000000000000000000",
1697              "222111111222112221", "222111111222112221", "222223333444222221",
1698              "222113333333112221", "222224444444222221",
1699              "000001111222000000", "000001111222000000", "222111111222112221"},
1700 
1701         /* For Text #5 */
1702         {"abc <ABC " + NKo123 + "> xyz.",
1703              "000000000111000000", "000002221111000000", "000002222333000000",
1704              "000003333333000000", "000000000000000000",
1705              "222222221111112221", "222222221111112221", "222222222333222221",
1706              "222113333333112221", "222224444444222221",
1707              "000000000111000000", "000000000111000000", "222222221111112221"},
1708 
1709         /* For Text #6 */
1710         {ArabicABC + " <" + NKoABC + " 123" + "> " + Arabic123 + ".",
1711              "111111111222112220", "111111111222112220", "111003333444002220",
1712              "111113333333112220", "111004444444002220",
1713              "111111111222112221", "111111111222112221", "111113333444112221",
1714              "111113333333112221", "111114444444112221",
1715              "111111111222112221", "111111111222112220", "111111111222112221"},
1716 
1717         /* For Text #7 */
1718         {ArabicABC + " <XYZ " + NKoABC + "> " + Arabic123 + ".",
1719              "111000000111112220", "111112221111112220", "111002222333002220",
1720              "111113333333112220", "111004444444002220",
1721              "111112221111112221", "111112221111112221", "111112222333112221",
1722              "111113333333112221", "111114444444112221",
1723              "111112221111112221", "111000000111112220", "111112221111112221"},
1724 
1725         /* For Text #8 */
1726         {OsmanyaABC + " <" + KharoshthiABC + " " + Kharoshthi123 + "> " +
1727          Osmanya123 + ".",
1728              "000000001111111111111000000000", "000000001111111111111000000000",
1729              "000000003333333333333000000000", "000000003333333333333000000000",
1730              "000000000000000000000000000000",
1731              "222222111111111111111112222221", "222222111111111111111112222221",
1732              "222222223333333333333222222221", "222222113333333333333112222221",
1733              "222222224444444444444222222221",
1734              "000000001111111111111000000000", "000000001111111111111000000000",
1735              "222222111111111111111112222221"},
1736 
1737         /* For Text #9 */
1738         {KharoshthiABC + " <" + OsmanyaABC + " " + Osmanya123 + "> " +
1739          Kharoshthi123 + ".",
1740              "111111000000000000000001111110", "111111112222222222222111111110",
1741              "111111002222222222222001111110", "111111113333333333333111111110",
1742              "111111004444444444444001111110",
1743              "111111112222222222222111111111", "111111112222222222222111111111",
1744              "111111112222222222222111111111", "111111111111111111111111111111",
1745              "111111114444444444444111111111",
1746              "111111112222222222222111111111", "111111000000000000000001111110",
1747              "111111112222222222222111111111"},
1748     };
1749 
1750     /* Golden data for baseIsLeftToRight() results */
1751     private static boolean[][] baseIsLTR4Constructor1 = {
1752         /* For Text #0 */
1753         {true,  true,  true,  true,  true,
1754          false, false, false, false, false,
1755          true,  true,  false},
1756 
1757         /* For Text #1 */
1758         {true,  true,  true,  true,  true,
1759          false, false, false, false, false,
1760          true,  true,  false},
1761 
1762         /* For Text #2 */
1763         {true,  true,  true,  true,  true,
1764          false, false, false, false, false,
1765          false, true,  false},
1766 
1767         /* For Text #3 */
1768         {true,  true,  true,  true,  true,
1769          false, false, false, false, false,
1770          false, true,  false},
1771 
1772         /* For Text #4 */
1773         {true,  true,  true,  true,  true,
1774          false, false, false, false, false,
1775          true,  true,  false},
1776 
1777         /* For Text #5 */
1778         {true,  true,  true,  true,  true,
1779          false, false, false, false, false,
1780          true,  true,  false},
1781 
1782         /* For Text #6 */
1783         {true,  true,  true,  true,  true,
1784          false, false, false, false, false,
1785          false, true,  false},
1786 
1787         /* For Text #7 */
1788         {true,  true,  true,  true,  true,
1789          false, false, false, false, false,
1790          false, true,  false},
1791 
1792         /* For Text #8 */
1793         {true,  true,  true,  true,  true,
1794          false, false, false, false, false,
1795          true,  true,  false},
1796 
1797         /* For Text #9 */
1798         {true,  true,  true,  true,  true,
1799          false, false, false, false, false,
1800          false, true,  false},
1801     };
1802 
1803     /* Golden data for isLeftToRight() & isRightToLeft() results */
1804     private static boolean[][][] isLTR_isRTL4Constructor1 = {
1805         /* For Text #0 */
1806          /* isLeftToRight() results */
1807         {{true,  false, true,  false, true,
1808           false, false, false, false, false,
1809           true,  true,  false},
1810          /* isRightToLeft() results   */
1811          {false, false, false, false, false,
1812           false, false, false, false, false,
1813           false, false, false}},
1814 
1815         /* For Text #1 */
1816          /* isLeftToRight() results */
1817         {{false, false, false, false, true,
1818           false, false, false, false, false,
1819           false, false, false},
1820          /* isRightToLeft() results   */
1821          {false, false, false, false, false,
1822           false, false, false, false, false,
1823           false, false, false}},
1824 
1825         /* For Text #2 */
1826          /* isLeftToRight() results */
1827         {{false, false, false, false, false,
1828           false, false, false, false, false,
1829           false, false, false},
1830          /* isRightToLeft() results   */
1831          {false, false, false, false, false,
1832           false, false, false, true,  false,
1833           false, false, false}},
1834 
1835         /* For Text #3 */
1836          /* isLeftToRight() results */
1837         {{false, false, false, false, false,
1838           false, false, false, false, false,
1839           false, false, false},
1840          /* isRightToLeft() results   */
1841          {false, false, false, false, false,
1842           false, false, false, true,  false,
1843           false, false, false}},
1844 
1845         /* For Text #4 */
1846          /* isLeftToRight() results */
1847         {{false, false, false, false, true,
1848           false, false, false, false, false,
1849           false, false, false},
1850          /* isRightToLeft() results   */
1851          {false, false, false, false, false,
1852           false, false, false, false, false,
1853           false, false, false}},
1854 
1855         /* For Text #5 */
1856          /* isLeftToRight() results */
1857         {{false, false, false, false, true,
1858           false, false, false, false, false,
1859           false, false, false},
1860          /* isRightToLeft() results   */
1861          {false, false, false, false, false,
1862           false, false, false, false, false,
1863           false, false, false}},
1864 
1865         /* For Text #6 */
1866          /* isLeftToRight() results */
1867         {{false, false, false, false, false,
1868           false, false, false, false, false,
1869           false, false, false},
1870          /* isRightToLeft() results   */
1871          {false, false, false, false, false,
1872           false, false, false, false, false,
1873           false, false, false}},
1874 
1875         /* For Text #7 */
1876          /* isLeftToRight() results */
1877         {{false, false, false, false, false,
1878           false, false, false, false, false,
1879           false, false, false},
1880          /* isRightToLeft() results   */
1881          {false, false, false, false, false,
1882           false, false, false, false, false,
1883           false, false, false}},
1884 
1885         /* For Text #8 */
1886          /* isLeftToRight() results */
1887         {{false, false, false, false, true,
1888           false, false, false, false, false,
1889           false, false, false},
1890          /* isRightToLeft() results   */
1891          {false, false, false, false, false,
1892           false, false, false, false, false,
1893           false, false, false}},
1894 
1895         /* For Text #9 */
1896          /* isLeftToRight() results */
1897         {{false, false, false, false, false,
1898           false, false, false, false, false,
1899           false, false, false},
1900          /* isRightToLeft() results   */
1901          {false, false, false, false, false,
1902           false, false, false, true,  false,
1903           false, false, false}},
1904     };
1905 
1906     /* --------------------------------------------------------------------- */
1907 
1908     /*
1909      * Test data for Bidi(String, int) constructor and methods
1910      */
1911 
1912     /* Text for Bidi processing and its levels */
1913     private static String[][] data4Constructor2 = {
1914         /* For Text #0 */
1915         {" ABC 123.",
1916              "000000000", "000000000", "000000000", "122222221"},
1917 
1918         /* For Text #1 */
1919         {" ABC " + HebrewABC + " " + NKo123 + " 123.",
1920              "00000111111112220", "00000111111112220", "00000111111112220",
1921              "12221111111112221"},
1922 
1923         /* For Text #2 */
1924         {" ABC " + ArabicABC + " " + Arabic123 + " 123.",
1925              "00000111122212220", "00000111122212220", "00000111122212220",
1926              "12221111122212221"},
1927 
1928         /* For Text #3 */
1929         {" " + NKoABC + " ABC 123 " + NKo123 + ".",
1930              "11111222222211111", "11111222222211111", "01110000000001110",
1931              "11111222222211111"},
1932 
1933         /* For Text #4 */
1934         {" " + ArabicABC + " ABC 123 " + Arabic123 + ".",
1935              "11111222222212221", "11111222222212221", "01110000000002220",
1936              "11111222222212221"},
1937 
1938         /* For Text #5 */
1939         {" " + HebrewABC + " " + NKo123 + ".",
1940              "111111111", "111111111", "011111110", "111111111"},
1941 
1942         /* For Text #6 */
1943         {" " + ArabicABC + " " + Arabic123 + ".",
1944              "111112221", "111112221", "011112220", "111112221"},
1945 
1946         /* For Text #7 */
1947         {" " + KharoshthiABC + " " + Kharoshthi123 + ".",
1948              "111111111111111", "111111111111111", "011111111111110",
1949              "111111111111111"},
1950 
1951         /* For Text #8 */
1952         {L + HebrewABC + " " + NKo123 + ".",
1953              "011111110", "011111110", "011111110", "211111111"},
1954 
1955         /* For Text #9 */
1956         {R + "ABC " + Osmanya123 + ".",
1957              "000000000000", "000000000000", "000000000000", "122222222221"},
1958 
1959         /* For Text #10 */
1960         {"ABC " + PArabicABC + " " + PArabicABC + " 123",
1961              "000011111111222", "000011111111222", "000011111111222",
1962              "222111111111222"},
1963 
1964         /* For Text #11 */
1965         {RLE + "ABC " + HebrewABC + " " + NKo123 + "." + PDF,
1966              "22221111111110", "22221111111110", "22221111111110",
1967              "44443333333331"},
1968 
1969         /* For Text #12 */
1970         {"He said \"" + RLE + "ABC " + HebrewABC + " " + NKo123 + PDF + ".\"",
1971              "000000000222211111111000", "000000000222211111111000",
1972              "000000000222211111111000", "222222211444433333333111"},
1973 
1974         /* For Text #13 */
1975         {LRO + "He said \"" + RLE + "ABC " + NKoABC + " " + NKo123 + PDF +
1976          ".\"" + PDF,
1977              "22222222224444333333332220", "22222222224444333333332220",
1978              "22222222224444333333332220", "22222222224444333333332221"},
1979 
1980         /* For Text #14 */
1981         {LRO + "He said \"" + RLE + "ABC " + HebrewABC + " " + NKo123 + PDF +
1982          ".\"",  // PDF missing
1983              "2222222222444433333333222", "2222222222444433333333222",
1984              "2222222222444433333333222", "2222222222444433333333222"},
1985 
1986         /* For Text #15 */
1987         {"Did you say '" + LRE + "he said \"" + RLE + "ABC " + HebrewABC +
1988          " " + NKo123 + PDF + "\"" + PDF + "'?",
1989              "0000000000000222222222244443333333322000",
1990              "0000000000000222222222244443333333322000",
1991              "0000000000000222222222244443333333322000",
1992              "2222222222222222222222244443333333322111"},
1993 
1994         /* For Text #16 */
1995         {RLO + "Did you say '" + LRE + "he said \"" + RLE + "ABC " +
1996          HebrewABC + " " + NKo123 + PDF + "\"" + PDF + "'?" + PDF,
1997              "111111111111112222222222444433333333221110",
1998              "111111111111112222222222444433333333221110",
1999              "111111111111112222222222444433333333221110",
2000              "333333333333334444444444666655555555443331"},
2001 
2002         /* For Text #17 */
2003         {RLO + "Did you say '" + LRE + "he said \"" + RLE + "ABC " +
2004          HebrewABC + " " + NKo123 + PDF + "\"" + PDF + "'?",  // PDF missing
2005              "11111111111111222222222244443333333322111",
2006              "11111111111111222222222244443333333322111",
2007              "11111111111111222222222244443333333322111",
2008              "33333333333333444444444466665555555544333"},
2009 
2010         /* For Text #18 */
2011         {" ABC (" + ArabicABC + " " + Arabic123 + ") 123.",
2012              "0000001111222002220", "0000001111222002220",
2013              "0000001111222002220", "1222111111222112221"},
2014 
2015         /* For Text #19 */
2016         {" " + HebrewABC + " (ABC 123) " + NKo123 + ".",
2017              "1111112222222111111", "1111112222222111111",
2018              "0111000000000001110", "1111112222222111111"},
2019 
2020         /* For Text #20 */
2021         {" He said \"" + RLE + "ABC " + NKoABC + " " + NKo123 + PDF + ".\" ",
2022              "00000000002222111111110000", "00000000002222111111110000",
2023              "00000000002222111111110000", "12222222114444333333331111"},
2024 
2025         /* For Text #21 */
2026         {" Did you say '" + LRE + "he said \"" + RLE + "ABC " + HebrewABC +
2027          " " + NKo123 + PDF + "\"" + PDF + "'? ",
2028              "000000000000002222222222444433333333220000",
2029              "000000000000002222222222444433333333220000",
2030              "000000000000002222222222444433333333220000",
2031              "122222222222222222222222444433333333221111"},
2032 
2033         /* For Text #22 */
2034         {RLE + OsmanyaABC + " " + KharoshthiABC + " " + Kharoshthi123 + "." +
2035          PDF,
2036              "22222221111111111111110", "22222221111111111111110",
2037              "22222221111111111111110", "44444443333333333333331"},
2038 
2039         /* For Text #23 */
2040         {" ABC (" + Arabic123 + " " + ArabicABC + ") 123.",
2041              "0000002221111002220", "0000002221111002220",
2042              "0000002221111002220", "1222112221111112221"},
2043 
2044         /* For Text #24 */
2045         {" 123 (" + ArabicABC + " " + Arabic123 + ") ABC.",
2046              "1222111111222112221", "1222111111222112221",
2047              "0000001111222000000", "1222111111222112221"},
2048 
2049         /* For Text #25 */
2050         {" 123 (" + Arabic123 + " " + ArabicABC + ") ABC.",
2051              "1222112221111112221", "1222112221111112221",
2052              "0000002221111000000", "1222112221111112221"},
2053 
2054         /* For Text #26 */
2055         {" " + ArabicABC + " (ABC 123) "  + Arabic123 + ".",
2056              "1111112222222112221", "1111112222222112221",
2057              "0111000000000002220", "1111112222222112221"},
2058 
2059         /* For Text #27 */
2060         {" " + ArabicABC + " (123 ABC) "  + Arabic123 + ".",
2061              "1111112221222112221", "1111112221222112221",
2062              "0111002220000002220", "1111112221222112221"},
2063 
2064         /* For Text #28 */
2065         {" " + Arabic123 + " (ABC 123) "  + ArabicABC + ".",
2066              "0222000000000001110", "0222000000000001110",
2067              "0222000000000001110", "1222112222222111111"},
2068 
2069         /* For Text #29 */
2070         {" " + Arabic123 + " (123 ABC) "  + ArabicABC + ".",
2071              "0222000000000001110", "0222000000000001110",
2072              "0222000000000001110", "1222112221222111111"},
2073 
2074         /* For Text #30 */
2075         {RLI + "ABC " + ArabicABC + " " + ArabicABC + "." + PDI,
2076              "02221111111110", "14443333333331",
2077              "02221111111110", "14443333333331"},
2078 
2079         /* For Text #31 */
2080         {"ABC abc \"" + RLI + "IJK " + ArabicABC + " " + ArabicABC + PDI +
2081          ".\" \"" + RLI + ArabicABC + " " + ArabicABC + PDI + ",\" xyz XYZ.",
2082              "0000000000222111111110000001111111000000000000",
2083              "0000000000222111111110000001111111000000000000",
2084              "0000000000222111111110000001111111000000000000",
2085              "2222222222444333333332222223333333222222222221"},
2086 
2087         /* For Text #32 */
2088         {ArabicABC + " " + ArabicABC + " '" + LRI + "abc def \"" + RLI +
2089          "xyz " + ArabicABC + " " + ArabicABC + PDI + "\"" + PDI + "'?",
2090              "111111111122222222224443333333322111",
2091              "111111111122222222224443333333322111",
2092              "111111100022222222224443333333322000",
2093              "111111111122222222224443333333322111"},
2094 
2095         /* For Text #33 */
2096         {FSI + Arabic123 + " ABC " + ArabicABC + " " + ArabicABC + "." + PDI,
2097              "044422222333333320", "144422222333333321",
2098              "044422222333333320", "144422222333333321"},
2099 
2100         /* For Text #34 */
2101         {FSI + "123 ABC " + ArabicABC + " " + ArabicABC + "." + PDI,
2102              "022222222333333320", "122222222333333321",
2103              "022222222333333320", "122222222333333321"},
2104 
2105         /* For Text #35 */
2106         {FSI + "123 " + ArabicABC + " ABC " + ArabicABC + "." + PDI,
2107              "022211111222111110", "144433333444333331",
2108              "022211111222111110", "144433333444333331"},
2109 
2110         /* For Text #36 */
2111         {FSI + Arabic123 + " " + ArabicABC + " ABC " + ArabicABC + "." + PDI,
2112              "022211111222111110", "144433333444333331",
2113              "022211111222111110", "144433333444333331"},
2114 
2115         /* For Text #37 */
2116         {FSI + Arabic123 + " 123." + PDI,
2117              "0444222220", "1444222221", "0444222220", "1444222221"},
2118 
2119         /* For Text #38 */
2120         {FSI + "123 " + Arabic123 + "." + PDI,
2121              "0222244420", "1222244421", "0222244420", "1222244421"},
2122     };
2123 
2124     /* Golden data for baseIsLeftToRight() results */
2125     private static boolean[][] baseIsLTR4Constructor2 = {
2126         /* For Text #0 - $4  */
2127         {true,  true,  true,  false},
2128         {true,  true,  true,  false},
2129         {true,  true,  true,  false},
2130         {false, false, true,  false},
2131         {false, false, true,  false},
2132 
2133         /* For Text #5 - $9  */
2134         {false, false, true,  false},
2135         {false, false, true,  false},
2136         {false, false, true,  false},
2137         {true,  true,  true,  false},
2138         {true,  true,  true,  false},
2139 
2140         /* For Text #10 - $14  */
2141         {true,  true,  true,  false},
2142         {true,  true,  true,  false},
2143         {true,  true,  true,  false},
2144         {true,  true,  true,  false},
2145         {true,  true,  true,  false},
2146 
2147         /* For Text #15 - $19  */
2148         {true,  true,  true,  false},
2149         {true,  true,  true,  false},
2150         {true,  true,  true,  false},
2151         {true,  true,  true,  false},
2152         {false, false, true,  false},
2153 
2154         /* For Text #20 - $24  */
2155         {true,  true,  true,  false},
2156         {true,  true,  true,  false},
2157         {true,  true,  true,  false},
2158         {true,  true,  true,  false},
2159         {false, false, true,  false},
2160 
2161         /* For Text #25 - $29  */
2162         {false, false, true,  false},
2163         {false, false, true,  false},
2164         {false, false, true,  false},
2165         {true,  true,  true,  false},
2166         {true,  true,  true,  false},
2167 
2168         /* For Text #30 - $34  */
2169         {true,  false, true,  false},
2170         {true,  true,  true,  false},
2171         {false, false, true,  false},
2172         {true,  false, true,  false},
2173         {true , false, true,  false},
2174 
2175         /* For Text #35 - $38  */
2176         {true,  false, true,  false},
2177         {true,  false, true,  false},
2178         {true,  false, true,  false},
2179         {true,  false, true,  false},
2180     };
2181 
2182     /* Golden data for isLeftToRight() & isRightToLeft() results */
2183     private static boolean[][][] isLTR_isRTL4Constructor2 = {
2184         /* isLeftToRight() results   &   isRightToLeft() results   */
2185         /* For Text #0 - $4  */
2186         {{true,  true,  true,  false}, {false, false, false, false}},
2187         {{false, false, false, false}, {false, false, false, false}},
2188         {{false, false, false, false}, {false, false, false, false}},
2189         {{false, false, false, false}, {false, false, false, false}},
2190         {{false, false, false, false}, {false, false, false, false}},
2191 
2192         /* For Text #5 - $9  */
2193         {{false, false, false, false}, {true,  true,  false, true }},
2194         {{false, false, false, false}, {false, false, false, false}},
2195         {{false, false, false, false}, {true,  true,  false, true }},
2196         {{false, false, false, false}, {false, false, false, false}},
2197         {{true,  true,  true,  false}, {false, false, false, false}},
2198 
2199         /* For Text #10 - $14  */
2200         {{false, false, false, false}, {false, false, false, false}},
2201         {{false, false, false, false}, {false, false, false, false}},
2202         {{false, false, false, false}, {false, false, false, false}},
2203         {{false, false, false, false}, {false, false, false, false}},
2204         {{false, false, false, false}, {false, false, false, false}},
2205 
2206         /* For Text #15 - $19  */
2207         {{false, false, false, false}, {false, false, false, false}},
2208         {{false, false, false, false}, {false, false, false, false}},
2209         {{false, false, false, false}, {false, false, false, false}},
2210         {{false, false, false, false}, {false, false, false, false}},
2211         {{false, false, false, false}, {false, false, false, false}},
2212 
2213         /* For Text #20 - $24  */
2214         {{false, false, false, false}, {false, false, false, false}},
2215         {{false, false, false, false}, {false, false, false, false}},
2216         {{false, false, false, false}, {false, false, false, false}},
2217         {{false, false, false, false}, {false, false, false, false}},
2218         {{false, false, false, false}, {false, false, false, false}},
2219 
2220         /* For Text #25 - $29  */
2221         {{false, false, false, false}, {false, false, false, false}},
2222         {{false, false, false, false}, {false, false, false, false}},
2223         {{false, false, false, false}, {false, false, false, false}},
2224         {{false, false, false, false}, {false, false, false, false}},
2225         {{false, false, false, false}, {false, false, false, false}},
2226 
2227         /* For Text #30 - $34  */
2228         {{false, false, false, false}, {false, false, false, false}},
2229         {{false, false, false, false}, {false, false, false, false}},
2230         {{false, false, false, false}, {false, false, false, false}},
2231         {{false, false, false, false}, {false, false, false, false}},
2232         {{false, false, false, false}, {false, false, false, false}},
2233 
2234         /* For Text #35 - $37  */
2235         {{false, false, false, false}, {false, false, false, false}},
2236         {{false, false, false, false}, {false, false, false, false}},
2237         {{false, false, false, false}, {false, false, false, false}},
2238         {{false, false, false, false}, {false, false, false, false}},
2239     };
2240 
2241     /* Golden data for requiresBidi() results */
2242     private static boolean[] requiresBidi4Constructor2 = {
2243         /* For Text #0 - $9  */
2244         false, true,  true,  true,  true,
2245         true,  true,  true,  true,  false,
2246 
2247         /* For Text #10 - $19  */
2248         true,  true,  true,  true,  true,
2249         true,  true,  true,  true,  true,
2250 
2251         /* For Text #20 - $29  */
2252         true,  true,  true,  true,  true,
2253         true,  true,  true,  true,  true,
2254 
2255         /* For Text #30 - $37  */
2256         true,  true,  true,  true,  true,
2257         true,  true,  true,  true,
2258     };
2259 
2260     /* --------------------------------------------------------------------- */
2261 
2262     /*
2263      * Test data for Bidi(char[], ...) constructor and methods
2264      */
2265 
2266     /* Enbeddings */
2267     private static byte[][][] emb4Constructor3 = {
2268         /* Embeddings for paragraphs which don't include surrogate pairs. */
2269         {{0, 0, 0, 0, 0,  1,  1,  1,  1,  1,  1,  1, 0, 0, 0, 0, 0, 0},
2270          {0, 0, 0, 0, 0,  2,  2,  2,  2,  2,  2,  2, 0, 0, 0, 0, 0, 0},
2271          {0, 0, 0, 0, 0, -3, -3, -3, -3, -3, -3, -3, 0, 0, 0, 0, 0, 0},
2272          {0, 0, 0, 0, 0, -4, -4, -4, -4, -4, -4, -4, 0, 0, 0, 0, 0, 0}},
2273 
2274         /* Embeddings for paragraphs which include surrogate pairs. */
2275         {{ 0,  0,  0,  0,  0,  0,  0,  0,
2276            1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
2277            0,  0,  0,  0,  0,  0,  0,  0,  0},
2278          { 0,  0,  0,  0,  0,  0,  0,  0,
2279            2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
2280            0,  0,  0,  0,  0,  0,  0,  0,  0},
2281          { 0,  0,  0,  0,  0,  0,  0,  0,
2282           -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,
2283            0,  0,  0,  0,  0,  0,  0,  0,  0},
2284          { 0,  0,  0,  0,  0,  0,  0,  0,
2285           -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4,
2286            0,  0,  0,  0,  0,  0,  0,  0,  0}},
2287     };
2288 
2289     /* Text for Bidi processing and its levels */
2290     private static String[][] data4Constructor3 = {
2291         /* For Text #0 */
2292         {"abc <ABC XYZ> xyz.",
2293              /* DIRECTION_DEFAULT_LEFT_TO_RIGHT */
2294              "000002222222000000", "000000000000000000",
2295              "000003333333000000", "000000000000000000",
2296              /* DIRECTION_DEFAULT_RIGHT_TO_LEFT */
2297              "222222222222222221", "222222222222222221",
2298              "222113333333112221", "222224444444222221",
2299              /* DIRECTION_LEFT_TO_RIGHT */
2300              "000002222222000000", "000000000000000000",
2301              "000003333333000000", "000000000000000000",
2302              /* DIRECTION_RIGHT_TO_LEFT */
2303              "222222222222222221", "222222222222222221",
2304              "222113333333112221", "222224444444222221"},
2305 
2306         /* For Text #1 */
2307         {"ABC <" + HebrewABC + " " + NKo123 + "> XYZ.",
2308              /* DIRECTION_DEFAULT_LEFT_TO_RIGHT */
2309              "000001111111000000", "000003333333000000",
2310              "000003333333000000", "000000000000000000",
2311              /* DIRECTION_DEFAULT_RIGHT_TO_LEFT */
2312              "222111111111112221", "222223333333222221",
2313              "222113333333112221", "222224444444222221",
2314              /* DIRECTION_LEFT_TO_RIGHT */
2315              "000001111111000000", "000003333333000000",
2316              "000003333333000000", "000000000000000000",
2317              /* DIRECTION_RIGHT_TO_LEFT */
2318              "222111111111112221", "222223333333222221",
2319              "222113333333112221", "222224444444222221"},
2320 
2321         /* For Text #2 */
2322         {NKoABC + " <ABC XYZ> " + NKo123 + ".",
2323              /* DIRECTION_DEFAULT_LEFT_TO_RIGHT */
2324              "111112222222111111", "111112222222111111",
2325              "111111111111111111", "111114444444111111",
2326              /* DIRECTION_DEFAULT_RIGHT_TO_LEFT */
2327              "111112222222111111", "111112222222111111",
2328              "111111111111111111", "111114444444111111",
2329              /* DIRECTION_LEFT_TO_RIGHT */
2330              "111112222222111110", "111002222222001110",
2331              "111113333333111110", "111004444444001110",
2332              /* DIRECTION_RIGHT_TO_LEFT */
2333              "111112222222111111", "111112222222111111",
2334              "111111111111111111", "111114444444111111"},
2335 
2336         /* For Text #3 */
2337         {HebrewABC + " <" + ArabicABC + " " + Arabic123 + "> " + NKo123 + ".",
2338              /* DIRECTION_DEFAULT_LEFT_TO_RIGHT */
2339              "111111111222111111", "111113333444111111",
2340              "111111111111111111", "111114444444111111",
2341              /* DIRECTION_DEFAULT_RIGHT_TO_LEFT */
2342              "111111111222111111", "111113333444111111",
2343              "111111111111111111", "111114444444111111",
2344              /* DIRECTION_LEFT_TO_RIGHT */
2345              "111111111222111110", "111003333444001110",
2346              "111113333333111110", "111004444444001110",
2347              /* DIRECTION_RIGHT_TO_LEFT */
2348              "111111111222111111", "111113333444111111",
2349              "111111111111111111", "111114444444111111"},
2350 
2351         /* For Text #4 */
2352         {"abc <123 456> xyz.",
2353              /* DIRECTION_DEFAULT_LEFT_TO_RIGHT */
2354              "000002221222000000", "000000000000000000",
2355              "000003333333000000", "000000000000000000",
2356              /* DIRECTION_DEFAULT_RIGHT_TO_LEFT */
2357              "222222222222222221", "222222222222222221",
2358              "222113333333112221", "222224444444222221",
2359              /* DIRECTION_LEFT_TO_RIGHT */
2360              "000002221222000000", "000000000000000000",
2361              "000003333333000000", "000000000000000000",
2362              /* DIRECTION_RIGHT_TO_LEFT */
2363              "222222222222222221", "222222222222222221",
2364              "222113333333112221", "222224444444222221"},
2365 
2366         /* For Text #5 */
2367         {OsmanyaABC + " <" + KharoshthiABC + " " + Kharoshthi123 + "> " +
2368          Osmanya123 + ".",
2369              /* DIRECTION_DEFAULT_LEFT_TO_RIGHT */
2370              "000000001111111111111000000000", "000000003333333333333000000000",
2371              "000000003333333333333000000000", "000000000000000000000000000000",
2372              /* DIRECTION_DEFAULT_RIGHT_TO_LEFT */
2373              "222222111111111111111112222221", "222222223333333333333222222221",
2374              "222222113333333333333112222221", "222222224444444444444222222221",
2375              /* DIRECTION_LEFT_TO_RIGHT */
2376              "000000001111111111111000000000", "000000003333333333333000000000",
2377              "000000003333333333333000000000", "000000000000000000000000000000",
2378              /* DIRECTION_RIGHT_TO_LEFT */
2379              "222222111111111111111112222221", "222222223333333333333222222221",
2380              "222222113333333333333112222221", "222222224444444444444222222221"},
2381 
2382         /* For Text #6 */
2383         {KharoshthiABC + " <" + OsmanyaABC + " " + Osmanya123 + "> " +
2384          Kharoshthi123 + ".",
2385              /* DIRECTION_DEFAULT_LEFT_TO_RIGHT */
2386              "111111112222222222222111111111", "111111112222222222222111111111",
2387              "111111111111111111111111111111", "111111114444444444444111111111",
2388              /* DIRECTION_DEFAULT_RIGHT_TO_LEFT */
2389              "111111112222222222222111111111", "111111112222222222222111111111",
2390              "111111111111111111111111111111", "111111114444444444444111111111",
2391              /* DIRECTION_LEFT_TO_RIGHT */
2392              "111111112222222222222111111110", "111111002222222222222001111110",
2393              "111111113333333333333111111110", "111111004444444444444001111110",
2394              /* DIRECTION_RIGHT_TO_LEFT */
2395              "111111112222222222222111111111", "111111112222222222222111111111",
2396              "111111111111111111111111111111", "111111114444444444444111111111"},
2397     };
2398 
2399     /* Golden data for baseIsLeftToRight() results */
2400     private static boolean[][] baseIsLTR4Constructor3 = {
2401         /* For Text #0 */
2402         {true,  true,  true,  true,    // DIRECTION_DEFAULT_LEFT_TO_RIGHT
2403          true,  true,  true,  true,    // DIRECTION_DEFAULT_RIGHT_TO_LEFT
2404          true,  true,  true,  true,    // DIRECTION_LEFT_TO_RIGHT
2405          false, false, false, false},  // DIRECTION_RIGHT_TO_LEFT
2406 
2407         /* For Text #1 */
2408         {true,  true,  true,  true,
2409          true,  true,  true,  true,
2410          true,  true,  true,  true,
2411          false, false, false, false},
2412 
2413         /* For Text #2 */
2414         {false, false, false, false,
2415          false, false, false, false,
2416          true,  true,  true,  true,
2417          false, false, false, false},
2418 
2419         /* For Text #3 */
2420         {false, false, false, false,
2421          false, false, false, false,
2422          true,  true,  true,  true,
2423          false, false, false, false},
2424 
2425         /* For Text #4 */
2426         {true,  true,  true,  true,
2427          true,  true,  true,  true,
2428          true,  true,  true,  true,
2429          false, false, false, false},
2430 
2431         /* For Text #5 */
2432         {true,  true,  true,  true,
2433          true,  true,  true,  true,
2434          true,  true,  true,  true,
2435          false, false, false, false},
2436 
2437         /* For Text #6 */
2438         {false, false, false, false,
2439          false, false, false, false,
2440          true,  true,  true,  true,
2441          false, false, false, false},
2442     };
2443 
2444     /* Golden data for isLeftToRight() & isRightToLeft() results */
2445     private static boolean[][][] isLTR_isRTL4Constructor3 = {
2446         /* For Text #0 */
2447          /* isLeftToRight() results */
2448         {{false, true,  false, true,     // DIRECTION_DEFAULT_LEFT_TO_RIGHT
2449           false, false, false, false,    // DIRECTION_DEFAULT_RIGHT_TO_LEFT
2450           false, true,  false, true,     // DIRECTION_LEFT_TO_RIGHT
2451           false, false, false, false},   // DIRECTION_RIGHT_TO_LEFT
2452          /* isRightToLeft() results   */
2453          {false, false, false, false,    // DIRECTION_DEFAULT_LEFT_TO_RIGHT
2454           false, false, false, false,    // DIRECTION_DEFAULT_RIGHT_TO_LEFT
2455           false, false, false, false,    // DIRECTION_LEFT_TO_RIGHT
2456           false, false, false, false}},  // DIRECTION_RIGHT_TO_LEFTT
2457 
2458         /* For Text #1 */
2459          /* isLeftToRight() results */
2460         {{false, false, false, true,
2461           false, false, false, false,
2462           false, false, false, true,
2463           false, false, false, false},
2464          /* isRightToLeft() results   */
2465          {false, false, false, false,
2466           false, false, false, false,
2467           false, false, false, false,
2468           false, false, false, false}},
2469 
2470         /* For Text #2 */
2471          /* isLeftToRight() results */
2472         {{false, false, false, false,
2473           false, false, false, false,
2474           false, false, false, false,
2475           false, false, false, false},
2476          /* isRightToLeft() results   */
2477          {false, false, true,  false,
2478           false, false, true,  false,
2479           false, false, false, false,
2480           false, false, true,  false}},
2481 
2482         /* For Text #3 */
2483          /* isLeftToRight() results */
2484         {{false, false, false, false,
2485           false, false, false, false,
2486           false, false, false, false,
2487           false, false, false, false},
2488          /* isRightToLeft() results   */
2489          {false, false, true,  false,
2490           false, false, true,  false,
2491           false, false, false, false,
2492           false, false, true,  false}},
2493 
2494         /* For Text #4 */
2495          /* isLeftToRight() results */
2496         {{false, true,  false, true,
2497           false, false, false, false,
2498           false, true,  false, true,
2499           false, false, false, false },
2500          /* isRightToLeft() results   */
2501          {false, false, false, false,
2502           false, false, false, false,
2503           false, false, false, false,
2504           false, false, false, false}},
2505 
2506         /* For Text #5 */
2507          /* isLeftToRight() results */
2508         {{false, false, false, true,
2509           false, false, false, false,
2510           false, false, false, true,
2511           false, false, false, false},
2512          /* isRightToLeft() results   */
2513          {false, false, false, false,
2514           false, false, false, false,
2515           false, false, false, false,
2516           false, false, false, false}},
2517 
2518         /* For Text #6 */
2519          /* isLeftToRight() results */
2520         {{false, false, false, false,
2521           false, false, false, false,
2522           false, false, false, false,
2523           false, false, false, false},
2524          /* isRightToLeft() results   */
2525          {false, false, true,  false,
2526           false, false, true,  false,
2527           false, false, false, false,
2528           false, false, true,  false}},
2529     };
2530 
2531     /* --------------------------------------------------------------------- */
2532 
2533     /*
2534      * Test data for reorderVisually() methods
2535      */
2536 
2537     private static Object[][][] data4reorderVisually = {
2538         {{"ABC", " ", "abc", " ", ArabicABC, "."},   // Original text
2539          {"000000001110"},                           // levels
2540          {"ABC", " ", "abc", " ", ArabicABC, "."}},  // Reordered text
2541 
2542         {{"ABC", " ", HebrewABC, " ", NKoABC, "."},
2543          {"222111111111"},
2544          {".", NKoABC, " ", HebrewABC, " ", "ABC"}},
2545 
2546         {{OsmanyaABC, " ", HebrewABC, " ", KharoshthiABC, "."},
2547          {"222222111111111111"},
2548          {".", KharoshthiABC, " ", HebrewABC, " ", OsmanyaABC,}},
2549 
2550         {{"ABC", " ", Osmanya123, " ", "\"", OsmanyaABC, " ", Kharoshthi123,
2551           " ", KharoshthiABC, ".", "\""},
2552          {"0000000000002222221111111111111100"},
2553          {"ABC", " ", Osmanya123, " ", "\"", KharoshthiABC, " ", Kharoshthi123,
2554           " ", OsmanyaABC, ".", "\""}},
2555     };
2556 
2557 }
2558