/* * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* * @test * @bug 6850113 8032446 * @summary confirm the behavior of new Bidi implementation. (Backward compatibility) * @modules java.desktop */ import java.awt.font.NumericShaper; import java.awt.font.TextAttribute; import java.text.AttributedString; import java.text.Bidi; import java.util.Arrays; public class BidiConformance { /* internal flags */ private static boolean error = false; private static boolean verbose = false; private static boolean abort = false; private static final byte MAX_EXPLICIT_LEVEL = 125; public static void main(String[] args) { for (int i = 0; i < args.length; i++) { String arg = args[i]; if (arg.equals("-verbose")) { verbose = true; } else if (arg.equals("-abort")) { abort = true; } } BidiConformance bc = new BidiConformance(); bc.test(); if (error) { throw new RuntimeException("Failed."); } else { System.out.println("Passed."); } } private void test() { testConstants(); testConstructors(); testMethods(); testMethods4Constructor1(); // Bidi(AttributedCharacterIterator) testMethods4Constructor2(); // Bidi(String, int) testMethods4Constructor3(); // Bidi(char[], ...) } private void testConstants() { System.out.println("*** Test constants"); checkResult("Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT", -2, Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT); checkResult("Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT", -1, Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT); checkResult("Bidi.DIRECTION_LEFT_TO_RIGHT", 0, Bidi.DIRECTION_LEFT_TO_RIGHT); checkResult("Bidi.DIRECTION_RIGHT_TO_LEFT", 1, Bidi.DIRECTION_RIGHT_TO_LEFT); } private void testConstructors() { System.out.println("*** Test constructors"); testConstructor1(); // Bidi(AttributedCharacterIterator) testConstructor2(); // Bidi(String, int) testConstructor3(); // Bidi(char[], ...) } private void testMethods() { System.out.println("*** Test methods"); testMethod_createLineBidi1(); testMethod_createLineBidi2(); testMethod_getLevelAt(); testMethod_getRunLevel(); testMethod_getRunLimit(); testMethod_getRunStart(); testMethod_reorderVisually1(); testMethod_reorderVisually2(); testMethod_requiresBidi(); } private void testMethods4Constructor1() { System.out.println("*** Test methods for constructor 1"); String paragraph; Bidi bidi; NumericShaper ns = NumericShaper.getShaper(NumericShaper.ARABIC); for (int textNo = 0; textNo < data4Constructor1.length; textNo++) { paragraph = data4Constructor1[textNo][0]; int start = paragraph.indexOf('<')+1; int limit = paragraph.indexOf('>'); int testNo; System.out.println("*** Test textNo=" + textNo + ": Bidi(AttributedCharacterIterator\"" + toReadableString(paragraph) + "\") " + " start=" + start + ", limit=" + limit); // Test 0 testNo = 0; System.out.println(" Test#" + testNo +": RUN_DIRECTION_LTR"); AttributedString astr = new AttributedString(paragraph); astr.addAttribute(TextAttribute.RUN_DIRECTION, TextAttribute.RUN_DIRECTION_LTR); bidi = new Bidi(astr.getIterator()); callTestEachMethod4Constructor1(textNo, testNo, bidi); // Test 1 ++testNo; System.out.println(" Test#" + testNo + ": RUN_DIRECTION_LTR, BIDI_EMBEDDING(1)"); astr = new AttributedString(paragraph); astr.addAttribute(TextAttribute.RUN_DIRECTION, TextAttribute.RUN_DIRECTION_LTR); astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(1), start, limit); bidi = new Bidi(astr.getIterator()); callTestEachMethod4Constructor1(textNo, testNo, bidi); // Test 2 ++testNo; System.out.println(" Test#" + testNo + ": RUN_DIERCTION_LTR, BIDI_EMBEDDING(2)"); astr = new AttributedString(paragraph); astr.addAttribute(TextAttribute.RUN_DIRECTION, TextAttribute.RUN_DIRECTION_LTR); astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(2), start, limit); bidi = new Bidi(astr.getIterator()); callTestEachMethod4Constructor1(textNo, testNo, bidi); // Test 3 ++testNo; System.out.println(" Test#" + testNo + ": RUN_DIRECTIOIN_LTR, BIDI_EMBEDDING(-3)"); astr = new AttributedString(paragraph); astr.addAttribute(TextAttribute.RUN_DIRECTION, TextAttribute.RUN_DIRECTION_LTR); astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(-3), start, limit); bidi = new Bidi(astr.getIterator()); callTestEachMethod4Constructor1(textNo, testNo, bidi); // Test 4 ++testNo; System.out.println(" Test#" + testNo + ": RUN_DIRECTION_LTR, BIDI_EMBEDDING(-4)"); astr = new AttributedString(paragraph); astr.addAttribute(TextAttribute.RUN_DIRECTION, TextAttribute.RUN_DIRECTION_LTR); astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(-4), start, limit); bidi = new Bidi(astr.getIterator()); callTestEachMethod4Constructor1(textNo, testNo, bidi); // Test 5 ++testNo; System.out.println(" Test#" + testNo + ": RUN_DIRECTION_RTL"); astr = new AttributedString(paragraph); astr.addAttribute(TextAttribute.RUN_DIRECTION, TextAttribute.RUN_DIRECTION_RTL); bidi = new Bidi(astr.getIterator()); callTestEachMethod4Constructor1(textNo, testNo, bidi); // Test 6 ++testNo; System.out.println(" Test#" + testNo + ": RUN_DIRECTION_RTL, BIDI_EMBEDDING(1)"); astr = new AttributedString(paragraph); astr.addAttribute(TextAttribute.RUN_DIRECTION, TextAttribute.RUN_DIRECTION_RTL); astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(1), start, limit); try { bidi = new Bidi(astr.getIterator()); callTestEachMethod4Constructor1(textNo, testNo, bidi); } catch (IllegalArgumentException e) { errorHandling(" Unexpected exception: " + e); } // Test 7 ++testNo; System.out.println(" Test#" + testNo + ": RUN_DIRECTION_RTL, BIDI_EMBEDDING(2)"); astr = new AttributedString(paragraph); astr.addAttribute(TextAttribute.RUN_DIRECTION, TextAttribute.RUN_DIRECTION_RTL); astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(2), start, limit); try { bidi = new Bidi(astr.getIterator()); callTestEachMethod4Constructor1(textNo, testNo, bidi); } catch (IllegalArgumentException e) { errorHandling(" Unexpected exception: " + e); } // Test 8 ++testNo; System.out.println(" Test#" + testNo + ": RUN_DIRECTION_RTL, BIDI_EMBEDDING(-3)"); astr = new AttributedString(paragraph); astr.addAttribute(TextAttribute.RUN_DIRECTION, TextAttribute.RUN_DIRECTION_RTL); astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(-3), start, limit); try { bidi = new Bidi(astr.getIterator()); callTestEachMethod4Constructor1(textNo, testNo, bidi); } catch (IllegalArgumentException e) { errorHandling(" Unexpected exception: " + e); } // Test 9 ++testNo; System.out.println(" Test#" + testNo + ": RUN_DIRECTION_RTL, BIDI_EMBEDDING(-4)"); astr = new AttributedString(paragraph); astr.addAttribute(TextAttribute.RUN_DIRECTION, TextAttribute.RUN_DIRECTION_RTL); astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(-4), start, limit); try { bidi = new Bidi(astr.getIterator()); callTestEachMethod4Constructor1(textNo, testNo, bidi); } catch (IllegalArgumentException e) { errorHandling(" Unexpected exception: " + e); } // Test 10 ++testNo; System.out.println(" Test#" + testNo + ": TextAttribute not specified"); astr = new AttributedString(paragraph); bidi = new Bidi(astr.getIterator()); callTestEachMethod4Constructor1(textNo, testNo, bidi); // Test 11 ++testNo; System.out.println(" Test#" + testNo + ": RUN_DIRECTION_LTR, NUMERIC_SHAPING(ARABIC)"); astr = new AttributedString(paragraph); astr.addAttribute(TextAttribute.RUN_DIRECTION, TextAttribute.RUN_DIRECTION_LTR); astr.addAttribute(TextAttribute.NUMERIC_SHAPING, ns); bidi = new Bidi(astr.getIterator()); callTestEachMethod4Constructor1(textNo, testNo, bidi); // Test 12 ++testNo; System.out.println(" Test#" + testNo + ": RUN_DIRECTION_RTL, NUMERIC_SHAPING(ARABIC)"); astr = new AttributedString(paragraph); astr.addAttribute(TextAttribute.RUN_DIRECTION, TextAttribute.RUN_DIRECTION_RTL); astr.addAttribute(TextAttribute.NUMERIC_SHAPING, ns); bidi = new Bidi(astr.getIterator()); callTestEachMethod4Constructor1(textNo, testNo, bidi); } } private void testMethods4Constructor2() { System.out.println("*** Test methods for constructor 2"); String paragraph; Bidi bidi; for (int textNo = 0; textNo < data4Constructor2.length; textNo++) { paragraph = data4Constructor2[textNo][0]; for (int flagNo = 0; flagNo < FLAGS.length; flagNo++) { int flag = FLAGS[flagNo]; System.out.println("*** Test textNo=" + textNo + ": Bidi(\"" + toReadableString(paragraph) + "\", " + getFlagName(flag) + ")"); bidi = new Bidi(paragraph, flag); callTestEachMethod4Constructor2(textNo, flagNo, bidi); } } } private void testMethods4Constructor3() { System.out.println("*** Test methods for constructor 3"); String paragraph; Bidi bidi; for (int textNo = 0; textNo < data4Constructor3.length; textNo++) { paragraph = data4Constructor3[textNo][0]; char[] c = paragraph.toCharArray(); int start = paragraph.indexOf('<')+1; byte[][] embeddings = (c.length < emb4Constructor3[1][0].length) ? emb4Constructor3[0] : emb4Constructor3[1]; for (int flagNo = 0; flagNo < FLAGS.length; flagNo++) { int flag = FLAGS[flagNo]; for (int embNo = 0; embNo < embeddings.length; embNo++) { int dataNo = flagNo * FLAGS.length + embNo; System.out.println("*** Test textNo=" + textNo + ": Bidi(char[]\"" + toReadableString(paragraph) + "\", 0, embeddings={" + toString(embeddings[embNo]) + "}, " + c.length + ", " + getFlagName(flag) + ")" + " dataNo=" + dataNo); try { bidi = new Bidi(c, 0, embeddings[embNo], 0, c.length, flag); callTestEachMethod4Constructor3(textNo, dataNo, bidi); } catch (Exception e) { errorHandling(" Unexpected exception: " + e); } } } } } private void testConstructor1() { Bidi bidi; try { bidi = new Bidi(null); errorHandling("Bidi((AttributedCharacterIterator)null) " + "should throw an IAE."); } catch (IllegalArgumentException e) { } catch (NullPointerException e) { errorHandling("Bidi((AttributedCharacterIterator)null) " + "should not throw an NPE but an IAE."); } String paragraph = data4Constructor1[1][0]; int start = paragraph.indexOf('<')+1; int limit = paragraph.indexOf('>'); AttributedString astr = new AttributedString(paragraph); astr.addAttribute(TextAttribute.RUN_DIRECTION, TextAttribute.RUN_DIRECTION_RTL); astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(-MAX_EXPLICIT_LEVEL), start, limit); try { bidi = new Bidi(astr.getIterator()); for (int i = start; i < limit; i++) { if (bidi.getLevelAt(i) != MAX_EXPLICIT_LEVEL) { errorHandling("Bidi(AttributedCharacterIterator).getLevelAt(" + i + ") should not be " + bidi.getLevelAt(i) + " but MAX_EXPLICIT_LEVEL-1 when BIDI_EMBEDDING is -MAX_EXPLICIT_LEVEL."); } } } catch (Exception e) { errorHandling(" Unexpected exception: " + e); } astr = new AttributedString(paragraph); astr.addAttribute(TextAttribute.RUN_DIRECTION, TextAttribute.RUN_DIRECTION_RTL); astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(-(MAX_EXPLICIT_LEVEL+1)), start, limit); try { bidi = new Bidi(astr.getIterator()); for (int i = start; i < limit; i++) { if (bidi.getLevelAt(i) != 1) { errorHandling("Bidi(AttributedCharacterIterator).getLevelAt() " + "should be 1 when BIDI_EMBEDDING is -(MAX_EXPLICIT_LEVEL+1)."); } } } catch (Exception e) { errorHandling(" Unexpected exception: " + e); } astr = new AttributedString(paragraph); astr.addAttribute(TextAttribute.RUN_DIRECTION, TextAttribute.RUN_DIRECTION_RTL); astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(MAX_EXPLICIT_LEVEL-1), start, limit); try { bidi = new Bidi(astr.getIterator()); for (int i = start; i < limit; i++) { if (bidi.getLevelAt(i) != MAX_EXPLICIT_LEVEL) { errorHandling("Bidi(AttributedCharacterIterator).getLevelAt() " + "should be MAX_EXPLICIT_LEVEL when BIDI_EMBEDDING is MAX_EXPLICIT_LEVEL-1."); } } } catch (Exception e) { errorHandling(" Unexpected exception: " + e); } astr = new AttributedString(paragraph); astr.addAttribute(TextAttribute.RUN_DIRECTION, TextAttribute.RUN_DIRECTION_RTL); astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(MAX_EXPLICIT_LEVEL), start, limit); try { bidi = new Bidi(astr.getIterator()); for (int i = start; i < limit; i++) { if (bidi.getLevelAt(i) != MAX_EXPLICIT_LEVEL) { errorHandling("Bidi(AttributedCharacterIterator).getLevelAt(" + i + ") should not be " + bidi.getLevelAt(i) + " but MAX_EXPLICIT_LEVEL when BIDI_EMBEDDING is MAX_EXPLICIT_LEVEL."); } } } catch (Exception e) { errorHandling(" Unexpected exception: " + e); } astr = new AttributedString(paragraph); astr.addAttribute(TextAttribute.RUN_DIRECTION, TextAttribute.RUN_DIRECTION_RTL); astr.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(MAX_EXPLICIT_LEVEL+1), start, limit); try { bidi = new Bidi(astr.getIterator()); for (int i = start; i < limit; i++) { if (bidi.getLevelAt(i) != 1) { errorHandling("Bidi(AttributedCharacterIterator).getLevelAt(" + i + ") should not be " + bidi.getLevelAt(i) + " but 1 when BIDI_EMBEDDING is MAX_EXPLICIT_LEVEL+1."); } } } catch (Exception e) { errorHandling(" Unexpected exception: " + e); } } private void testConstructor2() { Bidi bidi; try { bidi = new Bidi(null, Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT); errorHandling("Bidi((String)null, DIRECTION_DEFAULT_LEFT_TO_RIGHT)" + " should throw an IAE."); } catch (IllegalArgumentException e) { } catch (NullPointerException e) { errorHandling("Bidi((String)null, DIRECTION_DEFAULT_LEFT_TO_RIGHT) " + "should not throw an NPE but an IAE."); } try { bidi = new Bidi("abc", -3); } catch (Exception e) { errorHandling("Bidi(\"abc\", -3) should not throw an exception: " + e); } try { bidi = new Bidi("abc", 2); } catch (Exception e) { errorHandling("Bidi(\"abc\", 2) should not throw an exception: " + e); } } private void testConstructor3() { char[] text = {'a', 'b', 'c', 'd', 'e'}; byte[] embeddings = {0, 0, 0, 0, 0}; Bidi bidi; try { bidi = new Bidi(null, 0, embeddings, 0, 5, Bidi.DIRECTION_LEFT_TO_RIGHT); errorHandling("Bidi(char[], ...) should throw an IAE " + "when text=null."); } catch (IllegalArgumentException e) { } catch (NullPointerException e) { errorHandling("Bidi(char[], ...) should not throw an NPE " + "but an IAE when text=null."); } try { bidi = new Bidi(text, -1, embeddings, 0, 5, Bidi.DIRECTION_LEFT_TO_RIGHT); errorHandling("Bidi(char[], ...) should throw an IAE " + "when textStart is incorrect(-1: too small)."); } catch (IllegalArgumentException e) { } catch (ArrayIndexOutOfBoundsException e) { errorHandling("Bidi(char[], ...) should not throw an NPE " + "but an IAE when textStart is incorrect(-1: too small)."); } try { bidi = new Bidi(text, 4, embeddings, 0, 2, Bidi.DIRECTION_LEFT_TO_RIGHT); errorHandling("Bidi(char[], ...) should throw an IAE " + "when textStart is incorrect(4: too large)."); } catch (IllegalArgumentException e) { } catch (ArrayIndexOutOfBoundsException e) { errorHandling("Bidi(char[], ...) should not throw an NPE " + "but an IAE when textStart is incorrect(4: too large)."); } byte[] actualLevels = new byte[text.length]; byte[] validEmbeddings1 = {0, -MAX_EXPLICIT_LEVEL, -(MAX_EXPLICIT_LEVEL-1), -2, -1}; byte[] expectedLevels1 = {0, MAX_EXPLICIT_LEVEL, MAX_EXPLICIT_LEVEL-1, 2, 1}; try { bidi = new Bidi(text, 0, validEmbeddings1, 0, 5, Bidi.DIRECTION_LEFT_TO_RIGHT); for (int i = 0; i < text.length; i++) { actualLevels[i] = (byte)bidi.getLevelAt(i); } if (!Arrays.equals(expectedLevels1, actualLevels)) { errorHandling("Bidi(char[], ...).getLevelAt()" + " should be {" + toString(actualLevels) + "} when embeddings are {" + toString(expectedLevels1) + "}."); } } catch (Exception e) { errorHandling("Bidi(char[], ...) should not throw an exception " + "when embeddings is valid(-MAX_EXPLICIT_LEVEL)."); } byte[] validEmbeddings2 = {0, MAX_EXPLICIT_LEVEL, MAX_EXPLICIT_LEVEL-1, 2, 1}; byte[] expectedLevels2 = {0, MAX_EXPLICIT_LEVEL+1, MAX_EXPLICIT_LEVEL-1, 2, 2}; try { bidi = new Bidi(text, 0, validEmbeddings2, 0, 5, Bidi.DIRECTION_LEFT_TO_RIGHT); for (int i = 0; i < text.length; i++) { actualLevels[i] = (byte)bidi.getLevelAt(i); } if (!Arrays.equals(expectedLevels2, actualLevels)) { errorHandling("Bidi(char[], ...).getLevelAt()" + " should be {" + toString(actualLevels) + "} when embeddings are {" + toString(expectedLevels2) + "}."); } } catch (Exception e) { errorHandling("Bidi(char[], ...) should not throw an exception " + "when embeddings is valid(MAX_EXPLICIT_LEVEL)."); } byte[] invalidEmbeddings1 = {0, -(MAX_EXPLICIT_LEVEL+1), 0, 0, 0}; try { bidi = new Bidi(text, 0, invalidEmbeddings1, 0, 5, Bidi.DIRECTION_LEFT_TO_RIGHT); if (bidi.getLevelAt(1) != 0) { errorHandling("Bidi(char[], ...).getLevelAt(1) should be 0 " + "when embeddings[1] is -(MAX_EXPLICIT_LEVEL+1)."); } } catch (Exception e) { errorHandling("Bidi(char[], ...) should not throw an exception " + "even when embeddings includes -(MAX_EXPLICIT_LEVEL+1)."); } byte[] invalidEmbeddings2 = {0, MAX_EXPLICIT_LEVEL+1, 0, 0, 0}; try { bidi = new Bidi(text, 0, invalidEmbeddings2, 0, 5, Bidi.DIRECTION_LEFT_TO_RIGHT); if (bidi.getLevelAt(1) != 0) { errorHandling("Bidi(char[], ...).getLevelAt(1) should be 0 " + "when embeddings[1] is MAX_EXPLICIT_LEVEL+1."); } } catch (Exception e) { errorHandling("Bidi(char[], ...) should not throw an exception " + "even when embeddings includes MAX_EXPLICIT_LEVEL+1."); } try { bidi = new Bidi(text, 0, embeddings, 0, -1, Bidi.DIRECTION_LEFT_TO_RIGHT); errorHandling("Bidi(char[], ...) should throw an IAE " + "when paragraphLength=-1(too small)."); } catch (IllegalArgumentException e) { } catch (NegativeArraySizeException e) { errorHandling("Bidi(char[], ...) should not throw an NASE " + "but an IAE when paragraphLength=-1(too small)."); } try { bidi = new Bidi(text, 0, embeddings, 0, 6, Bidi.DIRECTION_LEFT_TO_RIGHT); errorHandling("Bidi(char[], ...) should throw an IAE " + "when paragraphLength=6(too large)."); } catch (IllegalArgumentException e) { } catch (ArrayIndexOutOfBoundsException e) { errorHandling("Bidi(char[], ...) should not throw an AIOoBE " + "but an IAE when paragraphLength=6(too large)."); } try { bidi = new Bidi(text, 0, embeddings, 0, 4, -3); } catch (Exception e) { errorHandling("Bidi(char[], ...) should not throw an exception " + "even when flag=-3(too small)."); } try { bidi = new Bidi(text, 0, embeddings, 0, 5, 2); } catch (Exception e) { errorHandling("Bidi(char[], ...) should not throw an exception " + "even when flag=2(too large)."); } } private void callTestEachMethod4Constructor1(int textNo, int testNo, Bidi bidi) { testEachMethod(bidi, data4Constructor1[textNo][0], data4Constructor1[textNo][testNo+1], baseIsLTR4Constructor1[textNo][testNo], isLTR_isRTL4Constructor1[textNo][0][testNo], isLTR_isRTL4Constructor1[textNo][1][testNo]); } private void callTestEachMethod4Constructor2(int textNo, int flagNo, Bidi bidi) { testEachMethod(bidi, data4Constructor2[textNo][0], data4Constructor2[textNo][flagNo+1], baseIsLTR4Constructor2[textNo][flagNo], isLTR_isRTL4Constructor2[textNo][0][flagNo], isLTR_isRTL4Constructor2[textNo][1][flagNo]); } private void callTestEachMethod4Constructor3(int textNo, int dataNo, Bidi bidi) { testEachMethod(bidi, data4Constructor3[textNo][0], data4Constructor3[textNo][dataNo+1], baseIsLTR4Constructor3[textNo][dataNo], isLTR_isRTL4Constructor3[textNo][0][dataNo], isLTR_isRTL4Constructor3[textNo][1][dataNo]); } private StringBuilder sb = new StringBuilder(); private void testEachMethod(Bidi bidi, String text, String expectedLevels, boolean expectedBaseIsLTR, boolean expectedIsLTR, boolean expectedIsRTL ) { /* Test baseIsLeftToRight() */ boolean actualBoolean = bidi.baseIsLeftToRight(); checkResult("baseIsLeftToRight()", expectedBaseIsLTR, actualBoolean); /* Test getBaseLevel() */ int expectedInt = (expectedBaseIsLTR) ? 0 : 1; int actualInt = bidi.getBaseLevel(); checkResult("getBaseLevel()", expectedInt, actualInt); /* Test getLength() */ expectedInt = text.length(); actualInt = bidi.getLength(); checkResult("getLength()", expectedInt, actualInt); /* Test getLevelAt() */ sb.setLength(0); for (int i = 0; i < text.length(); i++) { sb.append(bidi.getLevelAt(i)); } checkResult("getLevelAt()", expectedLevels, sb.toString()); /* Test getRunCount() */ expectedInt = getRunCount(expectedLevels); actualInt = bidi.getRunCount(); checkResult("getRunCount()", expectedInt, actualInt); /* Test getRunLevel(), getRunLimit() and getRunStart() */ if (expectedInt == actualInt) { int runCount = expectedInt; int[] expectedRunLevels = getRunLevels_int(runCount, expectedLevels); int[] expectedRunLimits = getRunLimits(runCount, expectedLevels); int[] expectedRunStarts = getRunStarts(runCount, expectedLevels); int[] actualRunLevels = new int[runCount]; int[] actualRunLimits = new int[runCount]; int[] actualRunStarts = new int[runCount]; for (int k = 0; k < runCount; k++) { actualRunLevels[k] = bidi.getRunLevel(k); actualRunLimits[k] = bidi.getRunLimit(k); actualRunStarts[k] = bidi.getRunStart(k); } checkResult("getRunLevel()", expectedRunLevels, actualRunLevels); checkResult("getRunStart()", expectedRunStarts, actualRunStarts); checkResult("getRunLimit()", expectedRunLimits, actualRunLimits); } /* Test isLeftToRight() */ boolean expectedBoolean = expectedIsLTR; actualBoolean = bidi.isLeftToRight(); checkResult("isLeftToRight()", expectedBoolean, actualBoolean); /* Test isMixed() */ expectedBoolean = !(expectedIsLTR || expectedIsRTL); actualBoolean = bidi.isMixed(); checkResult("isMixed()", expectedBoolean, actualBoolean); /* Test isRightToLeft() */ expectedBoolean = expectedIsRTL; actualBoolean = bidi.isRightToLeft(); checkResult("isRightToLeft()", expectedBoolean, actualBoolean); } private int getRunCount(String levels) { int len = levels.length(); char c = levels.charAt(0); int runCount = 1; for (int index = 1; index < len; index++) { if (levels.charAt(index) != c) { runCount++; c = levels.charAt(index); } } return runCount; } private int[] getRunLevels_int(int runCount, String levels) { int[] array = new int[runCount]; int len = levels.length(); char c = levels.charAt(0); int i = 0; array[i++] = c - '0'; for (int index = 1; index < len; index++) { if (levels.charAt(index) != c) { c = levels.charAt(index); array[i++] = c - '0'; } } return array; } private byte[] getRunLevels_byte(int runCount, String levels) { byte[] array = new byte[runCount]; int len = levels.length(); char c = levels.charAt(0); int i = 0; array[i++] = (byte)(c - '0'); for (int index = 1; index < len; index++) { if (levels.charAt(index) != c) { c = levels.charAt(index); array[i++] = (byte)(c - '0'); } } return array; } private int[] getRunLimits(int runCount, String levels) { int[] array = new int[runCount]; int len = levels.length(); char c = levels.charAt(0); int i = 0; for (int index = 1; index < len; index++) { if (levels.charAt(index) != c) { c = levels.charAt(index); array[i++] = index; } } array[i] = len; return array; } private int[] getRunStarts(int runCount, String levels) { int[] array = new int[runCount]; int len = levels.length(); char c = levels.charAt(0); int i = 1; for (int index = 1; index < len; index++) { if (levels.charAt(index) != c) { c = levels.charAt(index); array[i++] = index; } } return array; } private String[] getObjects(int runCount, String text, String levels) { String[] array = new String[runCount]; int[] runLimits = getRunLimits(runCount, levels); int runStart = 0; for (int i = 0; i < runCount; i++) { array[i] = text.substring(runStart, runLimits[i]); runStart = runLimits[i]; } return array; } private void testMethod_createLineBidi1() { System.out.println("*** Test createLineBidi() 1"); String str = " ABC 123. " + HebrewABC + " " + NKo123 + ". ABC 123"; int lineStart = str.indexOf('.') + 2; int lineLimit = str.lastIndexOf('.') + 2; Bidi bidi = new Bidi(str, FLAGS[0]); Bidi lineBidi = bidi.createLineBidi(lineStart, lineLimit); checkResult("getBaseLevel()", bidi.getBaseLevel(), lineBidi.getBaseLevel()); checkResult("getLevelAt(5)", bidi.getLevelAt(lineStart+5), lineBidi.getLevelAt(5)); } private void testMethod_createLineBidi2() { System.out.println("*** Test createLineBidi() 2"); Bidi bidi = new Bidi(data4Constructor1[0][0], FLAGS[0]); int len = data4Constructor1[0][0].length(); try { Bidi lineBidi = bidi.createLineBidi(0, len); } catch (Exception e) { errorHandling("createLineBidi(0, textLength)" + " should not throw an exception."); } try { Bidi lineBidi = bidi.createLineBidi(-1, len); errorHandling("createLineBidi(-1, textLength)" + " should throw an IAE."); } catch (IllegalArgumentException e) { } try { Bidi lineBidi = bidi.createLineBidi(0, len+1); errorHandling("createLineBidi(0, textLength+1)" + " should throw an IAE."); } catch (IllegalArgumentException e) { } } /* * Confirm that getLevelAt() doesn't throw an exception for invalid offset * unlike ICU4J. */ private void testMethod_getLevelAt() { System.out.println("*** Test getLevelAt()"); Bidi bidi = new Bidi(data4Constructor1[1][0], FLAGS[0]); int len = data4Constructor1[1][0].length(); try { int level = bidi.getLevelAt(-1); if (level != bidi.getBaseLevel()) { errorHandling("getLevelAt(-1) returned a wrong level." + " Expected=" + bidi.getBaseLevel() + ", got=" + level); } } catch (Exception e) { errorHandling("getLevelAt(-1) should not throw an exception."); } try { int level = bidi.getLevelAt(len+1); if (level != bidi.getBaseLevel()) { errorHandling("getLevelAt(textLength+1)" + " returned a wrong level." + " Expected=" + bidi.getBaseLevel() + ", got=" + level); } } catch (Exception e) { errorHandling("getLevelAt(-1) should not throw an exception."); } } private void testMethod_getRunLevel() { System.out.println("*** Test getRunLevel()"); String str = "ABC 123"; Bidi bidi = new Bidi(str, Bidi.DIRECTION_LEFT_TO_RIGHT); try { if (bidi.getRunLevel(-1) != 0 || // runCount - 2 (out of range) bidi.getRunLevel(0) != 0 || // runCount - 1 bidi.getRunLevel(1) != 0 || // runCount (out of range) bidi.getRunLevel(2) != 0) { // runCount + 1 (out of range) errorHandling("Incorrect getRunLevel() value(s)."); } } catch (Exception e) { errorHandling("getRunLevel() should not throw an exception: " + e); } str = "ABC " + HebrewABC + " 123"; bidi = new Bidi(str, Bidi.DIRECTION_LEFT_TO_RIGHT); try { if (bidi.getRunLevel(-1) != 0 || // runCount - 4 (out of range) bidi.getRunLevel(0) != 0 || // runCount - 3 bidi.getRunLevel(1) != 1 || // runCount - 2 bidi.getRunLevel(2) != 2 || // runCount - 1 bidi.getRunLevel(3) != 0 || // runCount (out of range) bidi.getRunLevel(4) != 0) { // runCount + 1 (out of range) errorHandling("Incorrect getRunLevel() value(s)."); } } catch (Exception e) { errorHandling("getRunLevel() should not throw an exception: " + e); } str = "ABC"; bidi = new Bidi(str, Bidi.DIRECTION_LEFT_TO_RIGHT); try { if (bidi.getRunLevel(-1) != 0 || // runCount - 2 (out of range) bidi.getRunLevel(0) != 0 || // runCount - 1 bidi.getRunLevel(1) != 0 || // runCount (out of range) bidi.getRunLevel(2) != 0) { // runCount + 1 (out of range) errorHandling("Incorrect getRunLevel() value(s)."); } } catch (Exception e) { errorHandling("getRunLevel() should not throw an exception: " + e); } str = "ABC"; bidi = new Bidi(str, Bidi.DIRECTION_RIGHT_TO_LEFT); try { if (bidi.getRunLevel(-1) != 1 || // runCount - 2 (out of range) bidi.getRunLevel(0) != 2 || // runCount - 1 bidi.getRunLevel(1) != 1 || // runCount (out of range) bidi.getRunLevel(2) != 1) { // runCount + 1 (out of range) errorHandling("Incorrect getRunLevel() value(s)."); } } catch (Exception e) { errorHandling("getRunLevel() should not throw an exception: " + e); } str = "ABC"; bidi = new Bidi(str, Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT); try { if (bidi.getRunLevel(-1) != 0 || // runCount - 2 (out of range) bidi.getRunLevel(0) != 0 || // runCount - 1 bidi.getRunLevel(1) != 0 || // runCount (out of range) bidi.getRunLevel(2) != 0) { // runCount + 1 (out of range) errorHandling("Incorrect getRunLevel() value(s)."); } } catch (Exception e) { errorHandling("getRunLevel() should not throw an exception: " + e); } str = "ABC"; bidi = new Bidi(str, Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT); try { if (bidi.getRunLevel(-1) != 0 || // runCount - 2 (out of range) bidi.getRunLevel(0) != 0 || // runCount - 1 bidi.getRunLevel(1) != 0 || // runCount (out of range) bidi.getRunLevel(2) != 0) { // runCount + 1 (out of range) errorHandling("Incorrect getRunLevel() value(s)."); } } catch (Exception e) { errorHandling("getRunLevel() should not throw an exception: " + e); } str = HebrewABC; bidi = new Bidi(str, Bidi.DIRECTION_LEFT_TO_RIGHT); try { if (bidi.getRunLevel(-1) != 0 || // runCount - 2 (out of range) bidi.getRunLevel(0) != 1 || // runCount - 1 bidi.getRunLevel(1) != 0 || // runCount (out of range) bidi.getRunLevel(2) != 0) { // runCount + 1 (out of range) errorHandling("Incorrect getRunLevel() value(s)."); } } catch (Exception e) { errorHandling("getRunLevel() should not throw an exception: " + e); } str = HebrewABC; bidi = new Bidi(str, Bidi.DIRECTION_RIGHT_TO_LEFT); try { if (bidi.getRunLevel(-1) != 1 || // runCount - 2 (out of range) bidi.getRunLevel(0) != 1 || // runCount - 1 bidi.getRunLevel(1) != 1 || // runCount (out of range) bidi.getRunLevel(2) != 1) { // runCount + 1 (out of range) errorHandling("Incorrect getRunLevel() value(s)."); } } catch (Exception e) { errorHandling("getRunLevel() should not throw an exception: " + e); } str = HebrewABC; bidi = new Bidi(str, Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT); try { if (bidi.getRunLevel(-1) != 1 || // runCount - 2 (out of range) bidi.getRunLevel(0) != 1 || // runCount - 1 bidi.getRunLevel(1) != 1 || // runCount (out of range) bidi.getRunLevel(2) != 1) { // runCount + 1 (out of range) errorHandling("Incorrect getRunLevel() value(s)."); } } catch (Exception e) { errorHandling("getRunLevel() should not throw an exception: " + e); } str = HebrewABC; bidi = new Bidi(str, Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT); try { if (bidi.getRunLevel(-1) != 1 || // runCount - 2 (out of range) bidi.getRunLevel(0) != 1 || // runCount - 1 bidi.getRunLevel(1) != 1 || // runCount (out of range) bidi.getRunLevel(2) != 1) { // runCount + 1 (out of range) errorHandling("Incorrect getRunLevel() value(s)."); } } catch (Exception e) { errorHandling("getRunLevel() should not throw an exception: " + e); } } private void testMethod_getRunLimit() { System.out.println("*** Test getRunLimit()"); String str = "ABC 123"; int length = str.length(); Bidi bidi = new Bidi(str, Bidi.DIRECTION_LEFT_TO_RIGHT); try { if (bidi.getRunLimit(-1) != length || // runCount - 2 bidi.getRunLimit(0) != length || // runCount - 1 bidi.getRunLimit(1) != length || // runCount bidi.getRunLimit(2) != length) { // runCount + 1 errorHandling("getRunLimit() should return " + length + " when getRunCount() is 1."); } } catch (Exception e) { errorHandling("getRunLimit() should not throw an exception " + "when getRunCount() is 1."); } str = "ABC " + ArabicABC + " 123"; length = str.length(); bidi = new Bidi(str, Bidi.DIRECTION_LEFT_TO_RIGHT); try { bidi.getRunLimit(-1); errorHandling("getRunLimit() should throw an AIOoBE " + "when run is -1(too small)."); } catch (ArrayIndexOutOfBoundsException e) { } catch (IllegalArgumentException e) { errorHandling("getRunLimit() should not throw an IAE " + "but an AIOoBE when run is -1(too small)."); } try { bidi.getRunLimit(0); bidi.getRunLimit(1); bidi.getRunLimit(2); } catch (ArrayIndexOutOfBoundsException e) { errorHandling("getRunLimit() should not throw an AIOOBE " + "when run is from 0 to 2(runCount-1)."); } try { bidi.getRunLimit(3); errorHandling("getRunLimit() should throw an AIOoBE " + "when run is 3(same as runCount)."); } catch (ArrayIndexOutOfBoundsException e) { } catch (IllegalArgumentException e) { errorHandling("getRunLimit() should not throw an IAE " + "but an AIOoBE when run is 3(same as runCount)."); } } private void testMethod_getRunStart() { System.out.println("*** Test getRunStart()"); String str = "ABC 123"; int length = str.length(); Bidi bidi = new Bidi(str, Bidi.DIRECTION_LEFT_TO_RIGHT); try { if (bidi.getRunStart(-1) != 0 || // runCount - 2 bidi.getRunStart(0) != 0 || // runCount - 1 bidi.getRunStart(1) != 0 || // runCount bidi.getRunStart(2) != 0) { // runCount + 1 errorHandling("getRunStart() should return 0" + " when getRunCount() is 1."); } } catch (Exception e) { errorHandling("getRunLimit() should not throw an exception" + " when getRunCount() is 1."); } str = "ABC " + NKoABC + " 123"; length = str.length(); bidi = new Bidi(str, Bidi.DIRECTION_LEFT_TO_RIGHT); try { bidi.getRunStart(-1); errorHandling("getRunStart() should throw an AIOoBE" + " when run is -1(too small)."); } catch (ArrayIndexOutOfBoundsException e) { } catch (IllegalArgumentException e) { errorHandling("getRunStart() should not throw an IAE " + "but an AIOoBE when run is -1(too small)."); } try { bidi.getRunStart(0); bidi.getRunStart(1); bidi.getRunStart(2); } catch (ArrayIndexOutOfBoundsException e) { errorHandling("getRunStart() should not throw an AIOOBE " + "when run is from 0 to 2(runCount-1)."); } try { if (bidi.getRunStart(3) != length) { errorHandling("getRunStart() should return " + length + " when run is 3(same as runCount)."); } } catch (Exception e) { errorHandling("getRunStart() should not throw an exception " + "when run is 3(same as runCount)."); } try { bidi.getRunStart(4); errorHandling("getRunStart() should throw an AIOoBE " + "when run is runCount+1(too large)."); } catch (ArrayIndexOutOfBoundsException e) { } catch (IllegalArgumentException e) { errorHandling("getRunStart() should not throw an IAE " + "but an AIOoBE when run is runCount+1(too large)."); } } private void testMethod_reorderVisually1() { System.out.println("*** Test reorderVisually() 1"); for (int textNo = 0; textNo < data4reorderVisually.length; textNo++) { Object[] objects = data4reorderVisually[textNo][0]; byte[] levels = getLevels(data4reorderVisually[textNo]); Object[] expectedObjects = data4reorderVisually[textNo][2]; Bidi.reorderVisually(levels, 0, objects, 0, objects.length); checkResult("textNo=" + textNo + ": reorderVisually(levels=[" + toString(levels) + "], objects=[" + toString(objects) + "])", expectedObjects, objects); } } private void testMethod_reorderVisually2() { System.out.println("*** Test reorderVisually() 2"); Object[] objects = data4reorderVisually[0][0]; byte[] levels = getLevels(data4reorderVisually[0]); int count = objects.length; int llen = levels.length; int olen = objects.length; try { Bidi.reorderVisually(null, 0, objects, 0, count); errorHandling("reorderVisually() should throw a NPE " + "when levels is null."); } catch (NullPointerException e) { } try { Bidi.reorderVisually(levels, -1, objects, 0, count); errorHandling("reorderVisually() should throw an IAE " + "when levelStart is -1."); } catch (IllegalArgumentException e) { } catch (ArrayIndexOutOfBoundsException e) { errorHandling("reorderVisually() should not throw an AIOoBE " + "but an IAE when levelStart is -1."); } try { Bidi.reorderVisually(levels, llen, objects, 0, count); errorHandling("reorderVisually() should throw an IAE " + "when levelStart is 6(levels.length)."); } catch (IllegalArgumentException e) { } catch (ArrayIndexOutOfBoundsException e) { errorHandling("reorderVisually() should not throw an AIOoBE " + "but an IAE when levelStart is 6(levels.length)."); } try { Bidi.reorderVisually(levels, 0, null, 0, count); errorHandling("reorderVisually() should throw a NPE" + " when objects is null."); } catch (NullPointerException e) { } try { Bidi.reorderVisually(levels, 0, objects, -1, count); errorHandling("reorderVisually() should throw an IAE" + " when objectStart is -1."); } catch (IllegalArgumentException e) { } catch (ArrayIndexOutOfBoundsException e) { errorHandling("reorderVisually() should not throw an AIOoBE " + "but an IAE when objectStart is -1."); } try { Bidi.reorderVisually(levels, 0, objects, 6, objects.length); errorHandling("reorderVisually() should throw an IAE " + "when objectStart is 6(objects.length)."); } catch (IllegalArgumentException e) { } try { Bidi.reorderVisually(levels, 0, objects, 0, -1); errorHandling("reorderVisually() should throw an IAE " + "when count is -1."); } catch (IllegalArgumentException e) { } catch (NegativeArraySizeException e) { errorHandling("reorderVisually() should not throw an NASE " + "but an IAE when count is -1."); } try { Bidi.reorderVisually(levels, 0, objects, 0, count+1); errorHandling("reorderVisually() should throw an IAE " + "when count is 7(objects.length+1)."); } catch (IllegalArgumentException e) { } catch (ArrayIndexOutOfBoundsException e) { errorHandling("reorderVisually() should not throw an AIOoBE " + "but an IAE when count is 7(objects.length+1)."); } try { Bidi.reorderVisually(levels, 0, objects, 0, 0); checkResult("reorderVisually(count=0)", data4reorderVisually[0][0], objects); } catch (Exception e) { errorHandling("reorderVisually() should not throw an exception" + " when count is 0."); } } private void testMethod_requiresBidi() { System.out.println("*** Test requiresBidi()"); String paragraph; char[] text; Bidi bidi; for (int textNo = 0; textNo < data4Constructor2.length; textNo++) { paragraph = data4Constructor2[textNo][0]; text = paragraph.toCharArray(); boolean rBidi = Bidi.requiresBidi(text, 0, text.length); if (rBidi != requiresBidi4Constructor2[textNo]) { error = true; System.err.println("Unexpected requiresBidi() value" + " for requiresBidi(\"" + paragraph + "\", " + 0 + ", " + text.length + ")." + "\n Expected: " + requiresBidi4Constructor2[textNo] + "\n Got : " + rBidi); } else if (verbose) { System.out.println(" Okay : requiresBidi() for" + " requiresBidi(\"" + paragraph + "\", " + 0 + ", " + text.length + ") Got: " + rBidi); } } char[] txt = {'A', 'B', 'C', 'D', 'E'}; int textLength = txt.length; try { Bidi.requiresBidi(txt, -1, textLength); errorHandling("requiresBidi() should throw an IAE" + " when start is -1(too small)."); } catch (IllegalArgumentException e) { } catch (ArrayIndexOutOfBoundsException e) { errorHandling("requiresBidi() should not throw an AIOoBE " + "but an IAE when start is -1(too small)."); } try { Bidi.requiresBidi(txt, textLength, textLength); } catch (Exception e) { errorHandling("requiresBidi() should not throw an exception " + "when start is textLength."); } try { Bidi.requiresBidi(txt, textLength+1, textLength); errorHandling("requiresBidi() should throw an IAE" + " when start is textLength+1(too large)."); } catch (IllegalArgumentException e) { } try { Bidi.requiresBidi(txt, 0, -1); errorHandling("requiresBidi() should throw an IAE" + " when limit is -1(too small)."); } catch (IllegalArgumentException e) { } try { Bidi.requiresBidi(txt, 0, textLength+1); errorHandling("requiresBidi() should throw an IAE" + " when limit is textLength+1(too large)."); } catch (IllegalArgumentException e) { } catch (ArrayIndexOutOfBoundsException e) { errorHandling("requiresBidi() should not throw an AIOoBE " + "but an IAE when limit is textLength+1(too large)."); } } private void checkResult(String name, int expectedValue, int actualValue) { if (expectedValue != actualValue) { errorHandling("Unexpected " + name + " value." + " Expected: " + expectedValue + " Got: " + actualValue); } else if (verbose) { System.out.println(" Okay : " + name + " = " + actualValue); } } private void checkResult(String name, boolean expectedValue, boolean actualValue) { if (expectedValue != actualValue) { errorHandling("Unexpected " + name + " value." + " Expected: " + expectedValue + " Got: " + actualValue); } else if (verbose) { System.out.println(" Okay : " + name + " = " + actualValue); } } private void checkResult(String name, String expectedValue, String actualValue) { if (!expectedValue.equals(actualValue)) { errorHandling("Unexpected " + name + " value." + "\n\tExpected: \"" + expectedValue + "\"" + "\n\tGot: \"" + actualValue + "\""); } else if (verbose) { System.out.println(" Okay : " + name + " = \"" + actualValue + "\""); } } private void checkResult(String name, int[] expectedValues, int[] actualValues) { if (!Arrays.equals(expectedValues, actualValues)) { errorHandling("Unexpected " + name + " value." + "\n\tExpected: " + toString(expectedValues) + "" + "\n\tGot: " + toString(actualValues) + ""); } else if (verbose) { System.out.println(" Okay : " + name + " = " + toString(actualValues)); } } private void checkResult(String name, Object[] expectedValues, Object[] actualValues) { if (!Arrays.equals(expectedValues, actualValues)) { errorHandling("Unexpected " + name + " value." + "\n\tExpected: [" + toString(expectedValues) + "]\n\tGot: [" + toString(actualValues) + "]"); } else if (verbose) { System.out.println(" Okay : " + name + " Reordered objects = [" + toString(actualValues) + "]"); } } private void errorHandling(String msg) { if (abort) { throw new RuntimeException("Error: " + msg); } else { error = true; System.err.println("**Error:" + msg); } } private String toString(int[] values) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < values.length-1; i++) { sb.append((int)values[i]); sb.append(' '); } sb.append((int)values[values.length-1]); return sb.toString(); } private String toString(byte[] values) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < values.length-1; i++) { sb.append((byte)values[i]); sb.append(' '); } sb.append((byte)values[values.length-1]); return sb.toString(); } private String toString(Object[] values) { StringBuilder sb = new StringBuilder(); String name; for (int i = 0; i < values.length-1; i++) { if ((name = getStringName((String)values[i])) != null) { sb.append(name); sb.append(", "); } else { sb.append('"'); sb.append((String)values[i]); sb.append("\", "); } } if ((name = getStringName((String)values[values.length-1])) != null) { sb.append(name); } else { sb.append('"'); sb.append((String)values[values.length-1]); sb.append('\"'); } return sb.toString(); } private String getStringName(String str) { if (ArabicABC.equals(str)) return "ArabicABC"; else if (Arabic123.equals(str)) return "Arabic123"; else if (PArabicABC.equals(str)) return "ArabicABC(Presentation form)"; else if (HebrewABC.equals(str)) return "HebrewABC"; else if (KharoshthiABC.equals(str)) return "KharoshthiABC(RTL)"; else if (Kharoshthi123.equals(str)) return "Kharoshthi123(RTL)"; else if (NKoABC.equals(str)) return "NKoABC(RTL)"; else if (NKo123.equals(str)) return "NKo123(RTL)"; else if (OsmanyaABC.equals(str)) return "OsmanyaABC(LTR)"; else if (Osmanya123.equals(str)) return "Osmanya123(LTR)"; else return null; } private String getFlagName(int flag) { if (flag == -2 || flag == 0x7e) return FLAGNAMES[0]; else if (flag == -1 || flag == 0x7f) return FLAGNAMES[1]; else if (flag == 0) return FLAGNAMES[2]; else if (flag == 1) return FLAGNAMES[3]; else return "Unknown(0x" + Integer.toHexString(flag) + ")"; } private String toReadableString(String str) { String s = str; s = s.replaceAll(ArabicABC, "ArabicABC"); s = s.replaceAll(Arabic123, "Arabic123"); s = s.replaceAll(PArabicABC, "ArabicABC(Presentation form)"); s = s.replaceAll(HebrewABC, "HebrewABC"); s = s.replaceAll(KharoshthiABC, "KharoshthiABC"); s = s.replaceAll(Kharoshthi123, "Kharoshthi123"); s = s.replaceAll(NKoABC, "NKoABC"); s = s.replaceAll(NKo123, "NKo123"); s = s.replaceAll(OsmanyaABC, "OsmanyaABC"); s = s.replaceAll(Osmanya123, "Osmanya123"); return s; } private byte[] getLevels(Object[][] data) { int levelLength = data[0].length; byte[] array = new byte[levelLength]; int textIndex = 0; for (int i = 0; i < levelLength; i++) { array[i] = (byte)(((String)data[1][0]).charAt(textIndex) - '0'); textIndex += ((String)data[0][i]).length(); } return array; } /* Bidi pubilc constants */ private static final int[] FLAGS = { Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT, // -2 (0x7e in ICU4J) Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT, // -1 (0x7f in ICU4J) Bidi.DIRECTION_LEFT_TO_RIGHT, // 0 Bidi.DIRECTION_RIGHT_TO_LEFT // 1 }; /* Bidi pubilc constants names */ private static final String[] FLAGNAMES = { "DIRECTION_DEFAULT_LEFT_TO_RIGHT", // -2 "DIRECTION_DEFAULT_RIGHT_TO_LEFT", // -1 "DIRECTION_LEFT_TO_RIGHT", // 0 "DIRECTION_RIGHT_TO_LEFT", // 1 }; /* Bidirectional Character Types */ private static final char L = '\u200E'; private static final char R = '\u202F'; private static final char LRE = '\u202A'; private static final char RLE = '\u202B'; private static final char PDF = '\u202C'; private static final char LRO = '\u202D'; private static final char RLO = '\u202E'; private static final char LRI = '\u2066'; private static final char RLI = '\u2067'; private static final char FSI = '\u2068'; private static final char PDI = '\u2069'; /* * 0x05D0-0x05EA: [R] Hewbrew letters (Strong) * 0x0627-0x063A: [AL] Arabic letters (Strong) * 0x0660-0x0669: [AN] Arabic-Indic digits (Weak) * 0x07CA-0x07E7: [R] NKo letters (Strong) * 0x07C0-0x07C9: [R] NKo digits (Strong) * 0xFE50-0xFEFF: [AL] Arabic presentaion form (Strong) * 0x10480-0x1049D: [L] Osmanya letters (Strong) * 0x104A0-0x104A9: [L] Osmanya digits (Strong) * 0x10A10-0x10A33: [R] Kharoshthi letters (Strong) * 0x10A40-0x10A43: [R] Kharoshthi digits (Strong) * * 0x200E: [L] Left-to-right mark (Implicit, Strong) * 0x200F: [R] Right-to-left mark (Implicit, Strong) * 0x202A: [LRE] Left-to-right embedding (Explicit, Strong) * 0x202B: [RLE] Right-to-left embedding (Explicit, Strong) * 0x202C: [PDF] Pop directional formatting (Explicit, Weak) * 0x202D: [LRO] Left-to-right override (Explicit, Strong) * 0x202E: [RLO] Right-to-left override (Explicit, Strong) */ /* Right-to-left */ private static String ArabicABC = "\u0627\u0628\u0629"; private static String Arabic123 = "\u0661\u0662\u0663"; private static String PArabicABC = "\uFE97\uFE92\uFE8E"; private static String HebrewABC = "\u05D0\u05D1\u05D2"; private static String KharoshthiABC = new String(Character.toChars(0x10A10)) + new String(Character.toChars(0x10A11)) + new String(Character.toChars(0x10A12)); private static String Kharoshthi123 = new String(Character.toChars(0x10A40)) + new String(Character.toChars(0x10A41)) + new String(Character.toChars(0x10A42)); private static String NKoABC = "\u07CA\u07CB\u07CC"; private static String NKo123 = "\u07C1\u07C2\u07C3"; /* Left-to-right */ private static String OsmanyaABC = new String(Character.toChars(0x10480)) + new String(Character.toChars(0x10481)) + new String(Character.toChars(0x10482)); private static String Osmanya123 = new String(Character.toChars(0x104A0)) + new String(Character.toChars(0x104A1)) + new String(Character.toChars(0x104A2)); /* --------------------------------------------------------------------- */ /* * Test data for Bidi(char[], ...) constructor and methods */ /* Text for Bidi processing and its levels */ private static String[][] data4Constructor1 = { /* For Text #0 */ {"abc <ABC XYZ> xyz.", "000000000000000000", "000002222222000000", "000000000000000000", "000003333333000000", "000000000000000000", "222222222222222221", "222222222222222221", "222222222222222221", "222113333333112221", "222224444444222221", "000000000000000000", "000000000000000000", "222222222222222221"}, /* For Text #1 */ {"ABC <" + HebrewABC + " " + NKo123 + "> XYZ.", "000001111111000000", "000001111111000000", "000003333333000000", "000003333333000000", "000000000000000000", "222111111111112221", "222111111111112221", "222223333333222221", "222113333333112221", "222224444444222221", "000001111111000000", "000001111111000000", "222111111111112221"}, /* For Text #2 */ {NKoABC + " <ABC XYZ> " + NKo123 + ".", "111000000000001110", "111112222222111110", "111002222222001110", "111113333333111110", "111004444444001110", "111112222222111111", "111112222222111111", "111112222222111111", "111111111111111111", "111114444444111111", "111112222222111111", "111000000000001110", "111112222222111111"}, /* For Text #3 */ {HebrewABC + " <" + ArabicABC + " " + Arabic123 + "> " + NKo123 + ".", "111111111222111110", "111111111222111110", "111003333444001110", "111113333333111110", "111004444444001110", "111111111222111111", "111111111222111111", "111113333444111111", "111111111111111111", "111114444444111111", "111111111222111111", "111111111222111110", "111111111222111111"}, /* For Text #4 */ {"abc <" + NKoABC + " 123> xyz.", "000001111222000000", "000001111222000000", "000003333444000000", "000003333333000000", "000000000000000000", "222111111222112221", "222111111222112221", "222223333444222221", "222113333333112221", "222224444444222221", "000001111222000000", "000001111222000000", "222111111222112221"}, /* For Text #5 */ {"abc <ABC " + NKo123 + "> xyz.", "000000000111000000", "000002221111000000", "000002222333000000", "000003333333000000", "000000000000000000", "222222221111112221", "222222221111112221", "222222222333222221", "222113333333112221", "222224444444222221", "000000000111000000", "000000000111000000", "222222221111112221"}, /* For Text #6 */ {ArabicABC + " <" + NKoABC + " 123" + "> " + Arabic123 + ".", "111111111222112220", "111111111222112220", "111003333444002220", "111113333333112220", "111004444444002220", "111111111222112221", "111111111222112221", "111113333444112221", "111113333333112221", "111114444444112221", "111111111222112221", "111111111222112220", "111111111222112221"}, /* For Text #7 */ {ArabicABC + " <XYZ " + NKoABC + "> " + Arabic123 + ".", "111000000111112220", "111112221111112220", "111002222333002220", "111113333333112220", "111004444444002220", "111112221111112221", "111112221111112221", "111112222333112221", "111113333333112221", "111114444444112221", "111112221111112221", "111000000111112220", "111112221111112221"}, /* For Text #8 */ {OsmanyaABC + " <" + KharoshthiABC + " " + Kharoshthi123 + "> " + Osmanya123 + ".", "000000001111111111111000000000", "000000001111111111111000000000", "000000003333333333333000000000", "000000003333333333333000000000", "000000000000000000000000000000", "222222111111111111111112222221", "222222111111111111111112222221", "222222223333333333333222222221", "222222113333333333333112222221", "222222224444444444444222222221", "000000001111111111111000000000", "000000001111111111111000000000", "222222111111111111111112222221"}, /* For Text #9 */ {KharoshthiABC + " <" + OsmanyaABC + " " + Osmanya123 + "> " + Kharoshthi123 + ".", "111111000000000000000001111110", "111111112222222222222111111110", "111111002222222222222001111110", "111111113333333333333111111110", "111111004444444444444001111110", "111111112222222222222111111111", "111111112222222222222111111111", "111111112222222222222111111111", "111111111111111111111111111111", "111111114444444444444111111111", "111111112222222222222111111111", "111111000000000000000001111110", "111111112222222222222111111111"}, }; /* Golden data for baseIsLeftToRight() results */ private static boolean[][] baseIsLTR4Constructor1 = { /* For Text #0 */ {true, true, true, true, true, false, false, false, false, false, true, true, false}, /* For Text #1 */ {true, true, true, true, true, false, false, false, false, false, true, true, false}, /* For Text #2 */ {true, true, true, true, true, false, false, false, false, false, false, true, false}, /* For Text #3 */ {true, true, true, true, true, false, false, false, false, false, false, true, false}, /* For Text #4 */ {true, true, true, true, true, false, false, false, false, false, true, true, false}, /* For Text #5 */ {true, true, true, true, true, false, false, false, false, false, true, true, false}, /* For Text #6 */ {true, true, true, true, true, false, false, false, false, false, false, true, false}, /* For Text #7 */ {true, true, true, true, true, false, false, false, false, false, false, true, false}, /* For Text #8 */ {true, true, true, true, true, false, false, false, false, false, true, true, false}, /* For Text #9 */ {true, true, true, true, true, false, false, false, false, false, false, true, false}, }; /* Golden data for isLeftToRight() & isRightToLeft() results */ private static boolean[][][] isLTR_isRTL4Constructor1 = { /* For Text #0 */ /* isLeftToRight() results */ {{true, false, true, false, true, false, false, false, false, false, true, true, false}, /* isRightToLeft() results */ {false, false, false, false, false, false, false, false, false, false, false, false, false}}, /* For Text #1 */ /* isLeftToRight() results */ {{false, false, false, false, true, false, false, false, false, false, false, false, false}, /* isRightToLeft() results */ {false, false, false, false, false, false, false, false, false, false, false, false, false}}, /* For Text #2 */ /* isLeftToRight() results */ {{false, false, false, false, false, false, false, false, false, false, false, false, false}, /* isRightToLeft() results */ {false, false, false, false, false, false, false, false, true, false, false, false, false}}, /* For Text #3 */ /* isLeftToRight() results */ {{false, false, false, false, false, false, false, false, false, false, false, false, false}, /* isRightToLeft() results */ {false, false, false, false, false, false, false, false, true, false, false, false, false}}, /* For Text #4 */ /* isLeftToRight() results */ {{false, false, false, false, true, false, false, false, false, false, false, false, false}, /* isRightToLeft() results */ {false, false, false, false, false, false, false, false, false, false, false, false, false}}, /* For Text #5 */ /* isLeftToRight() results */ {{false, false, false, false, true, false, false, false, false, false, false, false, false}, /* isRightToLeft() results */ {false, false, false, false, false, false, false, false, false, false, false, false, false}}, /* For Text #6 */ /* isLeftToRight() results */ {{false, false, false, false, false, false, false, false, false, false, false, false, false}, /* isRightToLeft() results */ {false, false, false, false, false, false, false, false, false, false, false, false, false}}, /* For Text #7 */ /* isLeftToRight() results */ {{false, false, false, false, false, false, false, false, false, false, false, false, false}, /* isRightToLeft() results */ {false, false, false, false, false, false, false, false, false, false, false, false, false}}, /* For Text #8 */ /* isLeftToRight() results */ {{false, false, false, false, true, false, false, false, false, false, false, false, false}, /* isRightToLeft() results */ {false, false, false, false, false, false, false, false, false, false, false, false, false}}, /* For Text #9 */ /* isLeftToRight() results */ {{false, false, false, false, false, false, false, false, false, false, false, false, false}, /* isRightToLeft() results */ {false, false, false, false, false, false, false, false, true, false, false, false, false}}, }; /* --------------------------------------------------------------------- */ /* * Test data for Bidi(String, int) constructor and methods */ /* Text for Bidi processing and its levels */ private static String[][] data4Constructor2 = { /* For Text #0 */ {" ABC 123.", "000000000", "000000000", "000000000", "122222221"}, /* For Text #1 */ {" ABC " + HebrewABC + " " + NKo123 + " 123.", "00000111111112220", "00000111111112220", "00000111111112220", "12221111111112221"}, /* For Text #2 */ {" ABC " + ArabicABC + " " + Arabic123 + " 123.", "00000111122212220", "00000111122212220", "00000111122212220", "12221111122212221"}, /* For Text #3 */ {" " + NKoABC + " ABC 123 " + NKo123 + ".", "11111222222211111", "11111222222211111", "01110000000001110", "11111222222211111"}, /* For Text #4 */ {" " + ArabicABC + " ABC 123 " + Arabic123 + ".", "11111222222212221", "11111222222212221", "01110000000002220", "11111222222212221"}, /* For Text #5 */ {" " + HebrewABC + " " + NKo123 + ".", "111111111", "111111111", "011111110", "111111111"}, /* For Text #6 */ {" " + ArabicABC + " " + Arabic123 + ".", "111112221", "111112221", "011112220", "111112221"}, /* For Text #7 */ {" " + KharoshthiABC + " " + Kharoshthi123 + ".", "111111111111111", "111111111111111", "011111111111110", "111111111111111"}, /* For Text #8 */ {L + HebrewABC + " " + NKo123 + ".", "011111110", "011111110", "011111110", "211111111"}, /* For Text #9 */ {R + "ABC " + Osmanya123 + ".", "000000000000", "000000000000", "000000000000", "122222222221"}, /* For Text #10 */ {"ABC " + PArabicABC + " " + PArabicABC + " 123", "000011111111222", "000011111111222", "000011111111222", "222111111111222"}, /* For Text #11 */ {RLE + "ABC " + HebrewABC + " " + NKo123 + "." + PDF, "22221111111110", "22221111111110", "22221111111110", "44443333333331"}, /* For Text #12 */ {"He said \"" + RLE + "ABC " + HebrewABC + " " + NKo123 + PDF + ".\"", "000000000222211111111000", "000000000222211111111000", "000000000222211111111000", "222222211444433333333111"}, /* For Text #13 */ {LRO + "He said \"" + RLE + "ABC " + NKoABC + " " + NKo123 + PDF + ".\"" + PDF, "22222222224444333333332220", "22222222224444333333332220", "22222222224444333333332220", "22222222224444333333332221"}, /* For Text #14 */ {LRO + "He said \"" + RLE + "ABC " + HebrewABC + " " + NKo123 + PDF + ".\"", // PDF missing "2222222222444433333333222", "2222222222444433333333222", "2222222222444433333333222", "2222222222444433333333222"}, /* For Text #15 */ {"Did you say '" + LRE + "he said \"" + RLE + "ABC " + HebrewABC + " " + NKo123 + PDF + "\"" + PDF + "'?", "0000000000000222222222244443333333322000", "0000000000000222222222244443333333322000", "0000000000000222222222244443333333322000", "2222222222222222222222244443333333322111"}, /* For Text #16 */ {RLO + "Did you say '" + LRE + "he said \"" + RLE + "ABC " + HebrewABC + " " + NKo123 + PDF + "\"" + PDF + "'?" + PDF, "111111111111112222222222444433333333221110", "111111111111112222222222444433333333221110", "111111111111112222222222444433333333221110", "333333333333334444444444666655555555443331"}, /* For Text #17 */ {RLO + "Did you say '" + LRE + "he said \"" + RLE + "ABC " + HebrewABC + " " + NKo123 + PDF + "\"" + PDF + "'?", // PDF missing "11111111111111222222222244443333333322111", "11111111111111222222222244443333333322111", "11111111111111222222222244443333333322111", "33333333333333444444444466665555555544333"}, /* For Text #18 */ {" ABC (" + ArabicABC + " " + Arabic123 + ") 123.", "0000001111222002220", "0000001111222002220", "0000001111222002220", "1222111111222112221"}, /* For Text #19 */ {" " + HebrewABC + " (ABC 123) " + NKo123 + ".", "1111112222222111111", "1111112222222111111", "0111000000000001110", "1111112222222111111"}, /* For Text #20 */ {" He said \"" + RLE + "ABC " + NKoABC + " " + NKo123 + PDF + ".\" ", "00000000002222111111110000", "00000000002222111111110000", "00000000002222111111110000", "12222222114444333333331111"}, /* For Text #21 */ {" Did you say '" + LRE + "he said \"" + RLE + "ABC " + HebrewABC + " " + NKo123 + PDF + "\"" + PDF + "'? ", "000000000000002222222222444433333333220000", "000000000000002222222222444433333333220000", "000000000000002222222222444433333333220000", "122222222222222222222222444433333333221111"}, /* For Text #22 */ {RLE + OsmanyaABC + " " + KharoshthiABC + " " + Kharoshthi123 + "." + PDF, "22222221111111111111110", "22222221111111111111110", "22222221111111111111110", "44444443333333333333331"}, /* For Text #23 */ {" ABC (" + Arabic123 + " " + ArabicABC + ") 123.", "0000002221111002220", "0000002221111002220", "0000002221111002220", "1222112221111112221"}, /* For Text #24 */ {" 123 (" + ArabicABC + " " + Arabic123 + ") ABC.", "1222111111222112221", "1222111111222112221", "0000001111222000000", "1222111111222112221"}, /* For Text #25 */ {" 123 (" + Arabic123 + " " + ArabicABC + ") ABC.", "1222112221111112221", "1222112221111112221", "0000002221111000000", "1222112221111112221"}, /* For Text #26 */ {" " + ArabicABC + " (ABC 123) " + Arabic123 + ".", "1111112222222112221", "1111112222222112221", "0111000000000002220", "1111112222222112221"}, /* For Text #27 */ {" " + ArabicABC + " (123 ABC) " + Arabic123 + ".", "1111112221222112221", "1111112221222112221", "0111002220000002220", "1111112221222112221"}, /* For Text #28 */ {" " + Arabic123 + " (ABC 123) " + ArabicABC + ".", "0222000000000001110", "0222000000000001110", "0222000000000001110", "1222112222222111111"}, /* For Text #29 */ {" " + Arabic123 + " (123 ABC) " + ArabicABC + ".", "0222000000000001110", "0222000000000001110", "0222000000000001110", "1222112221222111111"}, /* For Text #30 */ {RLI + "ABC " + ArabicABC + " " + ArabicABC + "." + PDI, "02221111111110", "14443333333331", "02221111111110", "14443333333331"}, /* For Text #31 */ {"ABC abc \"" + RLI + "IJK " + ArabicABC + " " + ArabicABC + PDI + ".\" \"" + RLI + ArabicABC + " " + ArabicABC + PDI + ",\" xyz XYZ.", "0000000000222111111110000001111111000000000000", "0000000000222111111110000001111111000000000000", "0000000000222111111110000001111111000000000000", "2222222222444333333332222223333333222222222221"}, /* For Text #32 */ {ArabicABC + " " + ArabicABC + " '" + LRI + "abc def \"" + RLI + "xyz " + ArabicABC + " " + ArabicABC + PDI + "\"" + PDI + "'?", "111111111122222222224443333333322111", "111111111122222222224443333333322111", "111111100022222222224443333333322000", "111111111122222222224443333333322111"}, /* For Text #33 */ {FSI + Arabic123 + " ABC " + ArabicABC + " " + ArabicABC + "." + PDI, "044422222333333320", "144422222333333321", "044422222333333320", "144422222333333321"}, /* For Text #34 */ {FSI + "123 ABC " + ArabicABC + " " + ArabicABC + "." + PDI, "022222222333333320", "122222222333333321", "022222222333333320", "122222222333333321"}, /* For Text #35 */ {FSI + "123 " + ArabicABC + " ABC " + ArabicABC + "." + PDI, "022211111222111110", "144433333444333331", "022211111222111110", "144433333444333331"}, /* For Text #36 */ {FSI + Arabic123 + " " + ArabicABC + " ABC " + ArabicABC + "." + PDI, "022211111222111110", "144433333444333331", "022211111222111110", "144433333444333331"}, /* For Text #37 */ {FSI + Arabic123 + " 123." + PDI, "0444222220", "1444222221", "0444222220", "1444222221"}, /* For Text #38 */ {FSI + "123 " + Arabic123 + "." + PDI, "0222244420", "1222244421", "0222244420", "1222244421"}, }; /* Golden data for baseIsLeftToRight() results */ private static boolean[][] baseIsLTR4Constructor2 = { /* For Text #0 - $4 */ {true, true, true, false}, {true, true, true, false}, {true, true, true, false}, {false, false, true, false}, {false, false, true, false}, /* For Text #5 - $9 */ {false, false, true, false}, {false, false, true, false}, {false, false, true, false}, {true, true, true, false}, {true, true, true, false}, /* For Text #10 - $14 */ {true, true, true, false}, {true, true, true, false}, {true, true, true, false}, {true, true, true, false}, {true, true, true, false}, /* For Text #15 - $19 */ {true, true, true, false}, {true, true, true, false}, {true, true, true, false}, {true, true, true, false}, {false, false, true, false}, /* For Text #20 - $24 */ {true, true, true, false}, {true, true, true, false}, {true, true, true, false}, {true, true, true, false}, {false, false, true, false}, /* For Text #25 - $29 */ {false, false, true, false}, {false, false, true, false}, {false, false, true, false}, {true, true, true, false}, {true, true, true, false}, /* For Text #30 - $34 */ {true, false, true, false}, {true, true, true, false}, {false, false, true, false}, {true, false, true, false}, {true , false, true, false}, /* For Text #35 - $38 */ {true, false, true, false}, {true, false, true, false}, {true, false, true, false}, {true, false, true, false}, }; /* Golden data for isLeftToRight() & isRightToLeft() results */ private static boolean[][][] isLTR_isRTL4Constructor2 = { /* isLeftToRight() results & isRightToLeft() results */ /* For Text #0 - $4 */ {{true, true, true, false}, {false, false, false, false}}, {{false, false, false, false}, {false, false, false, false}}, {{false, false, false, false}, {false, false, false, false}}, {{false, false, false, false}, {false, false, false, false}}, {{false, false, false, false}, {false, false, false, false}}, /* For Text #5 - $9 */ {{false, false, false, false}, {true, true, false, true }}, {{false, false, false, false}, {false, false, false, false}}, {{false, false, false, false}, {true, true, false, true }}, {{false, false, false, false}, {false, false, false, false}}, {{true, true, true, false}, {false, false, false, false}}, /* For Text #10 - $14 */ {{false, false, false, false}, {false, false, false, false}}, {{false, false, false, false}, {false, false, false, false}}, {{false, false, false, false}, {false, false, false, false}}, {{false, false, false, false}, {false, false, false, false}}, {{false, false, false, false}, {false, false, false, false}}, /* For Text #15 - $19 */ {{false, false, false, false}, {false, false, false, false}}, {{false, false, false, false}, {false, false, false, false}}, {{false, false, false, false}, {false, false, false, false}}, {{false, false, false, false}, {false, false, false, false}}, {{false, false, false, false}, {false, false, false, false}}, /* For Text #20 - $24 */ {{false, false, false, false}, {false, false, false, false}}, {{false, false, false, false}, {false, false, false, false}}, {{false, false, false, false}, {false, false, false, false}}, {{false, false, false, false}, {false, false, false, false}}, {{false, false, false, false}, {false, false, false, false}}, /* For Text #25 - $29 */ {{false, false, false, false}, {false, false, false, false}}, {{false, false, false, false}, {false, false, false, false}}, {{false, false, false, false}, {false, false, false, false}}, {{false, false, false, false}, {false, false, false, false}}, {{false, false, false, false}, {false, false, false, false}}, /* For Text #30 - $34 */ {{false, false, false, false}, {false, false, false, false}}, {{false, false, false, false}, {false, false, false, false}}, {{false, false, false, false}, {false, false, false, false}}, {{false, false, false, false}, {false, false, false, false}}, {{false, false, false, false}, {false, false, false, false}}, /* For Text #35 - $37 */ {{false, false, false, false}, {false, false, false, false}}, {{false, false, false, false}, {false, false, false, false}}, {{false, false, false, false}, {false, false, false, false}}, {{false, false, false, false}, {false, false, false, false}}, }; /* Golden data for requiresBidi() results */ private static boolean[] requiresBidi4Constructor2 = { /* For Text #0 - $9 */ false, true, true, true, true, true, true, true, true, false, /* For Text #10 - $19 */ true, true, true, true, true, true, true, true, true, true, /* For Text #20 - $29 */ true, true, true, true, true, true, true, true, true, true, /* For Text #30 - $37 */ true, true, true, true, true, true, true, true, true, }; /* --------------------------------------------------------------------- */ /* * Test data for Bidi(char[], ...) constructor and methods */ /* Enbeddings */ private static byte[][][] emb4Constructor3 = { /* Embeddings for paragraphs which don't include surrogate pairs. */ {{0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, -3, -3, -3, -3, -3, -3, -3, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, -4, -4, -4, -4, -4, -4, -4, 0, 0, 0, 0, 0, 0}}, /* Embeddings for paragraphs which include surrogate pairs. */ {{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, 0, 0, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, 0, 0, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, }; /* Text for Bidi processing and its levels */ private static String[][] data4Constructor3 = { /* For Text #0 */ {"abc <ABC XYZ> xyz.", /* DIRECTION_DEFAULT_LEFT_TO_RIGHT */ "000002222222000000", "000000000000000000", "000003333333000000", "000000000000000000", /* DIRECTION_DEFAULT_RIGHT_TO_LEFT */ "222222222222222221", "222222222222222221", "222113333333112221", "222224444444222221", /* DIRECTION_LEFT_TO_RIGHT */ "000002222222000000", "000000000000000000", "000003333333000000", "000000000000000000", /* DIRECTION_RIGHT_TO_LEFT */ "222222222222222221", "222222222222222221", "222113333333112221", "222224444444222221"}, /* For Text #1 */ {"ABC <" + HebrewABC + " " + NKo123 + "> XYZ.", /* DIRECTION_DEFAULT_LEFT_TO_RIGHT */ "000001111111000000", "000003333333000000", "000003333333000000", "000000000000000000", /* DIRECTION_DEFAULT_RIGHT_TO_LEFT */ "222111111111112221", "222223333333222221", "222113333333112221", "222224444444222221", /* DIRECTION_LEFT_TO_RIGHT */ "000001111111000000", "000003333333000000", "000003333333000000", "000000000000000000", /* DIRECTION_RIGHT_TO_LEFT */ "222111111111112221", "222223333333222221", "222113333333112221", "222224444444222221"}, /* For Text #2 */ {NKoABC + " <ABC XYZ> " + NKo123 + ".", /* DIRECTION_DEFAULT_LEFT_TO_RIGHT */ "111112222222111111", "111112222222111111", "111111111111111111", "111114444444111111", /* DIRECTION_DEFAULT_RIGHT_TO_LEFT */ "111112222222111111", "111112222222111111", "111111111111111111", "111114444444111111", /* DIRECTION_LEFT_TO_RIGHT */ "111112222222111110", "111002222222001110", "111113333333111110", "111004444444001110", /* DIRECTION_RIGHT_TO_LEFT */ "111112222222111111", "111112222222111111", "111111111111111111", "111114444444111111"}, /* For Text #3 */ {HebrewABC + " <" + ArabicABC + " " + Arabic123 + "> " + NKo123 + ".", /* DIRECTION_DEFAULT_LEFT_TO_RIGHT */ "111111111222111111", "111113333444111111", "111111111111111111", "111114444444111111", /* DIRECTION_DEFAULT_RIGHT_TO_LEFT */ "111111111222111111", "111113333444111111", "111111111111111111", "111114444444111111", /* DIRECTION_LEFT_TO_RIGHT */ "111111111222111110", "111003333444001110", "111113333333111110", "111004444444001110", /* DIRECTION_RIGHT_TO_LEFT */ "111111111222111111", "111113333444111111", "111111111111111111", "111114444444111111"}, /* For Text #4 */ {"abc <123 456> xyz.", /* DIRECTION_DEFAULT_LEFT_TO_RIGHT */ "000002221222000000", "000000000000000000", "000003333333000000", "000000000000000000", /* DIRECTION_DEFAULT_RIGHT_TO_LEFT */ "222222222222222221", "222222222222222221", "222113333333112221", "222224444444222221", /* DIRECTION_LEFT_TO_RIGHT */ "000002221222000000", "000000000000000000", "000003333333000000", "000000000000000000", /* DIRECTION_RIGHT_TO_LEFT */ "222222222222222221", "222222222222222221", "222113333333112221", "222224444444222221"}, /* For Text #5 */ {OsmanyaABC + " <" + KharoshthiABC + " " + Kharoshthi123 + "> " + Osmanya123 + ".", /* DIRECTION_DEFAULT_LEFT_TO_RIGHT */ "000000001111111111111000000000", "000000003333333333333000000000", "000000003333333333333000000000", "000000000000000000000000000000", /* DIRECTION_DEFAULT_RIGHT_TO_LEFT */ "222222111111111111111112222221", "222222223333333333333222222221", "222222113333333333333112222221", "222222224444444444444222222221", /* DIRECTION_LEFT_TO_RIGHT */ "000000001111111111111000000000", "000000003333333333333000000000", "000000003333333333333000000000", "000000000000000000000000000000", /* DIRECTION_RIGHT_TO_LEFT */ "222222111111111111111112222221", "222222223333333333333222222221", "222222113333333333333112222221", "222222224444444444444222222221"}, /* For Text #6 */ {KharoshthiABC + " <" + OsmanyaABC + " " + Osmanya123 + "> " + Kharoshthi123 + ".", /* DIRECTION_DEFAULT_LEFT_TO_RIGHT */ "111111112222222222222111111111", "111111112222222222222111111111", "111111111111111111111111111111", "111111114444444444444111111111", /* DIRECTION_DEFAULT_RIGHT_TO_LEFT */ "111111112222222222222111111111", "111111112222222222222111111111", "111111111111111111111111111111", "111111114444444444444111111111", /* DIRECTION_LEFT_TO_RIGHT */ "111111112222222222222111111110", "111111002222222222222001111110", "111111113333333333333111111110", "111111004444444444444001111110", /* DIRECTION_RIGHT_TO_LEFT */ "111111112222222222222111111111", "111111112222222222222111111111", "111111111111111111111111111111", "111111114444444444444111111111"}, }; /* Golden data for baseIsLeftToRight() results */ private static boolean[][] baseIsLTR4Constructor3 = { /* For Text #0 */ {true, true, true, true, // DIRECTION_DEFAULT_LEFT_TO_RIGHT true, true, true, true, // DIRECTION_DEFAULT_RIGHT_TO_LEFT true, true, true, true, // DIRECTION_LEFT_TO_RIGHT false, false, false, false}, // DIRECTION_RIGHT_TO_LEFT /* For Text #1 */ {true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false}, /* For Text #2 */ {false, false, false, false, false, false, false, false, true, true, true, true, false, false, false, false}, /* For Text #3 */ {false, false, false, false, false, false, false, false, true, true, true, true, false, false, false, false}, /* For Text #4 */ {true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false}, /* For Text #5 */ {true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false}, /* For Text #6 */ {false, false, false, false, false, false, false, false, true, true, true, true, false, false, false, false}, }; /* Golden data for isLeftToRight() & isRightToLeft() results */ private static boolean[][][] isLTR_isRTL4Constructor3 = { /* For Text #0 */ /* isLeftToRight() results */ {{false, true, false, true, // DIRECTION_DEFAULT_LEFT_TO_RIGHT false, false, false, false, // DIRECTION_DEFAULT_RIGHT_TO_LEFT false, true, false, true, // DIRECTION_LEFT_TO_RIGHT false, false, false, false}, // DIRECTION_RIGHT_TO_LEFT /* isRightToLeft() results */ {false, false, false, false, // DIRECTION_DEFAULT_LEFT_TO_RIGHT false, false, false, false, // DIRECTION_DEFAULT_RIGHT_TO_LEFT false, false, false, false, // DIRECTION_LEFT_TO_RIGHT false, false, false, false}}, // DIRECTION_RIGHT_TO_LEFTT /* For Text #1 */ /* isLeftToRight() results */ {{false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false}, /* isRightToLeft() results */ {false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false}}, /* For Text #2 */ /* isLeftToRight() results */ {{false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false}, /* isRightToLeft() results */ {false, false, true, false, false, false, true, false, false, false, false, false, false, false, true, false}}, /* For Text #3 */ /* isLeftToRight() results */ {{false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false}, /* isRightToLeft() results */ {false, false, true, false, false, false, true, false, false, false, false, false, false, false, true, false}}, /* For Text #4 */ /* isLeftToRight() results */ {{false, true, false, true, false, false, false, false, false, true, false, true, false, false, false, false }, /* isRightToLeft() results */ {false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false}}, /* For Text #5 */ /* isLeftToRight() results */ {{false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false}, /* isRightToLeft() results */ {false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false}}, /* For Text #6 */ /* isLeftToRight() results */ {{false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false}, /* isRightToLeft() results */ {false, false, true, false, false, false, true, false, false, false, false, false, false, false, true, false}}, }; /* --------------------------------------------------------------------- */ /* * Test data for reorderVisually() methods */ private static Object[][][] data4reorderVisually = { {{"ABC", " ", "abc", " ", ArabicABC, "."}, // Original text {"000000001110"}, // levels {"ABC", " ", "abc", " ", ArabicABC, "."}}, // Reordered text {{"ABC", " ", HebrewABC, " ", NKoABC, "."}, {"222111111111"}, {".", NKoABC, " ", HebrewABC, " ", "ABC"}}, {{OsmanyaABC, " ", HebrewABC, " ", KharoshthiABC, "."}, {"222222111111111111"}, {".", KharoshthiABC, " ", HebrewABC, " ", OsmanyaABC,}}, {{"ABC", " ", Osmanya123, " ", "\"", OsmanyaABC, " ", Kharoshthi123, " ", KharoshthiABC, ".", "\""}, {"0000000000002222221111111111111100"}, {"ABC", " ", Osmanya123, " ", "\"", KharoshthiABC, " ", Kharoshthi123, " ", OsmanyaABC, ".", "\""}}, }; }