2 *******************************************************************************
\r
3 * Copyright (C) 2007, International Business Machines
\r
4 * Corporation and others. All Rights Reserved.
\r
5 *******************************************************************************
\r
8 package com.ibm.icu.dev.test.bidi;
\r
10 import java.util.Arrays;
\r
11 import com.ibm.icu.text.Bidi;
\r
12 import com.ibm.icu.text.BidiRun;
\r
15 * Regression test for Bidi class override.
\r
17 * @author Lina Kemmel, Matitiahu Allouche
\r
20 public class TestBidi extends BidiTest {
\r
22 private static final int MAXLEN = 256;
\r
23 private static final String levelString = "............................";
\r
25 public void testBidi() {
\r
29 logln("\nEntering TestBidi");
\r
30 bidi = new Bidi(MAXLEN, 0);
\r
31 bidiLine = new Bidi();
\r
33 doTests(bidi, bidiLine, false);
\r
34 doTests(bidi, bidiLine, true);
\r
36 logln("\nExiting TestBidi");
\r
39 private void doTests(Bidi bidi, Bidi bidiLine, boolean countRunsFirst) {
\r
44 int bidiTestCount = TestData.testCount();
\r
46 for (testNumber = 0; testNumber < bidiTestCount; ++testNumber) {
\r
47 TestData test = TestData.getTestData(testNumber);
\r
48 string = getStringFromDirProps(test.dirProps);
\r
49 paraLevel = test.paraLevel;
\r
51 bidi.setPara(string, paraLevel, null);
\r
52 logln("Bidi.setPara(tests[" + testNumber + "] OK, direction "
\r
53 + bidi.getDirection() + " paraLevel "
\r
55 } catch (Exception e) {
\r
56 errln("Bidi.setPara(tests[" + testNumber + "] failed, direction "
\r
57 + bidi.getDirection() + " paraLevel "
\r
60 lineStart = test.lineStart;
\r
61 if (lineStart == -1) {
\r
62 doTest(bidi, testNumber, test, 0, countRunsFirst);
\r
65 bidiLine = bidi.setLine(lineStart, test.lineLimit);
\r
66 logln("Bidi.setLine(" + lineStart + ", " + test.lineLimit
\r
67 + "), in tests[" + testNumber + "] OK, direction "
\r
68 + bidiLine.getDirection() + " paraLevel "
\r
69 + bidiLine.getBaseLevel());
\r
70 doTest(bidiLine, testNumber, test, lineStart, countRunsFirst);
\r
71 } catch (Exception e) {
\r
72 errln("Bidi.setLine(" + lineStart + ", " + test.lineLimit
\r
73 + "), in runAll test[" + testNumber + "] failed");
\r
75 /* do it again using createLineBidi instead of setLine */
\r
77 bidiLine = bidi.createLineBidi(lineStart, test.lineLimit);
\r
78 logln("Bidi.createLineBidi(" + lineStart + ", " + test.lineLimit
\r
79 + "), in tests[" + testNumber + "] OK, direction "
\r
80 + bidiLine.getDirection() + " paraLevel "
\r
81 + bidiLine.getBaseLevel());
\r
82 doTest(bidiLine, testNumber, test, lineStart, countRunsFirst);
\r
83 } catch (Exception e) {
\r
84 errln("Bidi.createLineBidi(" + lineStart + ", " + test.lineLimit
\r
85 + "), in runAll test[" + testNumber + "] failed");
\r
91 private void doTest(Bidi bidi, int testNumber, TestData test,
\r
92 int lineStart, boolean countRunsFirst) {
\r
93 short[] dirProps = test.dirProps;
\r
94 byte[] levels = test.levels;
\r
95 int[] visualMap = test.visualMap;
\r
96 int i, len = bidi.getLength(), logicalIndex = -1, runCount = 0;
\r
99 if (countRunsFirst) {
\r
100 logln("Calling Bidi.countRuns() first.");
\r
102 runCount = bidi.countRuns();
\r
103 } catch (IllegalStateException e) {
\r
104 errln("Bidi.countRuns(test[" + testNumber + "]) failed");
\r
107 logln("Calling Bidi.getLogicalMap() first.");
\r
110 _testReordering(bidi, testNumber);
\r
112 for (i = 0; i < len; ++i) {
\r
113 logln(i + " " + bidi.getLevelAt(i) + " " + levelString
\r
114 + TestData.dirPropNames[dirProps[lineStart + i]] + " "
\r
115 + bidi.getVisualIndex(i));
\r
118 log("\n-----levels:");
\r
119 for (i = 0; i < len; ++i) {
\r
123 log(" " + bidi.getLevelAt(i));
\r
126 log("\n--reordered:");
\r
127 for (i = 0; i < len; ++i) {
\r
131 log(" " + bidi.getVisualIndex(i));
\r
135 assertEquals("\nFailure in Bidi.getDirection(test[" + testNumber + "])",
\r
136 test.direction, bidi.getDirection());
\r
137 assertEquals("\nFailure in Bidi.getParaLevel(test[" + testNumber + "])",
\r
138 test.resultLevel, bidi.getParaLevel());
\r
140 for (i = 0; i < len; ++i) {
\r
141 assertEquals("\nFailure in Bidi.getLevelAt(" + i +
\r
142 ") in test[" + testNumber + "]",
\r
143 levels[i], bidi.getLevelAt(i));
\r
146 for (i = 0; i < len; ++i) {
\r
148 logicalIndex = bidi.getVisualIndex(i);
\r
149 } catch (Throwable th) {
\r
150 errln("Bidi.getVisualIndex(" + i + ") in test[" + testNumber
\r
153 if(visualMap[i] != logicalIndex) {
\r
154 assertEquals("\nFailure in Bidi.getVisualIndex(" + i +
\r
155 ") in test[" + testNumber + "])",
\r
156 visualMap[i], logicalIndex);
\r
160 if (!countRunsFirst) {
\r
162 runCount = bidi.countRuns();
\r
163 } catch (IllegalStateException e) {
\r
164 errln("Bidi.countRuns(test[" + testNumber + "]) failed");
\r
170 for (logicalIndex = 0; logicalIndex < len; ) {
\r
171 level = bidi.getLevelAt(logicalIndex);
\r
172 run = bidi.getLogicalRun(logicalIndex);
\r
173 logicalIndex = run.getLimit();
\r
174 level2 = run.getEmbeddingLevel();
\r
175 assertEquals("Logical " + run.toString() +
\r
176 " in test[" + testNumber + "]: wrong level",
\r
178 if (--runCount < 0) {
\r
179 errln("Bidi.getLogicalRun(test[" + testNumber
\r
180 + "]): wrong number of runs compared to Bidi.countRuns() = "
\r
181 + bidi.countRuns());
\r
184 if (runCount != 0) {
\r
185 errln("Bidi.getLogicalRun(test[" + testNumber
\r
186 + "]): wrong number of runs compared to Bidi.countRuns() = "
\r
187 + bidi.countRuns());
\r
193 private void _testReordering(Bidi bidi, int testNumber) {
\r
200 int[] visualMap4 = new int[MAXLEN];
\r
202 int i, length = bidi.getLength(),
\r
203 destLength = bidi.getResultLength();
\r
204 int runCount, visualIndex, logicalIndex = -1, logicalStart, runLength;
\r
210 /* get the logical and visual maps from the object */
\r
211 logicalMap1 = bidi.getLogicalMap();
\r
212 if (logicalMap1 == null) {
\r
213 errln("getLogicalMap in test " + testNumber + " is null");
\r
214 logicalMap1 = new int[0];
\r
217 visualMap1 = bidi.getVisualMap();
\r
219 if (visualMap1 == null) {
\r
220 errln("getVisualMap() in test " + testNumber + " is null");
\r
221 visualMap1 = new int[0];
\r
224 /* invert them both */
\r
225 visualMap2 = Bidi.invertMap(logicalMap1);
\r
226 logicalMap2 = Bidi.invertMap(visualMap1);
\r
228 /* get them from the levels array, too */
\r
229 levels = bidi.getLevels();
\r
231 if (levels == null || levels.length != length) {
\r
232 errln("getLevels() in test " + testNumber + " failed");
\r
235 logicalMap3 = Bidi.reorderLogical(levels);
\r
236 visualMap3 = Bidi.reorderVisual(levels);
\r
238 /* get the visual map from the runs, too */
\r
240 runCount = bidi.countRuns();
\r
241 } catch (IllegalStateException e) {
\r
242 errln("countRuns() in test " + testNumber + " failed");
\r
246 logln("\n---- " + runCount + " runs");
\r
249 for (i = 0; i < runCount; ++i) {
\r
250 run = bidi.getVisualRun(i);
\r
252 errln("null visual run encountered at index " + i +
\r
253 ", in test " + testNumber);
\r
256 odd = run.isOddRun();
\r
257 logicalStart = run.getStart();
\r
258 runLength = run.getLength();
\r
259 log("(" + (run.isOddRun() ? "R" : "L"));
\r
260 log(" @" + run.getStart() + '[' + run.getLength() + "])\n");
\r
263 visualMap4[visualIndex++] = logicalStart++;
\r
264 } while (--runLength > 0);
\r
266 logicalStart += runLength; /* logicalLimit */
\r
268 visualMap4[visualIndex++] = --logicalStart;
\r
269 } while (--runLength > 0);
\r
274 /* print all the maps */
\r
275 logln("logical maps:");
\r
276 for (i = 0; i < length; ++i) {
\r
277 log(logicalMap1[i] + " ");
\r
280 for (i = 0; i < length; ++i) {
\r
281 log(logicalMap2[i] + " ");
\r
284 for (i = 0; i < length; ++i) {
\r
285 log(logicalMap3[i] + " ");
\r
288 log("\nvisual maps:\n");
\r
289 for (i = 0; i < destLength; ++i) {
\r
290 log(visualMap1[i] + " ");
\r
293 for (i = 0; i < destLength; ++i) {
\r
294 log(visualMap2[i] + " ");
\r
297 for (i = 0; i < length; ++i) {
\r
298 log(visualMap3[i] + " ");
\r
301 for (i = 0; i < length; ++i) {
\r
302 log(visualMap4[i] + " ");
\r
306 /* check that the indexes are the same between these and Bidi.getLogical/VisualIndex() */
\r
307 for (i = 0; i < length; ++i) {
\r
308 if (logicalMap1[i] != logicalMap2[i]) {
\r
309 errln("Error in tests[" + testNumber + "]: (logicalMap1[" + i +
\r
310 "] == " + logicalMap1[i] + ") != (logicalMap2[" + i +
\r
311 "] == " + logicalMap2[i] + ")");
\r
313 if (logicalMap1[i] != logicalMap3[i]) {
\r
314 errln("Error in tests[" + testNumber + "]: (logicalMap1[" + i +
\r
315 "] == " + logicalMap1[i] + ") != (logicalMap3[" + i +
\r
316 "] == " + logicalMap3[i] + ")");
\r
318 if (visualMap1[i] != visualMap2[i]) {
\r
319 errln("Error in tests[" + testNumber + "]: (visualMap1[" + i +
\r
320 "] == " + visualMap1[i] + ") != (visualMap2[" + i +
\r
321 "] == " + visualMap2[i] + ")");
\r
323 if (visualMap1[i] != visualMap3[i]) {
\r
324 errln("Error in tests[" + testNumber + "]: (visualMap1[" + i +
\r
325 "] == " + visualMap1[i] + ") != (visualMap3[" + i +
\r
326 "] == " + visualMap3[i] + ")");
\r
328 if (visualMap1[i] != visualMap4[i]) {
\r
329 errln("Error in tests[" + testNumber + "]: (visualMap1[" + i +
\r
330 "] == " + visualMap1[i] + ") != (visualMap4[" + i +
\r
331 "] == " + visualMap4[i] + ")");
\r
334 visualIndex = bidi.getVisualIndex(i);
\r
335 } catch (Exception e) {
\r
336 errln("Bidi.getVisualIndex(" + i + ") failed in tests[" +
\r
339 if (logicalMap1[i] != visualIndex) {
\r
340 errln("Error in tests[" + testNumber + "]: (logicalMap1[" + i +
\r
341 "] == " + logicalMap1[i] + ") != (Bidi.getVisualIndex(" + i +
\r
342 ") == " + visualIndex + ")");
\r
345 logicalIndex = bidi.getLogicalIndex(i);
\r
346 } catch (Exception e) {
\r
347 errln("Bidi.getLogicalIndex(" + i + ") failed in tests[" +
\r
350 if (visualMap1[i] != logicalIndex) {
\r
351 errln("Error in tests[" + testNumber + "]: (visualMap1[" + i +
\r
352 "] == " + visualMap1[i] + ") != (Bidi.getLogicalIndex(" + i +
\r
353 ") == " + logicalIndex + ")");
\r
358 private String getStringFromDirProps(short[] dirProps) {
\r
361 if (dirProps == null) {
\r
364 int length = dirProps.length;
\r
365 char[] buffer = new char[length];
\r
367 /* this part would have to be modified for UTF-x */
\r
368 for (i = 0; i < length; ++i) {
\r
369 buffer[i] = charFromDirProp[dirProps[i]];
\r
371 return new String(buffer);
\r
374 private void doMisc() {
\r
375 /* Miscellaneous tests to exercize less popular code paths */
\r
376 Bidi bidi = new Bidi(120, 66), bidiLine;
\r
378 assertEquals("\nwriteReverse should return an empty string",
\r
379 "", Bidi.writeReverse("", 0));
\r
381 bidi.setPara("", Bidi.LTR, null);
\r
382 assertEquals("\nwriteReordered should return an empty string",
\r
383 "", bidi.writeReordered(0));
\r
385 bidi.setPara("abc", Bidi.LTR, null);
\r
386 assertEquals("\ngetRunStart should return 0",
\r
387 0, bidi.getRunStart(0));
\r
388 assertEquals("\ngetRunLimit should return 3",
\r
389 3, bidi.getRunLimit(0));
\r
391 bidi.setPara("abc ", Bidi.RTL, null);
\r
392 bidiLine = bidi.setLine(0, 6);
\r
393 for (int i = 3; i < 6; i++) {
\r
394 assertEquals("\nTrailing space at " + i + " should get paragraph level",
\r
395 Bidi.RTL, bidiLine.getLevelAt(i));
\r
398 bidi.setPara("abc def", Bidi.RTL, null);
\r
399 bidiLine = bidi.setLine(0, 6);
\r
400 for (int i = 3; i < 6; i++) {
\r
401 assertEquals("\nTrailing space at " + i + " should get paragraph level",
\r
402 Bidi.RTL, bidiLine.getLevelAt(i));
\r
405 bidi.setPara("abcdefghi ", Bidi.RTL, null);
\r
406 bidiLine = bidi.setLine(0, 6);
\r
407 for (int i = 3; i < 6; i++) {
\r
408 assertEquals("\nTrailing char at " + i + " should get level 2",
\r
409 2, bidiLine.getLevelAt(i));
\r
412 bidi.setReorderingOptions(Bidi.OPTION_REMOVE_CONTROLS);
\r
413 bidi.setPara("\u200eabc def", Bidi.RTL, null);
\r
414 bidiLine = bidi.setLine(0, 6);
\r
415 assertEquals("\nWrong result length", 5, bidiLine.getResultLength());
\r
417 bidi.setPara("abcdefghi", Bidi.LTR, null);
\r
418 bidiLine = bidi.setLine(0, 6);
\r
419 assertEquals("\nWrong direction #1", Bidi.LTR, bidiLine.getDirection());
\r
421 bidi.setPara("", Bidi.LTR, null);
\r
422 byte[] levels = bidi.getLevels();
\r
423 assertEquals("\nWrong number of level elements", 0, levels.length);
\r
424 assertEquals("\nWrong number of runs #1", 0, bidi.countRuns());
\r
426 bidi.setPara(" ", Bidi.RTL, null);
\r
427 bidiLine = bidi.setLine(0, 6);
\r
428 assertEquals("\nWrong number of runs #2", 1, bidiLine.countRuns());
\r
430 bidi.setPara("a\u05d0 bc", Bidi.RTL, null);
\r
431 bidiLine = bidi.setLine(0, 6);
\r
432 assertEquals("\nWrong direction #2", Bidi.MIXED, bidi.getDirection());
\r
433 assertEquals("\nWrong direction #3", Bidi.MIXED, bidiLine.getDirection());
\r
434 assertEquals("\nWrong number of runs #3", 2, bidiLine.countRuns());
\r
436 int[] map = Bidi.reorderLogical(null);
\r
437 assertTrue("\nWe should have got a null map #1", map == null);
\r
438 map = Bidi.reorderLogical(new byte[] {0,99,99});
\r
439 assertTrue("\nWe should have got a null map #2", map == null);
\r
440 map = Bidi.reorderVisual(null);
\r
441 assertTrue("\nWe should have got a null map #3", map == null);
\r
443 map = Bidi.invertMap(null);
\r
444 assertTrue("\nWe should have got a null map #4", map == null);
\r
445 map = Bidi.invertMap(new int[] {0,1,-1,5,4});
\r
446 assertTrue("\nUnexpected inverted Map",
\r
447 Arrays.equals(map, new int[] {0,1,-1,-1,4,3}));
\r
449 bidi.setPara("", Bidi.LTR, null);
\r
450 map = bidi.getLogicalMap();
\r
451 assertTrue("\nMap should have length==0 #1", map.length == 0);
\r
452 map = bidi.getVisualMap();
\r
453 assertTrue("\nMap should have length==0 #2", map.length == 0);
\r
455 /* test BidiRun.toString and allocation of run memory > 1 */
\r
456 bidi.setPara("abc", Bidi.LTR, null);
\r
457 assertEquals("\nWrong run display", "BidiRun 0 - 3 @ 0",
\r
458 bidi.getLogicalRun(0).toString());
\r
460 /* test REMOVE_BIDI_CONTROLS together with DO_MIRRORING */
\r
461 bidi.setPara("abc\u200e", Bidi.LTR, null);
\r
462 String out = bidi.writeReordered(Bidi.REMOVE_BIDI_CONTROLS | Bidi.DO_MIRRORING);
\r
463 assertEquals("\nWrong result #1", "abc", out);
\r
465 /* test inverse Bidi with marks and contextual orientation */
\r
466 bidi.setReorderingMode(Bidi.REORDER_INVERSE_LIKE_DIRECT);
\r
467 bidi.setReorderingOptions(Bidi.OPTION_INSERT_MARKS);
\r
468 bidi.setPara("", Bidi.LEVEL_DEFAULT_RTL, null);
\r
469 out = bidi.writeReordered(0);
\r
470 assertEquals("\nWrong result #2", "", out);
\r
471 bidi.setPara(" ", Bidi.LEVEL_DEFAULT_RTL, null);
\r
472 out = bidi.writeReordered(0);
\r
473 assertEquals("\nWrong result #3", " ", out);
\r
474 bidi.setPara("abc", Bidi.LEVEL_DEFAULT_RTL, null);
\r
475 out = bidi.writeReordered(0);
\r
476 assertEquals("\nWrong result #4", "abc", out);
\r
477 bidi.setPara("\u05d0\u05d1", Bidi.LEVEL_DEFAULT_RTL, null);
\r
478 out = bidi.writeReordered(0);
\r
479 assertEquals("\nWrong result #5", "\u05d1\u05d0", out);
\r
480 bidi.setPara("abc \u05d0\u05d1", Bidi.LEVEL_DEFAULT_RTL, null);
\r
481 out = bidi.writeReordered(0);
\r
482 assertEquals("\nWrong result #6", "\u05d1\u05d0 abc", out);
\r
483 bidi.setPara("\u05d0\u05d1 abc", Bidi.LEVEL_DEFAULT_RTL, null);
\r
484 out = bidi.writeReordered(0);
\r
485 assertEquals("\nWrong result #7", "\u200fabc \u05d1\u05d0", out);
\r
486 bidi.setPara("\u05d0\u05d1 abc .-=", Bidi.LEVEL_DEFAULT_RTL, null);
\r
487 out = bidi.writeReordered(0);
\r
488 assertEquals("\nWrong result #8", "\u200f=-. abc \u05d1\u05d0", out);
\r
489 bidi.orderParagraphsLTR(true);
\r
490 bidi.setPara("\n\r \n\rabc\n\u05d0\u05d1\rabc \u05d2\u05d3\n\r" +
\r
491 "\u05d4\u05d5 abc\n\u05d6\u05d7 abc .-=\r\n" +
\r
492 "-* \u05d8\u05d9 abc .-=", Bidi.LEVEL_DEFAULT_RTL, null);
\r
493 out = bidi.writeReordered(0);
\r
494 assertEquals("\nWrong result #9",
\r
495 "\n\r \n\rabc\n\u05d1\u05d0\r\u05d3\u05d2 abc\n\r" +
\r
496 "\u200fabc \u05d5\u05d4\n\u200f=-. abc \u05d7\u05d6\r\n" +
\r
497 "\u200f=-. abc \u05d9\u05d8 *-", out);
\r
499 bidi.setPara("\u05d0 \t", Bidi.LTR, null);
\r
500 out = bidi.writeReordered(0);
\r
501 assertEquals("\nWrong result #10", "\u05D0\u200e \t", out);
\r
502 bidi.setPara("\u05d0 123 \t\u05d1 123 \u05d2", Bidi.LTR, null);
\r
503 out = bidi.writeReordered(0);
\r
504 assertEquals("\nWrong result #11", "\u05d0 \u200e123\u200e \t\u05d2 123 \u05d1", out);
\r
505 bidi.setPara("\u05d0 123 \u0660\u0661 ab", Bidi.LTR, null);
\r
506 out = bidi.writeReordered(0);
\r
507 assertEquals("\nWrong result #12", "\u05d0 \u200e123 \u200e\u0660\u0661 ab", out);
\r
508 bidi.setPara("ab \t", Bidi.RTL, null);
\r
509 out = bidi.writeReordered(0);
\r
510 assertEquals("\nWrong result #13", "\u200f\t ab", out);
\r
512 /* check exceeding para level */
\r
514 bidi.setPara("A\u202a\u05d0\u202aC\u202c\u05d1\u202cE", (byte)(Bidi.MAX_EXPLICIT_LEVEL - 1), null);
\r
515 assertEquals("\nWrong level at index 2", 61, bidi.getLevelAt(2));
\r
517 /* check 1-char runs with RUNS_ONLY */
\r
518 bidi.setReorderingMode(Bidi.REORDER_RUNS_ONLY);
\r
519 bidi.setPara("a \u05d0 b \u05d1 c \u05d2 d ", Bidi.LTR, null);
\r
520 assertEquals("\nWrong number of runs #4", 14, bidi.countRuns());
\r
524 public static void main(String[] args) {
\r
526 new TestBidi().run(args);
\r
528 catch (Exception e) {
\r
529 System.out.println(e);
\r