/* ******************************************************************************* * Copyright (C) 2001-2010, International Business Machines * Corporation and others. All Rights Reserved. ******************************************************************************* */ package com.ibm.icu.dev.test.bidi; import java.util.Arrays; import com.ibm.icu.impl.Utility; import com.ibm.icu.text.Bidi; /** * Regression test for the basic "inverse" Bidi mode. * * ported from C by Lina Kemmel, Matitiahu Allouche */ public class TestInverse extends BidiTest { private int countRoundtrips = 0; private int countNonRoundtrips = 0; static final String[] testCases = { "\u006c\u0061\u0028\u0074\u0069\u006e\u0020\u05d0\u05d1\u0029\u05d2\u05d3", "\u006c\u0061\u0074\u0020\u05d0\u05d1\u05d2\u0020\u0031\u0032\u0033", "\u006c\u0061\u0074\u0020\u05d0\u0028\u05d1\u05d2\u0020\u0031\u0029\u0032\u0033", "\u0031\u0032\u0033\u0020\u05d0\u05d1\u05d2\u0020\u0034\u0035\u0036", "\u0061\u0062\u0020\u0061\u0062\u0020\u0661\u0662" }; public void testInverse() { Bidi bidi; int i; logln("\nEntering TestInverse\n"); bidi = new Bidi(); log("inverse Bidi: testInverse(L) with " + testCases.length + " test cases ---\n"); for(i = 0; i < testCases.length; ++i) { logln("Testing case " + i); _testInverseBidi(bidi, testCases[i], Bidi.DIRECTION_LEFT_TO_RIGHT); } log("inverse Bidi: testInverse(R) with " + testCases.length + " test cases ---\n"); for (i = 0; i < testCases.length; ++i) { logln("Testing case " + i); _testInverseBidi(bidi, testCases[i], Bidi.DIRECTION_RIGHT_TO_LEFT); } _testManyInverseBidi(bidi, Bidi.DIRECTION_LEFT_TO_RIGHT); _testManyInverseBidi(bidi, Bidi.DIRECTION_RIGHT_TO_LEFT); logln("inverse Bidi: rountrips: " + countRoundtrips + " non-roundtrips: " + countNonRoundtrips); _testWriteReverse(); _testManyAddedPoints(); _testMisc(); logln("\nExiting TestInverse\n"); } private static final char[][] repeatSegments = { { 0x61, 0x62 }, /* L */ { 0x5d0, 0x5d1 }, /* R */ { 0x627, 0x628 }, /* AL */ { 0x31, 0x32 }, /* EN */ { 0x661, 0x662 }, /* AN */ { 0x20, 0x20 } /* WS (N) */ }; private static final int COUNT_REPEAT_SEGMENTS = 6; private void _testManyInverseBidi(Bidi bidi, int direction) { char[] text = { 0, 0, 0x20, 0, 0, 0x20, 0, 0 }; int i, j, k; log("inverse Bidi: testManyInverseBiDi(" + (direction == Bidi.DIRECTION_LEFT_TO_RIGHT ? 'L' : 'R') + ") - test permutations of text snippets ---\n"); for (i = 0; i < COUNT_REPEAT_SEGMENTS; ++i) { text[0] = repeatSegments[i][0]; text[1] = repeatSegments[i][1]; for (j = 0; j < COUNT_REPEAT_SEGMENTS; ++j) { text[3] = repeatSegments[j][0]; text[4] = repeatSegments[j][1]; for (k = 0; k < COUNT_REPEAT_SEGMENTS; ++k) { text[6] = repeatSegments[k][0]; text[7] = repeatSegments[k][1]; log("inverse Bidi: testManyInverseBiDi()[" + i + " " + j + " " + k + "]\n"); _testInverseBidi(bidi, new String(text), direction); } } } } private void _testInverseBidi(Bidi bidi, String src, int direction) { String visualLTR, logicalDest, visualDest; try { if (direction == Bidi.DIRECTION_LEFT_TO_RIGHT) { log("inverse Bidi: testInverse(L)\n"); /* convert visual to logical */ bidi.setInverse(true); if (!bidi.isInverse()) { err("Error while doing setInverse(true)\n"); } bidi.setPara(src, Bidi.LTR, null); if (!Arrays.equals(src.toCharArray(), bidi.getText())) { err("Wrong value returned by getText\n"); } if (!src.equals(bidi.getTextAsString())) { err("Wrong value returned by getTextAsString\n"); } logicalDest = bidi.writeReordered(Bidi.DO_MIRRORING | Bidi.INSERT_LRM_FOR_NUMERIC); log(" v "); printUnicode(src.toCharArray(), bidi.getLevels()); log("\n"); /* convert back to visual LTR */ bidi.setInverse(false); if (bidi.isInverse()) { err("Error while doing setInverse(false)\n"); } bidi.setPara(logicalDest, Bidi.LTR, null); visualDest = bidi.writeReordered(Bidi.DO_MIRRORING | Bidi.REMOVE_BIDI_CONTROLS); } else { logln("inverse Bidi: testInverse(R)\n"); /* reverse visual from RTL to LTR */ visualLTR = Bidi.writeReverse(src, 0); log(" vr"); printUnicode(src.toCharArray(), null); log("\n"); /* convert visual RTL to logical */ bidi.setInverse(true); bidi.setPara(visualLTR, Bidi.LTR, null); logicalDest = bidi.writeReordered(Bidi.DO_MIRRORING | Bidi.INSERT_LRM_FOR_NUMERIC); log(" vl"); printUnicode(visualLTR.toCharArray(), bidi.getLevels()); log("\n"); /* convert back to visual RTL */ bidi.setInverse(false); bidi.setPara(logicalDest, Bidi.LTR, null); visualDest = bidi.writeReordered(Bidi.DO_MIRRORING | Bidi.REMOVE_BIDI_CONTROLS | Bidi.OUTPUT_REVERSE); } log(" l "); printUnicode(logicalDest.toCharArray(), bidi.getLevels()); log("\n"); log(" v "); printUnicode(visualDest.toCharArray(), null); log("\n"); } catch (Exception e) { errln("inverse Bidi: *** failed"); visualDest = null; } /* check and print results */ if (src.equals(visualDest)) { ++countRoundtrips; log(" + roundtripped\n"); } else { ++countNonRoundtrips; log(" * did not roundtrip\n"); } } private void _testWriteReverse() { /* U+064e and U+0650 are combining marks (Mn) */ final String forward = "\u200f\u0627\u064e\u0650\u0020\u0028\u0031\u0029", reverseKeepCombining = "\u0029\u0031\u0028\u0020\u0627\u064e\u0650\u200f", reverseRemoveControlsKeepCombiningDoMirror = "\u0028\u0031\u0029\u0020\u0627\u064e\u0650"; String reverse; /* test Bidi.writeReverse() with "interesting" options */ try { reverse = Bidi.writeReverse(forward, Bidi.KEEP_BASE_COMBINING); } catch (Exception e) { errln("Failure in Bidi.writeReverse(KEEP_BASE_COMBINING)"); reverse = null; } assertEquals("\nFailure in " + getClass().toString() + " in Bidi.writeReverse", reverseKeepCombining, reverse, forward, null, "KEEP_BASE_COMBINING", null); try { reverse = Bidi.writeReverse(forward, Bidi.REMOVE_BIDI_CONTROLS | Bidi.DO_MIRRORING | Bidi.KEEP_BASE_COMBINING); } catch (Exception e) { errln("Failure in Bidi.writeReverse(KEEP_BASE_COMBINING)"); } assertEquals("\nFailure in " + getClass().toString() + " in Bidi.writeReverse", reverseRemoveControlsKeepCombiningDoMirror, reverse, forward, null, "REMOVE_BIDI_CONTROLS|DO_MIRRORING|KEEP_BASE_COMBINING", null); } private void printUnicode(char[] chars, byte[] levels) { int i; log("{ "); for (i = 0; i < chars.length; ++i) { log("0x" + Utility.hex(chars[i])); if (levels != null) { log("." + levels[i]); } log(" "); } log(" }"); } private void _testManyAddedPoints() { Bidi bidi = new Bidi(); char[] text = new char[90]; for (int i = 0; i < text.length; i+=3) { text[i] = 'a'; text[i+1] = '\u05d0'; text[i+2] = '3'; } bidi.setReorderingMode(Bidi.REORDER_INVERSE_LIKE_DIRECT); bidi.setReorderingOptions(Bidi.OPTION_INSERT_MARKS); bidi.setPara(text, Bidi.LTR, null); String out = bidi.writeReordered(0); char[] expected = new char[120]; for (int i = 0; i < expected.length; i+=4) { expected[i] = 'a'; expected[i+1] = '\u05d0'; expected[i+2] = '\u200e'; expected[i+3] = '3'; } assertEquals("\nInvalid output with many added points", new String(expected), out); } private void _testMisc() { Bidi bidi = new Bidi(); bidi.setInverse(true); bidi.setPara(" ", Bidi.RTL, null); String out = bidi.writeReordered(Bidi.OUTPUT_REVERSE | Bidi.INSERT_LRM_FOR_NUMERIC); assertEquals("\nInvalid output with RLM at both sides", "\u200f \u200f", out); } public static void main(String[] args) { try { new TestInverse().run(args); } catch (Exception e) { System.out.println(e); } } }