2 *******************************************************************************
\r
3 * Copyright (C) 2008-2010, 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
12 import com.ibm.icu.impl.Utility;
\r
13 import com.ibm.icu.text.Bidi;
\r
14 import com.ibm.icu.text.BidiRun;
\r
17 * Regression test for Bidi multiple paragraphs
\r
19 * @author Lina Kemmel, Matitiahu Allouche
\r
22 public class TestMultipleParagraphs extends BidiTest {
\r
24 private static final String text =
\r
25 "__ABC\u001c" /* Para #0 offset 0 */
\r
26 + "__\u05d0DE\u001c" /* 1 6 */
\r
27 + "__123\u001c" /* 2 12 */
\r
31 + "HI\r\n" /* 6 24 */
\r
35 + "JK\u001c"; /* 10 32 */
\r
36 private static final int paraCount = 11;
\r
37 private static final int[] paraBounds = {
\r
38 0, 6, 12, 18, 20, 23, 24, 28, 30, 31, 32, 35
\r
40 private static final byte[] paraLevels = {
\r
41 Bidi.LTR, Bidi.RTL, Bidi.LEVEL_DEFAULT_LTR, Bidi.LEVEL_DEFAULT_RTL, 22, 23
\r
43 private static final byte[][] multiLevels = {
\r
44 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
\r
45 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
\r
46 {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
\r
47 {0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0},
\r
48 {22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22},
\r
49 {23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23}
\r
51 private static final String text2 = "\u05d0 1-2\u001c\u0630 1-2\u001c1-2";
\r
52 private static final byte[] levels2 = {
\r
53 1, 1, 2, 2, 2, 0, 1, 1, 2, 1, 2, 0, 2, 2, 2
\r
55 private static final char[] multiparaTestString = {
\r
56 0x5de, 0x5e0, 0x5e1, 0x5d4, 0x20, 0x5e1, 0x5e4, 0x5da,
\r
57 0x20, 0xa, 0xa, 0x41, 0x72, 0x74, 0x69, 0x73,
\r
58 0x74, 0x3a, 0x20, 0x5de, 0x5e0, 0x5e1, 0x5d4, 0x20,
\r
59 0x5e1, 0x5e4, 0x5da, 0x20, 0xa, 0xa, 0x41, 0x6c,
\r
60 0x62, 0x75, 0x6d, 0x3a, 0x20, 0x5de, 0x5e0, 0x5e1,
\r
61 0x5d4, 0x20, 0x5e1, 0x5e4, 0x5da, 0x20, 0xa, 0xa,
\r
62 0x54, 0x69, 0x6d, 0x65, 0x3a, 0x20, 0x32, 0x3a,
\r
63 0x32, 0x37, 0xa, 0xa
\r
65 private static final byte[] multiparaTestLevels = {
\r
66 1, 1, 1, 1, 1, 1, 1, 1,
\r
67 1, 1, 0, 0, 0, 0, 0, 0,
\r
68 0, 0, 0, 1, 1, 1, 1, 1,
\r
69 1, 1, 1, 0, 0, 0, 0, 0,
\r
70 0, 0, 0, 0, 0, 1, 1, 1,
\r
71 1, 1, 1, 1, 1, 0, 0, 0,
\r
72 0, 0, 0, 0, 0, 0, 0, 0,
\r
76 public void testMultipleParagraphs()
\r
80 boolean orderParagraphsLTR;
\r
82 Bidi bidi = new Bidi();
\r
84 int count, paraStart, paraLimit, paraIndex, length;
\r
87 logln("\nEntering TestMultipleParagraphs\n");
\r
89 bidi.setPara(text, Bidi.LTR, null);
\r
90 } catch (IllegalArgumentException e) {
\r
91 errln("1st Bidi.setPara failed, paraLevel = " + Bidi.LTR);
\r
94 /* check paragraph count and boundaries */
\r
95 if (paraCount != (count = bidi.countParagraphs())) {
\r
96 errln("1st Bidi.countParagraphs returned " + count + ", should be " +
\r
100 for (i = 0; i < paraCount; i++) {
\r
101 run = bidi.getParagraphByIndex(i);
\r
102 paraStart = run.getStart();
\r
103 paraLimit = run.getLimit();
\r
104 if ((paraStart != paraBounds[i]) ||
\r
105 (paraLimit != paraBounds[i + 1])) {
\r
106 errln("Found boundaries of paragraph " + i + ": " +
\r
107 paraStart + "-" + paraLimit + "; expected: " +
\r
108 paraBounds[i] + "-" + paraBounds[i + 1]);
\r
112 /* check with last paragraph not terminated by B */
\r
113 char[] chars = text.toCharArray();
\r
114 chars[chars.length - 1] = 'L';
\r
115 src = new String(chars);
\r
117 bidi.setPara(src, Bidi.LTR, null);
\r
118 } catch (IllegalArgumentException e) {
\r
119 errln("2nd Bidi.setPara failed, paraLevel = " + Bidi.LTR);
\r
121 if (paraCount != (count = bidi.countParagraphs())) {
\r
122 errln("2nd Bidi.countParagraphs returned " + count +
\r
123 ", should be " + paraCount);
\r
126 run = bidi.getParagraphByIndex(i);
\r
127 paraStart = run.getStart();
\r
128 paraLimit = run.getLimit();
\r
129 if ((paraStart != paraBounds[i]) ||
\r
130 (paraLimit != paraBounds[i + 1])) {
\r
131 errln("2nd Found boundaries of paragraph " + i + ": " +
\r
132 paraStart + "-" + paraLimit + "; expected: " +
\r
133 paraBounds[i] + "-" + paraBounds[i + 1]);
\r
136 /* check paraLevel for all paragraphs under various paraLevel specs */
\r
137 for (k = 0; k < 6; k++) {
\r
139 bidi.setPara(src, paraLevels[k], null);
\r
140 } catch (IllegalArgumentException e) {
\r
141 errln("3nd Bidi.setPara failed, paraLevel = " + paraLevels[k]);
\r
143 for (i = 0; i < paraCount; i++) {
\r
144 paraIndex = bidi.getParagraphIndex(paraBounds[i]);
\r
145 run = bidi.getParagraph(paraBounds[i]);
\r
146 if (paraIndex != i) {
\r
147 errln("#1 For paraLevel = " + paraLevels[k] +
\r
148 " paragraph = " + i + ", found paragraph" +
\r
149 " index = " + paraIndex + " expected = " + i);
\r
151 gotLevel = run.getEmbeddingLevel();
\r
152 if (gotLevel != multiLevels[k][i]) {
\r
153 errln("#2 For paraLevel = " + paraLevels[k] +
\r
154 " paragraph = " + i + ", found level = " + gotLevel +
\r
155 ", expected = " + multiLevels[k][i]);
\r
158 gotLevel = bidi.getParaLevel();
\r
159 if (gotLevel != multiLevels[k][0]) {
\r
160 errln("#3 For paraLevel = " + paraLevels[k] +
\r
161 " getParaLevel = " + gotLevel + ", expected " +
\r
162 multiLevels[k][0]);
\r
166 /* check that the result of Bidi.getParaLevel changes if the first
\r
167 * paragraph has a different level
\r
169 chars[0] = '\u05d2'; /* Hebrew letter Gimel */
\r
170 src = new String(chars);
\r
172 bidi.setPara(src, Bidi.LEVEL_DEFAULT_LTR, null);
\r
173 } catch (IllegalArgumentException e) {
\r
174 errln("Bidi.setPara failed, paraLevel = " + Bidi.LEVEL_DEFAULT_LTR);
\r
176 gotLevel = bidi.getParaLevel();
\r
177 if (gotLevel != Bidi.RTL) {
\r
178 errln("#4 For paraLevel = Bidi.LEVEL_DEFAULT_LTR getParaLevel = " +
\r
179 gotLevel + ", expected = " + Bidi.RTL);
\r
182 /* check that line cannot overlap paragraph boundaries */
\r
183 bidiLine = new Bidi();
\r
185 k = paraBounds[2] + 1;
\r
187 bidiLine = bidi.setLine(i, k);
\r
188 errln("For line limits " + i + "-" + k
\r
189 + " got success, while expected failure");
\r
190 } catch (Exception e) {}
\r
195 bidiLine = bidi.setLine(i, k);
\r
196 } catch (Exception e) {
\r
197 errln("For line limits " + i + "-" + k + " got failure");
\r
200 /* check level of block separator at end of paragraph when orderParagraphsLTR==FALSE */
\r
202 bidi.setPara(src, Bidi.RTL, null);
\r
203 } catch (IllegalArgumentException e) {
\r
204 errln("Bidi.setPara failed, paraLevel = " + Bidi.RTL);
\r
206 /* get levels through para Bidi block */
\r
208 gotLevels = bidi.getLevels();
\r
209 } catch (Exception e) {
\r
210 errln("Error on Bidi.getLevels");
\r
211 gotLevels = new byte[bidi.getLength()];
\r
212 Arrays.fill(gotLevels, (byte)-1);
\r
214 for (i = 26; i < 32; i++) {
\r
215 if (gotLevels[i] != Bidi.RTL) {
\r
216 errln("For char " + i + "(0x" + Utility.hex(chars[i]) +
\r
217 "), level = " + gotLevels[i] + ", expected = " + Bidi.RTL);
\r
220 /* get levels through para Line block */
\r
224 bidiLine = bidi.setLine(i, k);
\r
225 } catch (Exception e) {
\r
226 errln("For line limits " + i + "-" + k + " got failure");
\r
229 paraIndex = bidiLine.getParagraphIndex(i);
\r
230 run = bidiLine.getParagraph(i);
\r
232 gotLevels = bidiLine.getLevels();
\r
233 } catch (Exception e) {
\r
234 errln("Error on bidiLine.getLevels");
\r
235 gotLevels = new byte[bidiLine.getLength()];
\r
236 Arrays.fill(gotLevels, (byte)-1);
\r
238 length = bidiLine.getLength();
\r
239 gotLevel = run.getEmbeddingLevel();
\r
240 if ((gotLevel != Bidi.RTL) || (gotLevels[length - 1] != Bidi.RTL)) {
\r
241 errln("For paragraph " + paraIndex + " with limits " +
\r
242 run.getStart() + "-" + run.getLimit() +
\r
243 ", paraLevel = " + gotLevel +
\r
244 "expected = " + Bidi.RTL +
\r
245 ", level of separator = " + gotLevels[length - 1] +
\r
246 " expected = " + Bidi.RTL);
\r
248 orderParagraphsLTR = bidi.isOrderParagraphsLTR();
\r
249 assertFalse("orderParagraphsLTR is true", orderParagraphsLTR);
\r
250 bidi.orderParagraphsLTR(true);
\r
251 orderParagraphsLTR = bidi.isOrderParagraphsLTR();
\r
252 assertTrue("orderParagraphsLTR is false", orderParagraphsLTR);
\r
254 /* check level of block separator at end of paragraph when orderParagraphsLTR==TRUE */
\r
256 bidi.setPara(src, Bidi.RTL, null);
\r
257 } catch (IllegalArgumentException e) {
\r
258 errln("Bidi.setPara failed, paraLevel = " + Bidi.RTL);
\r
260 /* get levels through para Bidi block */
\r
262 gotLevels = bidi.getLevels();
\r
263 } catch (Exception e) {
\r
264 errln("Error on Bidi.getLevels");
\r
265 gotLevels = new byte[bidi.getLength()];
\r
266 Arrays.fill(gotLevels, (byte)-1);
\r
268 for (i = 26; i < 32; i++) {
\r
269 if (gotLevels[i] != 0) {
\r
270 errln("For char " + i + "(0x" + Utility.hex(chars[i]) +
\r
271 "), level = "+ gotLevels[i] + ", expected = 0");
\r
274 /* get levels through para Line block */
\r
277 paraStart = run.getStart();
\r
278 paraLimit = run.getLimit();
\r
280 bidiLine = bidi.setLine(paraStart, paraLimit);
\r
281 } catch (Exception e) {
\r
282 errln("For line limits " + paraStart + "-" + paraLimit +
\r
285 paraIndex = bidiLine.getParagraphIndex(i);
\r
286 run = bidiLine.getParagraph(i);
\r
288 gotLevels = bidiLine.getLevels();
\r
289 } catch (Exception e) {
\r
290 errln("Error on bidiLine.getLevels");
\r
291 gotLevels = new byte[bidiLine.getLength()];
\r
292 Arrays.fill(gotLevels, (byte)-1);
\r
294 length = bidiLine.getLength();
\r
295 gotLevel = run.getEmbeddingLevel();
\r
296 if ((gotLevel != Bidi.RTL) || (gotLevels[length - 1] != 0)) {
\r
297 err("\nFor paragraph " + paraIndex + " with limits " +
\r
298 run.getStart() + "-" + run.getLimit() +
\r
299 ", paraLevel = " + gotLevel + "expected = " + Bidi.RTL +
\r
300 ", level of separator = " + gotLevels[length - 1] +
\r
301 " expected = 0\nlevels = ");
\r
302 for (count = 0; count < length; count++) {
\r
303 errcont(gotLevels[count] + " ");
\r
308 /* test that the concatenation of separate invocations of the bidi code
\r
309 * on each individual paragraph in order matches the levels array that
\r
310 * results from invoking bidi once over the entire multiparagraph tests
\r
311 * (with orderParagraphsLTR false, of course)
\r
313 src = text; /* restore original content */
\r
314 bidi.orderParagraphsLTR(false);
\r
316 bidi.setPara(src, Bidi.LEVEL_DEFAULT_RTL, null);
\r
317 } catch (IllegalArgumentException e) {
\r
318 errln("Bidi.setPara failed, paraLevel = " + Bidi.LEVEL_DEFAULT_RTL);
\r
321 gotLevels = bidi.getLevels();
\r
322 } catch (Exception e) {
\r
323 errln("Error on bidiLine.getLevels");
\r
324 gotLevels = new byte[bidi.getLength()];
\r
325 Arrays.fill(gotLevels, (byte)-1);
\r
327 for (i = 0; i < paraCount; i++) {
\r
328 /* use pLine for individual paragraphs */
\r
329 paraStart = paraBounds[i];
\r
330 length = paraBounds[i + 1] - paraStart;
\r
332 bidiLine.setPara(src.substring(paraStart, paraStart + length),
\r
333 Bidi.LEVEL_DEFAULT_RTL, null);
\r
334 } catch (IllegalArgumentException e) {
\r
335 errln("Bidi.setPara failed, paraLevel = " + Bidi.LEVEL_DEFAULT_RTL);
\r
337 for (j = 0; j < length; j++) {
\r
338 if ((k = bidiLine.getLevelAt(j)) !=
\r
339 (gotLevel = gotLevels[paraStart + j])) {
\r
340 errln("Checking paragraph concatenation: for paragraph[" +
\r
341 i + "], char[" + j + "] = 0x" +
\r
342 Utility.hex(src.charAt(paraStart + j)) +
\r
343 ", level = " + k + ", expected = " + gotLevel);
\r
348 /* ensure that leading numerics in a paragraph are not treated as arabic
\r
349 numerals because of arabic text in a preceding paragraph
\r
352 bidi.orderParagraphsLTR(true);
\r
354 bidi.setPara(src, Bidi.RTL, null);
\r
355 } catch (IllegalArgumentException e) {
\r
356 errln("Bidi.setPara failed, paraLevel = " + Bidi.RTL);
\r
359 gotLevels = bidi.getLevels();
\r
360 } catch (Exception e) {
\r
361 errln("Error on Bidi.getLevels");
\r
362 gotLevels = new byte[bidi.getLength()];
\r
363 Arrays.fill(gotLevels, (byte)-1);
\r
365 for (i = 0, length = src.length(); i < length; i++) {
\r
366 if (gotLevels[i] != levels2[i]) {
\r
367 errln("Checking leading numerics: for char " + i + "(0x" +
\r
368 Utility.hex(src.charAt(i)) + "), level = " +
\r
369 gotLevels[i] + ", expected = " + levels2[i]);
\r
373 /* check handling of whitespace before end of paragraph separator when
\r
374 * orderParagraphsLTR==TRUE, when last paragraph has, and lacks, a terminating B
\r
376 chars = src.toCharArray();
\r
377 Arrays.fill(chars, '\u0020');
\r
378 bidi.orderParagraphsLTR(true);
\r
379 for (i = 0x001c; i <= 0x0020; i += (0x0020-0x001c)) {
\r
380 chars[4] = (char)i; /* with and without terminating B */
\r
381 for (j = 0x0041; j <= 0x05d0; j += (0x05d0-0x0041)) {
\r
382 chars[0] = (char)j; /* leading 'A' or Alef */
\r
383 src = new String(chars);
\r
384 for (gotLevel = 4; gotLevel <= 5; gotLevel++) {
\r
385 /* test even and odd paraLevel */
\r
387 bidi.setPara(src, gotLevel, null);
\r
388 } catch (IllegalArgumentException e) {
\r
389 errln("Bidi.setPara failed, paraLevel = " + gotLevel);
\r
392 gotLevels = bidi.getLevels();
\r
393 } catch (Exception e) {
\r
394 errln("Error on Bidi.getLevels");
\r
395 gotLevels = new byte[bidi.getLength()];
\r
396 Arrays.fill(gotLevels, (byte)-1);
\r
398 for (k = 1; k <= 3; k++) {
\r
399 if (gotLevels[k] != gotLevel) {
\r
400 errln("Checking trailing spaces for leading char 0x" +
\r
401 Utility.hex(chars[0]) + ", last_char = " +
\r
402 Utility.hex(chars[4]) + ", index = " + k +
\r
403 "level = " + gotLevels[k] +
\r
404 ", expected = " + gotLevel);
\r
411 /* check default orientation when inverse bidi and paragraph starts
\r
412 * with LTR strong char and ends with RTL strong char, with and without
\r
415 bidi.setReorderingMode(Bidi.REORDER_INVERSE_LIKE_DIRECT);
\r
416 bidi.setPara("abc \u05d2\u05d1\n", Bidi.LEVEL_DEFAULT_LTR, null);
\r
417 String out = bidi.writeReordered(0);
\r
418 assertEquals("\nInvalid output", "\u05d1\u05d2 abc\n", out);
\r
419 bidi.setPara("abc \u05d2\u05d1", Bidi.LEVEL_DEFAULT_LTR, null);
\r
420 out = bidi.writeReordered(0);
\r
421 assertEquals("\nInvalid output #1", "\u05d1\u05d2 abc", out);
\r
423 /* check multiple paragraphs together with explicit levels
\r
425 bidi.setReorderingMode(Bidi.REORDER_DEFAULT);
\r
426 gotLevels = new byte[] {0,0,0,0,0,0,0,0,0,0};
\r
427 bidi.setPara("ab\u05d1\u05d2\n\u05d3\u05d4123", Bidi.LTR, gotLevels);
\r
428 out = bidi.writeReordered(0);
\r
429 assertEquals("\nInvalid output #2", "ab\u05d2\u05d1\n123\u05d4\u05d3", out);
\r
430 assertEquals("\nInvalid number of paras", 2, bidi.countParagraphs());
\r
432 logln("\nExiting TestMultipleParagraphs\n");
\r
434 /* check levels in multiple paragraphs with default para level
\r
437 bidi.setPara(multiparaTestString, Bidi.LEVEL_DEFAULT_LTR, null);
\r
439 gotLevels = bidi.getLevels();
\r
440 } catch (Exception e) {
\r
441 errln("Error on Bidi.getLevels for multiparaTestString");
\r
444 for (i = 0; i < multiparaTestString.length; i++) {
\r
445 if (gotLevels[i] != multiparaTestLevels[i]) {
\r
446 errln("Error on level for multiparaTestString at index " + i +
\r
447 ", expected=" + multiparaTestLevels[i] +
\r
448 ", actual=" + gotLevels[i]);
\r
454 public static void main(String[] args) {
\r
456 new TestMultipleParagraphs().run(args);
\r
458 catch (Exception e) {
\r
459 System.out.println(e);
\r