Home | History | Annotate | Download | only in bidi
      1 /*
      2 *******************************************************************************
      3 *   Copyright (C) 2007-2013, International Business Machines
      4 *   Corporation and others.  All Rights Reserved.
      5 *******************************************************************************
      6 */
      7 
      8 package com.ibm.icu.dev.test.bidi;
      9 
     10 import java.util.Arrays;
     11 
     12 import com.ibm.icu.text.Bidi;
     13 import com.ibm.icu.text.BidiRun;
     14 
     15 /**
     16  * Regression test for Bidi class override.
     17  *
     18  * @author Lina Kemmel, Matitiahu Allouche
     19  */
     20 
     21 public class TestBidi extends BidiTest {
     22 
     23     private static final int MAXLEN = 256;
     24     private static final String levelString = "............................";
     25 
     26     public void testBidi() {
     27         Bidi bidi;
     28         Bidi bidiLine;
     29 
     30         logln("\nEntering TestBidi");
     31         bidi = new Bidi(MAXLEN, 0);
     32         bidiLine = new Bidi();
     33 
     34         doTests(bidi, bidiLine, false);
     35         doTests(bidi, bidiLine, true);
     36         doMisc();
     37         logln("\nExiting TestBidi");
     38     }
     39 
     40     private void doTests(Bidi bidi, Bidi bidiLine, boolean countRunsFirst) {
     41         int testNumber;
     42         String string;
     43         int lineStart;
     44         byte paraLevel;
     45         int bidiTestCount = TestData.testCount();
     46 
     47         for (testNumber = 0; testNumber < bidiTestCount; ++testNumber) {
     48             TestData test = TestData.getTestData(testNumber);
     49             string = getStringFromDirProps(test.dirProps);
     50             paraLevel = test.paraLevel;
     51             try {
     52                 bidi.setPara(string, paraLevel, null);
     53                 logln("Bidi.setPara(tests[" + testNumber + "] OK, direction "
     54                         + bidi.getDirection() + " paraLevel "
     55                         + paraLevel);
     56             } catch (Exception e) {
     57                 errln("Bidi.setPara(tests[" + testNumber + "] failed, direction "
     58                         + bidi.getDirection() + " paraLevel "
     59                         + paraLevel);
     60             }
     61             lineStart = test.lineStart;
     62             if (lineStart == -1) {
     63                 doTest(bidi, testNumber, test, 0, countRunsFirst);
     64             } else {
     65                 try {
     66                     bidiLine = bidi.setLine(lineStart, test.lineLimit);
     67                     logln("Bidi.setLine(" + lineStart + ", " + test.lineLimit
     68                             + "), in tests[" + testNumber + "] OK, direction "
     69                             + bidiLine.getDirection() + " paraLevel "
     70                             + bidiLine.getBaseLevel());
     71                     doTest(bidiLine, testNumber, test, lineStart, countRunsFirst);
     72                 } catch (Exception e)  {
     73                     errln("Bidi.setLine(" + lineStart + ", " + test.lineLimit
     74                             + "), in runAll test[" + testNumber + "] failed");
     75                 }
     76                 /* do it again using createLineBidi instead of setLine */
     77                 try {
     78                     bidiLine = bidi.createLineBidi(lineStart, test.lineLimit);
     79                     logln("Bidi.createLineBidi(" + lineStart + ", " + test.lineLimit
     80                             + "), in tests[" + testNumber + "] OK, direction "
     81                             + bidiLine.getDirection() + " paraLevel "
     82                             + bidiLine.getBaseLevel());
     83                     doTest(bidiLine, testNumber, test, lineStart, countRunsFirst);
     84                 } catch (Exception e)  {
     85                     errln("Bidi.createLineBidi(" + lineStart + ", " + test.lineLimit
     86                             + "), in runAll test[" + testNumber + "] failed");
     87                 }
     88             }
     89         }
     90     }
     91 
     92     private void doTest(Bidi bidi, int testNumber, TestData test,
     93                         int lineStart, boolean countRunsFirst) {
     94         short[] dirProps = test.dirProps;
     95         byte[] levels = test.levels;
     96         int[] visualMap = test.visualMap;
     97         int i, len = bidi.getLength(), logicalIndex = -1, runCount = 0;
     98         byte level, level2;
     99 
    100         if (countRunsFirst) {
    101             logln("Calling Bidi.countRuns() first.");
    102             try {
    103                 runCount = bidi.countRuns();
    104             } catch (IllegalStateException e) {
    105                 errln("Bidi.countRuns(test[" + testNumber + "]) failed");
    106             }
    107         } else {
    108             logln("Calling Bidi.getLogicalMap() first.");
    109         }
    110 
    111         _testReordering(bidi, testNumber);
    112 
    113         for (i = 0; i < len; ++i) {
    114             logln(i + "  " + bidi.getLevelAt(i) + "  " + levelString
    115                     + TestData.dirPropNames[dirProps[lineStart + i]] + "  "
    116                     + bidi.getVisualIndex(i));
    117         }
    118 
    119         log("\n-----levels:");
    120         for (i = 0; i < len; ++i) {
    121             if (i > 0) {
    122                 log(",");
    123             }
    124             log(" " + bidi.getLevelAt(i));
    125         }
    126 
    127         log("\n--reordered:");
    128         for (i = 0; i < len; ++i) {
    129             if (i > 0) {
    130                 log(",");
    131             }
    132             log(" " + bidi.getVisualIndex(i));
    133         }
    134         log("\n");
    135 
    136         assertEquals("\nFailure in Bidi.getDirection(test[" + testNumber + "])",
    137                      test.direction, bidi.getDirection());
    138         assertEquals("\nFailure in Bidi.getParaLevel(test[" + testNumber + "])",
    139                      test.resultLevel, bidi.getParaLevel());
    140 
    141         for (i = 0; i < len; ++i) {
    142             assertEquals("\nFailure in Bidi.getLevelAt(" + i +
    143                          ") in test[" + testNumber + "]",
    144                          levels[i], bidi.getLevelAt(i));
    145         }
    146 
    147         for (i = 0; i < len; ++i) {
    148             try {
    149                 logicalIndex = bidi.getVisualIndex(i);
    150             } catch (Throwable th) {
    151                 errln("Bidi.getVisualIndex(" + i + ") in test[" + testNumber
    152                         + "] failed");
    153             }
    154             if(visualMap[i] != logicalIndex) {
    155                 assertEquals("\nFailure in Bidi.getVisualIndex(" + i +
    156                              ") in test[" + testNumber + "])",
    157                              visualMap[i], logicalIndex);
    158             }
    159         }
    160 
    161         if (!countRunsFirst) {
    162             try {
    163                 runCount = bidi.countRuns();
    164             } catch (IllegalStateException e) {
    165                 errln("Bidi.countRuns(test[" + testNumber + "]) failed");
    166             }
    167         }
    168 
    169         BidiRun run;
    170 
    171         for (logicalIndex = 0; logicalIndex < len; ) {
    172             level = bidi.getLevelAt(logicalIndex);
    173             run = bidi.getLogicalRun(logicalIndex);
    174             logicalIndex = run.getLimit();
    175             level2 = run.getEmbeddingLevel();
    176             assertEquals("Logical " + run.toString() +
    177                          " in test[" + testNumber + "]: wrong level",
    178                          level, level2);
    179             if (--runCount < 0) {
    180                 errln("Bidi.getLogicalRun(test[" + testNumber
    181                       + "]): wrong number of runs compared to Bidi.countRuns() = "
    182                       + bidi.countRuns());
    183             }
    184         }
    185         if (runCount != 0) {
    186             errln("Bidi.getLogicalRun(test[" + testNumber
    187                     + "]): wrong number of runs compared to Bidi.countRuns() = "
    188                     + bidi.countRuns());
    189         }
    190 
    191         log("\n\n");
    192     }
    193 
    194     private void _testReordering(Bidi bidi, int testNumber) {
    195         int[] logicalMap1;
    196         int[] logicalMap2;
    197         int[] logicalMap3;
    198         int[] visualMap1;
    199         int[] visualMap2;
    200         int[] visualMap3;
    201         int[] visualMap4 = new int[MAXLEN];
    202         byte[] levels;
    203         int i, length = bidi.getLength(),
    204                destLength = bidi.getResultLength();
    205         int runCount, visualIndex, logicalIndex = -1, logicalStart, runLength;
    206         boolean odd;
    207 
    208         if(length <= 0) {
    209             return;
    210         }
    211         /* get the logical and visual maps from the object */
    212         logicalMap1 = bidi.getLogicalMap();
    213         if (logicalMap1 == null) {
    214             errln("getLogicalMap in test " + testNumber + " is null");
    215             logicalMap1 = new int[0];
    216         }
    217 
    218         visualMap1 = bidi.getVisualMap();
    219 
    220         if (visualMap1 == null) {
    221             errln("getVisualMap() in test " + testNumber + " is null");
    222             visualMap1 = new int[0];
    223         }
    224 
    225         /* invert them both */
    226         visualMap2 = Bidi.invertMap(logicalMap1);
    227         logicalMap2 = Bidi.invertMap(visualMap1);
    228 
    229         /* get them from the levels array, too */
    230         levels = bidi.getLevels();
    231 
    232         if (levels == null || levels.length != length) {
    233             errln("getLevels() in test " + testNumber + " failed");
    234         }
    235 
    236         logicalMap3 = Bidi.reorderLogical(levels);
    237         visualMap3 = Bidi.reorderVisual(levels);
    238 
    239         /* get the visual map from the runs, too */
    240         try {
    241             runCount = bidi.countRuns();
    242         } catch (IllegalStateException e) {
    243             errln("countRuns() in test " + testNumber + " failed");
    244             runCount = 0;
    245         }
    246 
    247         logln("\n---- " + runCount + " runs");
    248         visualIndex = 0;
    249         BidiRun run;
    250         for (i = 0; i < runCount; ++i) {
    251             run = bidi.getVisualRun(i);
    252             if (run == null) {
    253                 errln("null visual run encountered at index " + i +
    254                       ", in test " + testNumber);
    255                 continue;
    256             }
    257             odd = run.isOddRun();
    258             logicalStart = run.getStart();
    259             runLength = run.getLength();
    260             log("(" + (run.isOddRun() ? "R" : "L"));
    261             log(" @" + run.getStart() + '[' + run.getLength() + "])\n");
    262             if (!odd) {
    263                 do {    /* LTR */
    264                     visualMap4[visualIndex++] = logicalStart++;
    265                 } while (--runLength > 0);
    266             } else {
    267                 logicalStart += runLength;  /* logicalLimit */
    268                 do {    /* RTL */
    269                     visualMap4[visualIndex++] = --logicalStart;
    270                 } while (--runLength > 0);
    271             }
    272         }
    273         log("\n");
    274 
    275         /* print all the maps */
    276         logln("logical maps:");
    277         for (i = 0; i < length; ++i) {
    278             log(logicalMap1[i] + " ");
    279         }
    280         log("\n");
    281         for (i = 0; i < length; ++i) {
    282             log(logicalMap2[i] + " ");
    283         }
    284         log("\n");
    285         for (i = 0; i < length; ++i) {
    286             log(logicalMap3[i] + " ");
    287         }
    288 
    289         log("\nvisual maps:\n");
    290         for (i = 0; i < destLength; ++i) {
    291             log(visualMap1[i] + " ");
    292         }
    293         log("\n");
    294         for (i = 0; i < destLength; ++i) {
    295             log(visualMap2[i] + " ");
    296         }
    297         log("\n");
    298         for (i = 0; i < length; ++i) {
    299             log(visualMap3[i] + " ");
    300         }
    301         log("\n");
    302         for (i = 0; i < length; ++i) {
    303             log(visualMap4[i] + " ");
    304         }
    305         log("\n");
    306 
    307         /* check that the indexes are the same between these and Bidi.getLogical/VisualIndex() */
    308         for (i = 0; i < length; ++i) {
    309             if (logicalMap1[i] != logicalMap2[i]) {
    310                 errln("Error in tests[" + testNumber + "]: (logicalMap1[" + i +
    311                       "] == " + logicalMap1[i] + ") != (logicalMap2[" + i +
    312                       "] == " + logicalMap2[i] + ")");
    313             }
    314             if (logicalMap1[i] != logicalMap3[i]) {
    315                 errln("Error in tests[" + testNumber + "]: (logicalMap1[" + i +
    316                       "] == " + logicalMap1[i] + ") != (logicalMap3[" + i +
    317                       "] == " + logicalMap3[i] + ")");
    318             }
    319             if (visualMap1[i] != visualMap2[i]) {
    320                 errln("Error in tests[" + testNumber + "]: (visualMap1[" + i +
    321                       "] == " + visualMap1[i] + ") != (visualMap2[" + i +
    322                       "] == " + visualMap2[i] + ")");
    323             }
    324             if (visualMap1[i] != visualMap3[i]) {
    325                 errln("Error in tests[" + testNumber + "]: (visualMap1[" + i +
    326                       "] == " + visualMap1[i] + ") != (visualMap3[" + i +
    327                       "] == " + visualMap3[i] + ")");
    328             }
    329             if (visualMap1[i] != visualMap4[i]) {
    330                 errln("Error in tests[" + testNumber + "]: (visualMap1[" + i +
    331                       "] == " + visualMap1[i] + ") != (visualMap4[" + i +
    332                       "] == " + visualMap4[i] + ")");
    333             }
    334             try {
    335                 visualIndex = bidi.getVisualIndex(i);
    336             } catch (Exception e) {
    337                 errln("Bidi.getVisualIndex(" + i + ") failed in tests[" +
    338                       testNumber + "]");
    339             }
    340             if (logicalMap1[i] != visualIndex) {
    341                 errln("Error in tests[" + testNumber + "]: (logicalMap1[" + i +
    342                       "] == " + logicalMap1[i] + ") != (Bidi.getVisualIndex(" + i +
    343                       ") == " + visualIndex + ")");
    344             }
    345             try {
    346                 logicalIndex = bidi.getLogicalIndex(i);
    347             } catch (Exception e) {
    348                 errln("Bidi.getLogicalIndex(" + i + ") failed in tests[" +
    349                       testNumber + "]");
    350             }
    351             if (visualMap1[i] != logicalIndex) {
    352                 errln("Error in tests[" + testNumber + "]: (visualMap1[" + i +
    353                       "] == " + visualMap1[i] + ") != (Bidi.getLogicalIndex(" + i +
    354                       ") == " + logicalIndex + ")");
    355             }
    356         }
    357     }
    358 
    359     private String getStringFromDirProps(short[] dirProps) {
    360         int i;
    361 
    362         if (dirProps == null) {
    363             return null;
    364         }
    365         int length = dirProps.length;
    366         char[] buffer = new char[length];
    367 
    368         /* this part would have to be modified for UTF-x */
    369         for (i = 0; i < length; ++i) {
    370             buffer[i] = charFromDirProp[dirProps[i]];
    371         }
    372         return new String(buffer);
    373     }
    374 
    375     private void doMisc() {
    376     /* Miscellaneous tests to exercize less popular code paths */
    377         Bidi bidi = new Bidi(120, 66), bidiLine;
    378 
    379         assertEquals("\nwriteReverse should return an empty string",
    380                      "", Bidi.writeReverse("", 0));
    381 
    382         bidi.setPara("", Bidi.LTR, null);
    383         assertEquals("\nwriteReordered should return an empty string",
    384                      "", bidi.writeReordered(0));
    385 
    386         bidi.setPara("abc", Bidi.LTR, null);
    387         assertEquals("\ngetRunStart should return 0",
    388                      0, bidi.getRunStart(0));
    389         assertEquals("\ngetRunLimit should return 3",
    390                      3, bidi.getRunLimit(0));
    391 
    392         bidi.setPara("abc          ", Bidi.RTL, null);
    393         bidiLine = bidi.setLine(0, 6);
    394         for (int i = 3; i < 6; i++) {
    395             assertEquals("\nTrailing space at " + i + " should get paragraph level",
    396                          Bidi.RTL, bidiLine.getLevelAt(i));
    397         }
    398 
    399         bidi.setPara("abc       def", Bidi.RTL, null);
    400         bidiLine = bidi.setLine(0, 6);
    401         for (int i = 3; i < 6; i++) {
    402             assertEquals("\nTrailing space at " + i + " should get paragraph level",
    403                          Bidi.RTL, bidiLine.getLevelAt(i));
    404         }
    405 
    406         bidi.setPara("abcdefghi    ", Bidi.RTL, null);
    407         bidiLine = bidi.setLine(0, 6);
    408         for (int i = 3; i < 6; i++) {
    409             assertEquals("\nTrailing char at " + i + " should get level 2",
    410                          2, bidiLine.getLevelAt(i));
    411         }
    412 
    413         bidi.setReorderingOptions(Bidi.OPTION_REMOVE_CONTROLS);
    414         bidi.setPara("\u200eabc       def", Bidi.RTL, null);
    415         bidiLine = bidi.setLine(0, 6);
    416         assertEquals("\nWrong result length", 5, bidiLine.getResultLength());
    417 
    418         bidi.setPara("abcdefghi", Bidi.LTR, null);
    419         bidiLine = bidi.setLine(0, 6);
    420         assertEquals("\nWrong direction #1", Bidi.LTR, bidiLine.getDirection());
    421 
    422         bidi.setPara("", Bidi.LTR, null);
    423         byte[] levels = bidi.getLevels();
    424         assertEquals("\nWrong number of level elements", 0, levels.length);
    425         assertEquals("\nWrong number of runs #1", 0, bidi.countRuns());
    426 
    427         bidi.setPara("          ", Bidi.RTL, null);
    428         bidiLine = bidi.setLine(0, 6);
    429         assertEquals("\nWrong number of runs #2", 1, bidiLine.countRuns());
    430 
    431         bidi.setPara("a\u05d0        bc", Bidi.RTL, null);
    432         bidiLine = bidi.setLine(0, 6);
    433         assertEquals("\nWrong direction #2", Bidi.MIXED, bidi.getDirection());
    434         assertEquals("\nWrong direction #3", Bidi.MIXED, bidiLine.getDirection());
    435         assertEquals("\nWrong number of runs #3", 2, bidiLine.countRuns());
    436 
    437         int[] map = Bidi.reorderLogical(null);
    438         assertTrue("\nWe should have got a null map #1", map == null);
    439         map = Bidi.reorderLogical(new byte[] {0,126, 127});
    440         assertTrue("\nWe should have got a null map #2", map == null);
    441         map = Bidi.reorderVisual(null);
    442         assertTrue("\nWe should have got a null map #3", map == null);
    443         map = Bidi.reorderVisual(new byte[] {0, -1, 4});
    444         assertTrue("\nWe should have got a null map #4", map == null);
    445 
    446         map = Bidi.invertMap(null);
    447         assertTrue("\nWe should have got a null map #5", map == null);
    448         map = Bidi.invertMap(new int[] {0,1,-1,5,4});
    449         assertTrue("\nUnexpected inverted Map",
    450                    Arrays.equals(map, new int[] {0,1,-1,-1,4,3}));
    451 
    452         bidi.setPara("", Bidi.LTR, null);
    453         map = bidi.getLogicalMap();
    454         assertTrue("\nMap should have length==0 #1", map.length == 0);
    455         map = bidi.getVisualMap();
    456         assertTrue("\nMap should have length==0 #2", map.length == 0);
    457 
    458         /* test BidiRun.toString and allocation of run memory > 1 */
    459         bidi.setPara("abc", Bidi.LTR, null);
    460         assertEquals("\nWrong run display", "BidiRun 0 - 3 @ 0",
    461                      bidi.getLogicalRun(0).toString());
    462 
    463         /* test REMOVE_BIDI_CONTROLS together with DO_MIRRORING */
    464         bidi.setPara("abc\u200e", Bidi.LTR, null);
    465         String out = bidi.writeReordered(Bidi.REMOVE_BIDI_CONTROLS | Bidi.DO_MIRRORING);
    466         assertEquals("\nWrong result #1", "abc", out);
    467 
    468         /* test inverse Bidi with marks and contextual orientation */
    469         bidi.setReorderingMode(Bidi.REORDER_INVERSE_LIKE_DIRECT);
    470         bidi.setReorderingOptions(Bidi.OPTION_INSERT_MARKS);
    471         bidi.setPara("", Bidi.LEVEL_DEFAULT_RTL, null);
    472         out = bidi.writeReordered(0);
    473         assertEquals("\nWrong result #2", "", out);
    474         bidi.setPara("   ", Bidi.LEVEL_DEFAULT_RTL, null);
    475         out = bidi.writeReordered(0);
    476         assertEquals("\nWrong result #3", "   ", out);
    477         bidi.setPara("abc", Bidi.LEVEL_DEFAULT_RTL, null);
    478         out = bidi.writeReordered(0);
    479         assertEquals("\nWrong result #4", "abc", out);
    480         bidi.setPara("\u05d0\u05d1", Bidi.LEVEL_DEFAULT_RTL, null);
    481         out = bidi.writeReordered(0);
    482         assertEquals("\nWrong result #5", "\u05d1\u05d0", out);
    483         bidi.setPara("abc \u05d0\u05d1", Bidi.LEVEL_DEFAULT_RTL, null);
    484         out = bidi.writeReordered(0);
    485         assertEquals("\nWrong result #6", "\u05d1\u05d0 abc", out);
    486         bidi.setPara("\u05d0\u05d1 abc", Bidi.LEVEL_DEFAULT_RTL, null);
    487         out = bidi.writeReordered(0);
    488         assertEquals("\nWrong result #7", "\u200fabc \u05d1\u05d0", out);
    489         bidi.setPara("\u05d0\u05d1 abc .-=", Bidi.LEVEL_DEFAULT_RTL, null);
    490         out = bidi.writeReordered(0);
    491         assertEquals("\nWrong result #8", "\u200f=-. abc \u05d1\u05d0", out);
    492         bidi.orderParagraphsLTR(true);
    493         bidi.setPara("\n\r   \n\rabc\n\u05d0\u05d1\rabc \u05d2\u05d3\n\r" +
    494                      "\u05d4\u05d5 abc\n\u05d6\u05d7 abc .-=\r\n" +
    495                      "-* \u05d8\u05d9 abc .-=", Bidi.LEVEL_DEFAULT_RTL, null);
    496         out = bidi.writeReordered(0);
    497         assertEquals("\nWrong result #9",
    498                      "\n\r   \n\rabc\n\u05d1\u05d0\r\u05d3\u05d2 abc\n\r" +
    499                      "\u200fabc \u05d5\u05d4\n\u200f=-. abc \u05d7\u05d6\r\n" +
    500                      "\u200f=-. abc \u05d9\u05d8 *-", out);
    501 
    502         bidi.setPara("\u05d0 \t", Bidi.LTR, null);
    503         out = bidi.writeReordered(0);
    504         assertEquals("\nWrong result #10", "\u05D0\u200e \t", out);
    505         bidi.setPara("\u05d0 123 \t\u05d1 123 \u05d2", Bidi.LTR, null);
    506         out = bidi.writeReordered(0);
    507         assertEquals("\nWrong result #11", "\u05d0 \u200e123\u200e \t\u05d2 123 \u05d1", out);
    508         bidi.setPara("\u05d0 123 \u0660\u0661 ab", Bidi.LTR, null);
    509         out = bidi.writeReordered(0);
    510         assertEquals("\nWrong result #12", "\u05d0 \u200e123 \u200e\u0660\u0661 ab", out);
    511         bidi.setPara("ab \t", Bidi.RTL, null);
    512         out = bidi.writeReordered(0);
    513         assertEquals("\nWrong result #13", "\u200f\t ab", out);
    514 
    515         /* check exceeding para level */
    516         bidi = new Bidi();
    517         bidi.setPara("A\u202a\u05d0\u202aC\u202c\u05d1\u202cE", (byte)(Bidi.MAX_EXPLICIT_LEVEL - 1), null);
    518         assertEquals("\nWrong level at index 2", Bidi.MAX_EXPLICIT_LEVEL, bidi.getLevelAt(2));
    519 
    520         /* check 1-char runs with RUNS_ONLY */
    521         bidi.setReorderingMode(Bidi.REORDER_RUNS_ONLY);
    522         bidi.setPara("a \u05d0 b \u05d1 c \u05d2 d ", Bidi.LTR, null);
    523         assertEquals("\nWrong number of runs #4", 14, bidi.countRuns());
    524 
    525         /* test testGetBaseDirection to verify fast string direction detection function */
    526         /* mixed start with L */
    527         String mixedEnglishFirst = "\u0061\u0627\u0032\u06f3\u0061\u0034";
    528         assertEquals("\nWrong direction through fast detection #1", Bidi.LTR, Bidi.getBaseDirection(mixedEnglishFirst));
    529         /* mixed start with AL */
    530         String mixedArabicFirst = "\u0661\u0627\u0662\u06f3\u0061\u0664";
    531         assertEquals("\nWrong direction through fast detection #2", Bidi.RTL, Bidi.getBaseDirection(mixedArabicFirst));
    532         /* mixed Start with R */
    533         String mixedHebrewFirst = "\u05EA\u0627\u0662\u06f3\u0061\u0664";
    534         assertEquals("\nWrong direction through fast detection #3", Bidi.RTL, Bidi.getBaseDirection(mixedHebrewFirst));
    535         /* all AL (Arabic. Persian) */
    536         String persian = "\u0698\u067E\u0686\u06AF";
    537         assertEquals("\nWrong direction through fast detection #4", Bidi.RTL, Bidi.getBaseDirection(persian));
    538         /* all R (Hebrew etc.) */
    539         String hebrew = "\u0590\u05D5\u05EA\u05F1";
    540         assertEquals("\nWrong direction through fast detection #5", Bidi.RTL, Bidi.getBaseDirection(hebrew));
    541         /* all L (English) */
    542         String english = "\u0071\u0061\u0066";
    543         assertEquals("\nWrong direction through fast detection #6", Bidi.LTR, Bidi.getBaseDirection(english));
    544         /* mixed start with weak AL an then L */
    545         String startWeakAL = "\u0663\u0071\u0061\u0066";
    546         assertEquals("\nWrong direction through fast detection #7", Bidi.LTR, Bidi.getBaseDirection(startWeakAL));
    547         /* mixed start with weak L and then AL */
    548         String startWeakL = "\u0031\u0698\u067E\u0686\u06AF";
    549         assertEquals("\nWrong direction through fast detection #8", Bidi.RTL, Bidi.getBaseDirection(startWeakL));
    550         /* empty */
    551         String empty = "";
    552         assertEquals("\nWrong direction through fast detection #9", Bidi.NEUTRAL, Bidi.getBaseDirection(empty));
    553         /* surrogate character */
    554         String surrogateChar = "\uD800\uDC00";
    555         assertEquals("\nWrong direction through fast detection #10", Bidi.LTR, Bidi.getBaseDirection(surrogateChar));
    556         /* all weak L (English digits) */
    557         String allEnglishDigits = "\u0031\u0032\u0033";
    558         assertEquals("\nWrong direction through fast detection #11", Bidi.NEUTRAL, Bidi.getBaseDirection(allEnglishDigits));
    559         /* all weak AL (Arabic digits) */
    560         String allArabicDigits = "\u0663\u0664\u0665";
    561         assertEquals("\nWrong direction through fast detection #12", Bidi.NEUTRAL, Bidi.getBaseDirection(allArabicDigits));
    562         /* null string */
    563         String nullString = null;
    564         assertEquals("\nWrong direction through fast detection #13", Bidi.NEUTRAL, Bidi.getBaseDirection(nullString));
    565         /* first L (English) others are R (Hebrew etc.) */
    566         String startEnglishOthersHebrew = "\u0071\u0590\u05D5\u05EA\u05F1";
    567         assertEquals("\nWrong direction through fast detection #14", Bidi.LTR, Bidi.getBaseDirection(startEnglishOthersHebrew));
    568         /* last R (Hebrew etc.) others are weak L (English Digits) */
    569         String lastHebrewOthersEnglishDigit = "\u0031\u0032\u0033\u05F1";
    570         assertEquals("\nWrong direction through fast detection #15", Bidi.RTL, Bidi.getBaseDirection(lastHebrewOthersEnglishDigit));
    571     }
    572 
    573 
    574     public static void main(String[] args) {
    575         try {
    576             new TestBidi().run(args);
    577         }
    578         catch (Exception e) {
    579             System.out.println(e);
    580         }
    581     }
    582 }
    583