/* * Copyright 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.template.soy.internal.i18n; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import com.google.common.base.Strings; import com.google.template.soy.data.Dir; import com.ibm.icu.lang.UCharacter; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; /** Test cases for BidiUtils */ @RunWith(JUnit4.class) public class BidiUtilsTest { private static final String LRE = "\u202A"; private static final String RLE = "\u202B"; private static final String PDF = "\u202C"; private static final String LRO = "\u202D"; private static final String RLO = "\u202E"; private static final String BN = "\u200B"; private static final String HE = "\u05D0"; // Hebrew character. RTL. private static final String HAN = "\u9910"; // Chinese character. LTR. private static final String FA = "\u06AF"; // Persian character. RTL. private static final String AR = "\u0627"; // Arabic character. RTL. private static final String TIMES = "\u00D7"; // Multiplication sign (bidi class ON). private static final String NBSP = "\u00A0"; // Non-breaking space (bidi class CS). private static final String MINUS = "\u2212"; // Mathematical minus (*not* a hyphen). private static final String HYPHEN = "\u2010"; // Hyphen (*not* a minus). private static final String ALT_PLUS = "\uFB29"; // "Alternative" Hebrew plus sign. private static final Dir LTR = Dir.LTR; private static final Dir RTL = Dir.RTL; private static final Dir NEUTRAL = Dir.NEUTRAL; @Test public void testLanguageDir() { assertEquals(RTL, BidiUtils.languageDir("he")); assertEquals(RTL, BidiUtils.languageDir("iw")); assertEquals(RTL, BidiUtils.languageDir("ar")); assertEquals(RTL, BidiUtils.languageDir("fa")); assertEquals(RTL, BidiUtils.languageDir("FA")); assertEquals(RTL, BidiUtils.languageDir("ar-EG")); assertEquals(RTL, BidiUtils.languageDir("Ar-eg")); assertEquals(RTL, BidiUtils.languageDir("az-Arab")); assertEquals(RTL, BidiUtils.languageDir("az-Arab-IR")); assertEquals(RTL, BidiUtils.languageDir("az-ARAB-IR")); assertEquals(RTL, BidiUtils.languageDir("az_arab_IR")); assertEquals(LTR, BidiUtils.languageDir("es")); assertEquals(LTR, BidiUtils.languageDir("zh-CN")); assertEquals(LTR, BidiUtils.languageDir("fil")); assertEquals(LTR, BidiUtils.languageDir("az")); assertEquals(LTR, BidiUtils.languageDir("iw-Latn")); assertEquals(LTR, BidiUtils.languageDir("iw-LATN")); assertEquals(LTR, BidiUtils.languageDir("iw-latn")); } @Test public void testDirectionalityEstimator_dirTypeOps() { BidiUtils.DirectionalityEstimator de = new BidiUtils.DirectionalityEstimator("my my \uD835\uDFCE\uD840\uDC00!", false); assertEquals(UCharacter.DIRECTIONALITY_LEFT_TO_RIGHT, de.dirTypeForward()); assertEquals(UCharacter.DIRECTIONALITY_LEFT_TO_RIGHT, de.dirTypeForward()); assertEquals(UCharacter.DIRECTIONALITY_WHITESPACE, de.dirTypeForward()); assertEquals(UCharacter.DIRECTIONALITY_LEFT_TO_RIGHT, de.dirTypeForward()); assertEquals(UCharacter.DIRECTIONALITY_LEFT_TO_RIGHT, de.dirTypeForward()); assertEquals(UCharacter.DIRECTIONALITY_WHITESPACE, de.dirTypeForward()); assertEquals(UCharacter.DIRECTIONALITY_EUROPEAN_NUMBER, de.dirTypeForward()); assertEquals(UCharacter.DIRECTIONALITY_LEFT_TO_RIGHT, de.dirTypeForward()); assertEquals(UCharacter.DIRECTIONALITY_OTHER_NEUTRALS, de.dirTypeForward()); try { de.dirTypeForward(); // Should throw. assertTrue(false); } catch (IndexOutOfBoundsException e) { } assertEquals(UCharacter.DIRECTIONALITY_OTHER_NEUTRALS, de.dirTypeBackward()); assertEquals(UCharacter.DIRECTIONALITY_LEFT_TO_RIGHT, de.dirTypeBackward()); assertEquals(UCharacter.DIRECTIONALITY_EUROPEAN_NUMBER, de.dirTypeBackward()); assertEquals(UCharacter.DIRECTIONALITY_WHITESPACE, de.dirTypeBackward()); assertEquals(UCharacter.DIRECTIONALITY_LEFT_TO_RIGHT, de.dirTypeBackward()); assertEquals(UCharacter.DIRECTIONALITY_LEFT_TO_RIGHT, de.dirTypeBackward()); assertEquals(UCharacter.DIRECTIONALITY_WHITESPACE, de.dirTypeBackward()); assertEquals(UCharacter.DIRECTIONALITY_LEFT_TO_RIGHT, de.dirTypeBackward()); assertEquals(UCharacter.DIRECTIONALITY_LEFT_TO_RIGHT, de.dirTypeBackward()); try { de.dirTypeBackward(); // Should throw. assertTrue(false); } catch (IndexOutOfBoundsException e) { } } @Test public void testDirectionalityEstimator_dirTypeOpsHtml() { BidiUtils.DirectionalityEstimator de = new BidiUtils.DirectionalityEstimator( "<span x='>" + HE + "'>my \uD835\uDFCE!</span>;>", true); assertEquals(UCharacter.DIRECTIONALITY_BOUNDARY_NEUTRAL, de.dirTypeForward()); assertEquals(UCharacter.DIRECTIONALITY_LEFT_TO_RIGHT, de.dirTypeForward()); assertEquals(UCharacter.DIRECTIONALITY_LEFT_TO_RIGHT, de.dirTypeForward()); assertEquals(UCharacter.DIRECTIONALITY_WHITESPACE, de.dirTypeForward()); assertEquals(UCharacter.DIRECTIONALITY_EUROPEAN_NUMBER, de.dirTypeForward()); assertEquals(UCharacter.DIRECTIONALITY_OTHER_NEUTRALS, de.dirTypeForward()); assertEquals(UCharacter.DIRECTIONALITY_BOUNDARY_NEUTRAL, de.dirTypeForward()); assertEquals(UCharacter.DIRECTIONALITY_OTHER_NEUTRALS, de.dirTypeForward()); assertEquals(UCharacter.DIRECTIONALITY_OTHER_NEUTRALS, de.dirTypeForward()); try { de.dirTypeForward(); // Should throw. assertTrue(false); } catch (IndexOutOfBoundsException e) { } assertEquals(UCharacter.DIRECTIONALITY_OTHER_NEUTRALS, de.dirTypeBackward()); assertEquals(UCharacter.DIRECTIONALITY_OTHER_NEUTRALS, de.dirTypeBackward()); assertEquals(UCharacter.DIRECTIONALITY_BOUNDARY_NEUTRAL, de.dirTypeBackward()); assertEquals(UCharacter.DIRECTIONALITY_OTHER_NEUTRALS, de.dirTypeBackward()); assertEquals(UCharacter.DIRECTIONALITY_EUROPEAN_NUMBER, de.dirTypeBackward()); assertEquals(UCharacter.DIRECTIONALITY_WHITESPACE, de.dirTypeBackward()); assertEquals(UCharacter.DIRECTIONALITY_LEFT_TO_RIGHT, de.dirTypeBackward()); assertEquals(UCharacter.DIRECTIONALITY_LEFT_TO_RIGHT, de.dirTypeBackward()); assertEquals(UCharacter.DIRECTIONALITY_BOUNDARY_NEUTRAL, de.dirTypeBackward()); try { de.dirTypeBackward(); // Should throw. assertTrue(false); } catch (IndexOutOfBoundsException e) { } } @Test public void testHasAnyLtr() { assertFalse(BidiUtils.hasAnyLtr("")); assertFalse(BidiUtils.hasAnyLtr("123\t... \n")); assertFalse(BidiUtils.hasAnyLtr(HE + HE + HE)); assertTrue(BidiUtils.hasAnyLtr(HE + "z" + HE + HE)); // LRE/RLE/LRO/RLO/PDF are ignored. assertFalse(BidiUtils.hasAnyLtr(LRE + PDF)); assertFalse(BidiUtils.hasAnyLtr(LRE + HE + PDF)); assertFalse(BidiUtils.hasAnyLtr(LRE + RLE + HE + PDF + PDF)); assertFalse(BidiUtils.hasAnyLtr(LRO + PDF)); assertFalse(BidiUtils.hasAnyLtr(LRO + HE + PDF)); assertFalse(BidiUtils.hasAnyLtr(LRO + RLE + HE + PDF + PDF)); assertTrue(BidiUtils.hasAnyLtr(RLE + "x" + PDF)); assertTrue(BidiUtils.hasAnyLtr(RLE + LRE + "x" + PDF + PDF)); assertTrue(BidiUtils.hasAnyLtr(RLO + "x" + PDF)); assertTrue(BidiUtils.hasAnyLtr(RLO + LRE + "x" + PDF + PDF)); assertTrue(BidiUtils.hasAnyLtr(RLE + HE + PDF + "x")); assertTrue(BidiUtils.hasAnyLtr(RLE + RLE + HE + PDF + PDF + "x")); assertTrue(BidiUtils.hasAnyLtr(RLO + HE + PDF + "x")); assertTrue(BidiUtils.hasAnyLtr(RLO + RLO + HE + PDF + PDF + "x")); assertTrue(BidiUtils.hasAnyLtr("<nasty title='a'>" + HE, false)); assertFalse(BidiUtils.hasAnyLtr("<nasty title='a'>" + HE, true)); } @Test public void testHasAnyRtl() { assertFalse(BidiUtils.hasAnyRtl("")); assertFalse(BidiUtils.hasAnyRtl("123\t... \n")); assertFalse(BidiUtils.hasAnyRtl("abc")); assertTrue(BidiUtils.hasAnyRtl("ab" + HE + "c")); // LRE/RLE/LRO/RLO/PDF are ignored. assertFalse(BidiUtils.hasAnyRtl(RLE + PDF)); assertFalse(BidiUtils.hasAnyRtl(RLE + "x" + PDF)); assertFalse(BidiUtils.hasAnyRtl(RLE + LRE + "x" + PDF + PDF)); assertFalse(BidiUtils.hasAnyRtl(RLO + PDF)); assertFalse(BidiUtils.hasAnyRtl(RLO + "x" + PDF)); assertFalse(BidiUtils.hasAnyRtl(RLO + LRE + "x" + PDF + PDF)); assertTrue(BidiUtils.hasAnyRtl(LRE + HE + PDF)); assertTrue(BidiUtils.hasAnyRtl(LRE + RLE + HE + PDF + PDF)); assertTrue(BidiUtils.hasAnyRtl(LRO + HE + PDF)); assertTrue(BidiUtils.hasAnyRtl(LRO + RLE + HE + PDF + PDF)); assertTrue(BidiUtils.hasAnyRtl(LRE + "x" + PDF + HE)); assertTrue(BidiUtils.hasAnyRtl(LRE + LRE + "x" + PDF + PDF + HE)); assertTrue(BidiUtils.hasAnyRtl(LRO + "x" + PDF + HE)); assertTrue(BidiUtils.hasAnyRtl(LRO + LRO + "x" + PDF + PDF + HE)); assertTrue(BidiUtils.hasAnyRtl("<nasty title='" + HE + "'>a", false)); assertFalse(BidiUtils.hasAnyRtl("<nasty title='" + HE + "'>a", true)); } @Test public void testGetUnicodeDir_NeutralText() { assertEquals(NEUTRAL, BidiUtils.getUnicodeDir("")); assertEquals(NEUTRAL, BidiUtils.getUnicodeDir("\t \r\n")); assertEquals(NEUTRAL, BidiUtils.getUnicodeDir("123")); assertEquals(NEUTRAL, BidiUtils.getUnicodeDir(" 123-()")); } @Test public void testGetUnicodeDir_LtrFirst() { assertEquals(LTR, BidiUtils.getUnicodeDir("\t a")); assertEquals(LTR, BidiUtils.getUnicodeDir("\t a " + HE)); } @Test public void testGetUnicodeDir_RtlFirst() { assertEquals(RTL, BidiUtils.getUnicodeDir("\t " + HE)); assertEquals(RTL, BidiUtils.getUnicodeDir("\t " + HE + " a")); } @Test public void testGetUnicodeDir_IgnoreEmbeddings() { assertEquals(LTR, BidiUtils.getUnicodeDir(RLE + PDF + "x")); assertEquals(RTL, BidiUtils.getUnicodeDir(LRE + HE + PDF + "x")); assertEquals(LTR, BidiUtils.getUnicodeDir(RLO + PDF + "x")); assertEquals(RTL, BidiUtils.getUnicodeDir(LRO + HE + PDF + "x")); assertEquals(RTL, BidiUtils.getUnicodeDir(LRE + PDF + HE)); assertEquals(LTR, BidiUtils.getUnicodeDir(RLE + "x" + PDF + HE)); assertEquals(RTL, BidiUtils.getUnicodeDir(LRO + PDF + HE)); assertEquals(LTR, BidiUtils.getUnicodeDir(RLO + "x" + PDF + HE)); } @Test public void testGetUnicodeDirOfHtml_MarkupSkipped() { assertEquals(LTR, BidiUtils.getUnicodeDir("<a tag>" + HE)); assertEquals(RTL, BidiUtils.getUnicodeDir("<a tag>" + HE, true)); assertEquals(RTL, BidiUtils.getUnicodeDir("<a x=\"y>\" tag>" + HE, true)); assertEquals(RTL, BidiUtils.getUnicodeDir("<a x=\"<y>\" tag>" + HE, true)); assertEquals(RTL, BidiUtils.getUnicodeDir("<a x='<y>' tag>" + HE, true)); assertEquals(LTR, BidiUtils.getUnicodeDir("<a x=\"<y>\" tag>a" + HE, true)); assertEquals(RTL, BidiUtils.getUnicodeDir("<a x=\"<y>\" tag><b>" + HE, true)); assertEquals(LTR, BidiUtils.getUnicodeDir("<notatag", true)); } @Test public void testGetUnicodeDirOfHtml_EntitySkipped() { assertEquals(NEUTRAL, BidiUtils.getUnicodeDir(" ", true)); // TODO: Uncomment these lines and rename test to ...Parsed() when we start to map entities to // the characters for which they stand. // assertEquals(RTL, BidiUtils.getUnicodeDir(" ‏", true)); // assertEquals(LTR, BidiUtils.getUnicodeDir(" a‏", true)); // assertEquals(LTR, BidiUtils.getUnicodeDir("‏")); // assertEquals(RTL, BidiUtils.getUnicodeDir("‏", true)); // assertEquals(LTR, BidiUtils.getUnicodeDir("&nosuchentity;", true)); } @Test public void testGetEntryDir_NeutralText() { assertEquals(NEUTRAL, BidiUtils.getEntryDir("")); assertEquals(NEUTRAL, BidiUtils.getEntryDir("\t \r\n")); assertEquals(NEUTRAL, BidiUtils.getEntryDir("123")); assertEquals(NEUTRAL, BidiUtils.getEntryDir(" 123-()")); } @Test public void testGetEntryDir_LtrFirst() { assertEquals(LTR, BidiUtils.getEntryDir("a")); assertEquals(LTR, BidiUtils.getEntryDir("\t a")); assertEquals(LTR, BidiUtils.getEntryDir("\t abc")); assertEquals(LTR, BidiUtils.getEntryDir("\t a " + HE)); assertEquals(LTR, BidiUtils.getEntryDir("\t a" + HE)); assertEquals(LTR, BidiUtils.getEntryDir("\t a " + HE + " " + HE + HE)); assertEquals(LTR, BidiUtils.getEntryDir("http://www.google.com " + HE)); } @Test public void testGetEntryDir_RtlFirst() { assertEquals(RTL, BidiUtils.getEntryDir(HE)); assertEquals(RTL, BidiUtils.getEntryDir("\t " + HE)); assertEquals(RTL, BidiUtils.getEntryDir("\t " + HE + HE + HE)); assertEquals(RTL, BidiUtils.getEntryDir("\t " + HE + " a")); assertEquals(RTL, BidiUtils.getEntryDir("\t " + HE + "a")); assertEquals(RTL, BidiUtils.getEntryDir("\t " + HE + " a abc")); } @Test public void testGetEntryDir_EmptyEmbeddingIgnored() { assertEquals(LTR, BidiUtils.getEntryDir(RLE + PDF + "a")); assertEquals(LTR, BidiUtils.getEntryDir(RLE + BN + PDF + "a")); assertEquals(LTR, BidiUtils.getEntryDir(RLO + PDF + "a")); assertEquals(LTR, BidiUtils.getEntryDir(RLO + BN + PDF + "a")); assertEquals(RTL, BidiUtils.getEntryDir(LRE + PDF + HE)); assertEquals(RTL, BidiUtils.getEntryDir(LRE + BN + PDF + HE)); assertEquals(RTL, BidiUtils.getEntryDir(LRO + PDF + HE)); assertEquals(RTL, BidiUtils.getEntryDir(LRO + BN + PDF + HE)); } @Test public void testGetEntryDir_NonEmptyLtrEmbeddingFirst() { assertEquals(LTR, BidiUtils.getEntryDir(LRE + "." + PDF + HE)); assertEquals(LTR, BidiUtils.getEntryDir(LRE + HE + PDF + HE)); assertEquals(LTR, BidiUtils.getEntryDir(RLE + PDF + LRE + HE + PDF + HE)); assertEquals(LTR, BidiUtils.getEntryDir(LRE + RLE + PDF + HE + PDF + HE)); assertEquals(LTR, BidiUtils.getEntryDir(LRE + HE + RLE + HE + PDF + PDF + HE)); assertEquals(LTR, BidiUtils.getEntryDir(RLE + LRE + HE + PDF + HE + PDF + HE)); assertEquals(LTR, BidiUtils.getEntryDir(RLE + LRE + RLE + PDF + HE + PDF + HE + PDF + HE)); assertEquals( LTR, BidiUtils.getEntryDir( RLE + LRE + RLE + BN + RLO + BN + PDF + BN + PDF + RLE + PDF + RLE + PDF + HE + PDF + HE + PDF + HE)); assertEquals(LTR, BidiUtils.getEntryDir(LRO + "." + PDF + HE)); assertEquals(LTR, BidiUtils.getEntryDir(LRO + HE + PDF + HE)); assertEquals(LTR, BidiUtils.getEntryDir(RLE + PDF + LRO + HE + PDF + HE)); assertEquals(LTR, BidiUtils.getEntryDir(LRO + RLE + PDF + HE + PDF + HE)); assertEquals(LTR, BidiUtils.getEntryDir(LRO + HE + RLE + HE + PDF + PDF + HE)); assertEquals(LTR, BidiUtils.getEntryDir(RLE + LRO + HE + PDF + HE + PDF + HE)); assertEquals(LTR, BidiUtils.getEntryDir(RLE + LRO + RLE + PDF + HE + PDF + HE + PDF + HE)); assertEquals( LTR, BidiUtils.getEntryDir( RLE + LRO + RLE + BN + RLO + BN + PDF + BN + PDF + RLE + PDF + RLE + PDF + HE + PDF + HE + PDF + HE)); } @Test public void testGetEntryDir_NonEmptyRtlEmbeddingFirst() { assertEquals(RTL, BidiUtils.getEntryDir(RLE + "." + PDF + "a")); assertEquals(RTL, BidiUtils.getEntryDir(RLE + "a" + PDF + "a")); assertEquals(RTL, BidiUtils.getEntryDir(LRE + PDF + RLE + "a" + PDF + "a")); assertEquals(RTL, BidiUtils.getEntryDir(RLE + LRE + PDF + "a" + PDF + "a")); assertEquals(RTL, BidiUtils.getEntryDir(RLE + "a" + LRE + "a" + PDF + PDF + "a")); assertEquals(RTL, BidiUtils.getEntryDir(LRE + RLE + "a" + PDF + "a" + PDF + "a")); assertEquals(RTL, BidiUtils.getEntryDir(LRE + RLE + LRE + PDF + "a" + PDF + "a" + PDF + "a")); assertEquals( RTL, BidiUtils.getEntryDir( LRE + RLE + LRE + BN + LRO + BN + PDF + BN + PDF + LRE + PDF + LRE + PDF + "a" + PDF + "a" + PDF + "a")); assertEquals(RTL, BidiUtils.getEntryDir(RLO + "." + PDF + "a")); assertEquals(RTL, BidiUtils.getEntryDir(RLO + "a" + PDF + "a")); assertEquals(RTL, BidiUtils.getEntryDir(LRE + PDF + RLO + "a" + PDF + "a")); assertEquals(RTL, BidiUtils.getEntryDir(RLO + LRE + PDF + "a" + PDF + "a")); assertEquals(RTL, BidiUtils.getEntryDir(RLO + "a" + LRE + "a" + PDF + PDF + "a")); assertEquals(RTL, BidiUtils.getEntryDir(LRE + RLO + "a" + PDF + "a" + PDF + "a")); assertEquals(RTL, BidiUtils.getEntryDir(LRE + RLO + LRE + PDF + "a" + PDF + "a" + PDF + "a")); assertEquals( RTL, BidiUtils.getEntryDir( LRE + RLO + LRE + BN + LRO + BN + PDF + BN + PDF + LRE + PDF + LRE + PDF + "a" + PDF + "a" + PDF + "a")); } @Test public void testGetEntryDirOfHtml_MarkupSkipped() { assertEquals(LTR, BidiUtils.getEntryDir("<a tag>" + HE)); assertEquals(RTL, BidiUtils.getEntryDir("<a tag>" + HE, true)); assertEquals(RTL, BidiUtils.getEntryDir("<a x=y tag>" + HE, true)); assertEquals(RTL, BidiUtils.getEntryDir("<a x=\"y>\" tag>" + HE, true)); assertEquals(RTL, BidiUtils.getEntryDir("<a x=\"<y>\" tag>" + HE, true)); assertEquals(RTL, BidiUtils.getEntryDir("<a x='<y>' tag>" + HE, true)); assertEquals(LTR, BidiUtils.getEntryDir("<a x=\"<y>\" tag>a" + HE, true)); assertEquals(RTL, BidiUtils.getEntryDir("<a x=\"<y>\" tag><b>" + HE, true)); assertEquals(LTR, BidiUtils.getEntryDir("<notatag", true)); } @Test public void testGetEntryDirOfHtml_EntitySkipped() { assertEquals(NEUTRAL, BidiUtils.getEntryDir(" ", true)); // TODO: Uncomment these lines and rename test to ...Parsed() when we start to map entities to // the characters for which they stand. // assertEquals(LTR, BidiUtils.getEntryDir("‏")); // assertEquals(RTL, BidiUtils.getEntryDir("‏", true)); // assertEquals(RTL, BidiUtils.getEntryDir("!!!!‏hello", true)); // assertEquals(RTL, BidiUtils.getEntryDir(" ‏", true)); // assertEquals(LTR, BidiUtils.getEntryDir(" a‏", true)); // assertEquals(LTR, BidiUtils.getEntryDir("&nosuchentity;", true)); } @Test public void testGetExitDir_NeutralText() { assertEquals(NEUTRAL, BidiUtils.getExitDir("")); assertEquals(NEUTRAL, BidiUtils.getExitDir("\t \r\n")); assertEquals(NEUTRAL, BidiUtils.getExitDir("123")); assertEquals(NEUTRAL, BidiUtils.getExitDir(" 123-()")); } @Test public void testGetExitDir_LtrLast() { assertEquals(LTR, BidiUtils.getExitDir("a")); assertEquals(LTR, BidiUtils.getExitDir("a \t")); assertEquals(LTR, BidiUtils.getExitDir("abc \t")); assertEquals(LTR, BidiUtils.getExitDir(HE + " a \t")); assertEquals(LTR, BidiUtils.getExitDir(HE + "a \t")); assertEquals(LTR, BidiUtils.getExitDir(HE + HE + " " + HE + " a \t")); assertEquals(LTR, BidiUtils.getExitDir(HE + " http://www.google.com")); } @Test public void testGetExitDir_RtlLast() { assertEquals(RTL, BidiUtils.getExitDir(HE)); assertEquals(RTL, BidiUtils.getExitDir(HE + " \t")); assertEquals(RTL, BidiUtils.getExitDir(HE + HE + HE + " \t")); assertEquals(RTL, BidiUtils.getExitDir("a " + HE + " \t")); assertEquals(RTL, BidiUtils.getExitDir("a" + HE + " \t")); assertEquals(RTL, BidiUtils.getExitDir("abc a " + HE + " \t")); } @Test public void testGetExitDir_EmptyEmbeddingIgnored() { assertEquals(LTR, BidiUtils.getExitDir("a" + RLE + PDF)); assertEquals(LTR, BidiUtils.getExitDir("a" + RLE + BN + PDF)); assertEquals(LTR, BidiUtils.getExitDir("a" + RLO + PDF)); assertEquals(LTR, BidiUtils.getExitDir("a" + RLO + BN + PDF)); assertEquals(RTL, BidiUtils.getExitDir(HE + LRE + PDF)); assertEquals(RTL, BidiUtils.getExitDir(HE + LRE + BN + PDF)); assertEquals(RTL, BidiUtils.getExitDir(HE + LRO + PDF)); assertEquals(RTL, BidiUtils.getExitDir(HE + LRO + BN + PDF)); } @Test public void testGetExitDir_NonEmptyLtrEmbeddingLast() { assertEquals(LTR, BidiUtils.getExitDir(HE + LRE + "." + PDF)); assertEquals(LTR, BidiUtils.getExitDir(HE + LRE + HE + PDF)); assertEquals(LTR, BidiUtils.getExitDir(HE + LRE + HE + PDF + RLE + PDF)); assertEquals(LTR, BidiUtils.getExitDir(HE + LRE + HE + RLE + PDF + PDF)); assertEquals(LTR, BidiUtils.getExitDir(HE + LRE + RLE + HE + PDF + HE + PDF)); assertEquals(LTR, BidiUtils.getExitDir(HE + RLE + HE + LRE + HE + PDF + PDF)); assertEquals(LTR, BidiUtils.getExitDir(HE + RLE + HE + LRE + HE + RLE + PDF + PDF + PDF)); assertEquals(LTR, BidiUtils.getExitDir(HE + LRO + "." + PDF)); assertEquals(LTR, BidiUtils.getExitDir(HE + LRO + HE + PDF)); assertEquals(LTR, BidiUtils.getExitDir(HE + LRO + HE + PDF + RLE + PDF)); assertEquals(LTR, BidiUtils.getExitDir(HE + LRO + HE + RLE + PDF + PDF)); assertEquals(LTR, BidiUtils.getExitDir(HE + LRO + RLE + HE + PDF + HE + PDF)); assertEquals(LTR, BidiUtils.getExitDir(HE + RLE + HE + LRO + HE + PDF + PDF)); assertEquals(LTR, BidiUtils.getExitDir(HE + RLE + HE + LRO + HE + RLE + PDF + PDF + PDF)); } @Test public void testGetExitDir_NonEmptyRtlEmbeddingLast() { assertEquals(RTL, BidiUtils.getExitDir("a" + RLE + "." + PDF)); assertEquals(RTL, BidiUtils.getExitDir("a" + RLE + "a" + PDF)); assertEquals(RTL, BidiUtils.getExitDir("a" + RLE + "a" + PDF + LRE + PDF)); assertEquals(RTL, BidiUtils.getExitDir("a" + RLE + "a" + LRE + PDF + PDF)); assertEquals(RTL, BidiUtils.getExitDir("a" + RLE + LRE + "a" + PDF + "a" + PDF)); assertEquals(RTL, BidiUtils.getExitDir("a" + LRE + "a" + RLE + "a" + PDF + PDF)); assertEquals(RTL, BidiUtils.getExitDir("a" + LRE + "a" + RLE + "a" + LRE + PDF + PDF + PDF)); assertEquals(RTL, BidiUtils.getExitDir("a" + RLO + "." + PDF)); assertEquals(RTL, BidiUtils.getExitDir("a" + RLO + "a" + PDF)); assertEquals(RTL, BidiUtils.getExitDir("a" + RLO + "a" + PDF + LRE + PDF)); assertEquals(RTL, BidiUtils.getExitDir("a" + RLO + "a" + LRE + PDF + PDF)); assertEquals(RTL, BidiUtils.getExitDir("a" + RLO + LRE + "a" + PDF + "a" + PDF)); assertEquals(RTL, BidiUtils.getExitDir("a" + LRE + "a" + RLO + "a" + PDF + PDF)); assertEquals(RTL, BidiUtils.getExitDir("a" + LRE + "a" + RLO + "a" + LRE + PDF + PDF + PDF)); } @Test public void testGetExitDirOfHtml_MarkupSkipped() { assertEquals(LTR, BidiUtils.getExitDir(HE + "<a tag>")); assertEquals(RTL, BidiUtils.getExitDir(HE + "<a tag>", true)); assertEquals(RTL, BidiUtils.getExitDir(HE + "<a x=y tag>", true)); assertEquals(RTL, BidiUtils.getExitDir(HE + "<a x=\"y>\" tag>", true)); assertEquals(RTL, BidiUtils.getExitDir(HE + "<a x=\"<y>\" tag>", true)); assertEquals(RTL, BidiUtils.getExitDir(HE + "<a x='<y>' tag>", true)); assertEquals(LTR, BidiUtils.getExitDir(HE + "a<a x=\"<y>\" tag>", true)); assertEquals(RTL, BidiUtils.getExitDir(HE + "<a x=\"<y>\" tag><b>", true)); assertEquals(LTR, BidiUtils.getExitDir("<notatag", true)); } @Test public void testGetExitDirOfHtml_EntitySkipped() { assertEquals(NEUTRAL, BidiUtils.getExitDir(" ", true)); // TODO: Uncomment these lines and rename test to ...Parsed() when we start to map entities to // the characters for which they stand. // assertEquals(LTR, BidiUtils.getExitDir("‏")); // assertEquals(RTL, BidiUtils.getExitDir("‏", true)); // assertEquals(RTL, BidiUtils.getExitDir("hello‏!!!!", true)); // assertEquals(RTL, BidiUtils.getExitDir("‏ ", true)); // assertEquals(LTR, BidiUtils.getExitDir("‏a ", true)); // assertEquals(LTR, BidiUtils.getExitDir("&nosuchentity;", true)); } private Dir estimateTextDir(String s) { return BidiUtils.estimateDirection(s, false); } private Dir estimateHtmlDir(String s) { return BidiUtils.estimateDirection(s, true); } // The following test is basically superseded by the more detailed and thorough tests below, but // more tests are always better. @Test public void testEstimateDirection_Old() { assertEquals(NEUTRAL, estimateTextDir("")); assertEquals(NEUTRAL, estimateTextDir(" ")); assertEquals(NEUTRAL, estimateTextDir("! (...)")); assertEquals(LTR, estimateTextDir("Pure Ascii content")); assertEquals(LTR, estimateTextDir("-17.0%")); assertEquals(LTR, estimateTextDir("http://foo/bar/")); assertEquals(LTR, estimateTextDir("http://foo/bar/?s=" + Strings.repeat(HE, 24))); assertEquals(LTR, estimateTextDir(LRO + HE + HE + PDF)); assertEquals(RTL, estimateTextDir(HE)); assertEquals(RTL, estimateTextDir("9 " + HE + " -> 17.5, 23, 45, 19")); // We want to consider URLs "weakly LTR" like numbers, so they do not affect the estimation // if there are any strong directional words around. This should work regardless of the number // of spaces preceding the URL (which is a concern in the implementation.) assertEquals( RTL, estimateTextDir( "http://foo/bar/ " + HE + " http://foo2/bar/ http://foo/bar3/ http://foo4/bar/")); assertEquals(RTL, estimateTextDir(RLO + "foo" + PDF)); assertEquals( RTL, estimateTextDir( "\u05d0\u05d9\u05df \u05de\u05de\u05e9 " + "\u05de\u05d4 \u05dc\u05e8\u05d0\u05d5\u05ea: " + "\u05dc\u05d0 \u05e6\u05d9\u05dc\u05de\u05ea\u05d9 " + "\u05d4\u05e8\u05d1\u05d4 \u05d5\u05d2\u05dd \u05d0" + "\u05dd \u05d4\u05d9\u05d9\u05ea\u05d9 \u05de\u05e6\u05dc" + "\u05dd, \u05d4\u05d9\u05d4 \u05e9\u05dd")); assertEquals( RTL, estimateTextDir( "\u05db\u05d0\u05df - http://geek.co.il/gallery/v/2007-06" + " - \u05d0\u05d9\u05df \u05de\u05de\u05e9 \u05de\u05d4 " + "\u05dc\u05e8\u05d0\u05d5\u05ea: \u05dc\u05d0 \u05e6" + "\u05d9\u05dc\u05de\u05ea\u05d9 \u05d4\u05e8\u05d1\u05d4 " + "\u05d5\u05d2\u05dd \u05d0\u05dd \u05d4\u05d9\u05d9\u05ea" + "\u05d9 \u05de\u05e6\u05dc\u05dd, \u05d4\u05d9\u05d4 " + "\u05e9\u05dd \u05d1\u05e2\u05d9\u05e7\u05e8 \u05d4\u05e8" + "\u05d1\u05d4 \u05d0\u05e0\u05e9\u05d9\u05dd. \u05de" + "\u05d4 \u05e9\u05db\u05df - \u05d0\u05e4\u05e9\u05e8 " + "\u05dc\u05e0\u05e6\u05dc \u05d0\u05ea \u05d4\u05d4 " + "\u05d3\u05d6\u05de\u05e0\u05d5\u05ea \u05dc\u05d4\u05e1" + "\u05ea\u05db\u05dc \u05e2\u05dc \u05db\u05de\u05d4 " + "\u05ea\u05de\u05d5\u05e0\u05d5\u05ea \u05de\u05e9\u05e2" + "\u05e9\u05e2\u05d5\u05ea \u05d9\u05e9\u05e0\u05d5\u05ea " + "\u05d9\u05d5\u05ea\u05e8 \u05e9\u05d9\u05e9 \u05dc" + "\u05d9 \u05d1\u05d0\u05ea\u05e8")); assertEquals( RTL, estimateTextDir("CAPTCHA \u05de\u05e9\u05d5\u05db\u05dc\u05dc \u05de\u05d3\u05d9?")); assertEquals(LTR, estimateTextDir("CAPTCHA blah \u05de\u05d3\u05d9?")); assertEquals(RTL, estimateTextDir(HE + HE + " " + LRO + HE + HE + PDF)); assertEquals( LTR, estimateTextDir(HE + HE + " " + LRO + HE + HE + PDF + " " + LRO + HE + HE + PDF)); assertEquals(RTL, estimateTextDir("hello " + RLO + "foo" + PDF + " " + RLO + "bar" + PDF)); assertEquals( RTL, estimateTextDir( "Yes Prime Minister \u05e2\u05d3\u05db\u05d5\u05df. " + "\u05e9\u05d0\u05dc\u05d5 \u05d0\u05d5\u05ea\u05d9 " + "\u05de\u05d4 \u05d0\u05e0\u05d9 \u05e8\u05d5\u05e6" + "\u05d4 \u05de\u05ea\u05e0\u05d4 \u05dc\u05d7\u05d2")); assertEquals( RTL, estimateTextDir( "17.4.02 \u05e9\u05e2\u05d4:13-20 .15-00 .\u05dc\u05d0 " + "\u05d4\u05d9\u05d9\u05ea\u05d9 \u05db\u05d0\u05df.")); assertEquals( RTL, estimateTextDir( "5710 5720 5730. \u05d4\u05d3\u05dc\u05ea. " + "\u05d4\u05e0\u05e9\u05d9\u05e7\u05d4")); assertEquals( RTL, estimateTextDir( "\u05d4\u05d3\u05dc\u05ea http://www.google.com " + "http://www.gmail.com")); assertEquals(LTR, estimateTextDir("\u05d4\u05d3\u05dc\u05ea <some quite nasty html mark up>")); assertEquals(RTL, estimateHtmlDir("\u05d4\u05d3\u05dc\u05ea <some quite nasty html mark up>")); assertEquals(LTR, estimateTextDir("\u05d4\u05d3\u05dc\u05ea & < >")); assertEquals(RTL, estimateHtmlDir("\u05d4\u05d3\u05dc\u05ea & < >")); } @Test public void testEstimateDirection_English() { String s = // 21 ltr, 0 rtl, 0 numeric "Once upon a midnight dreary,\n" + "While I nodded, weak and weary,\n" + "Over many a quaint and curious volume of forgotten lore..."; assertEquals(LTR, estimateTextDir(s)); assertEquals(LTR, estimateHtmlDir(s)); } @Test public void testEstimateDirection_Hebrew() { // s has 0 ltr, 3 rtl, 0 numeric String s = "\u05D0\u05D1\u05D2\u05D3 \u05D4\u05D5\u05D6 ... \u05D7\u05D8"; assertEquals(RTL, estimateTextDir(s)); assertEquals(RTL, estimateHtmlDir(s)); } @Test public void testEstimateDirection_Arabic() { // s has 0 ltr, 3 rtl, 0 numeric String s = "\u0627\u0628\u0629\u062A\u062B \u062C\u062D ... \u062E\u062F!"; assertEquals(RTL, estimateTextDir(s)); assertEquals(RTL, estimateHtmlDir(s)); } @Test public void testEstimateDirection_Chinese() { // s has 1 ltr, 0 rtl, 0 numeric String s = "\u9910!"; assertEquals(LTR, estimateTextDir(s)); assertEquals(LTR, estimateHtmlDir(s)); } @Test public void testEstimateDirection_Neutral() { String s = " ..././.\\*(())!#%% \r\n\t ];'\\;'@#$"; assertEquals(NEUTRAL, estimateTextDir(s)); assertEquals(NEUTRAL, estimateHtmlDir(s)); } @Test public void testEstimateDirection_EmptyString() { assertEquals(NEUTRAL, estimateTextDir("")); assertEquals(NEUTRAL, estimateHtmlDir("")); } @Test public void testEstimateDirection_Mixed() { assertEquals(RTL, estimateTextDir("supercalifragilisticexpialidocious " + HE)); assertEquals(RTL, estimateHtmlDir("supercalifragilisticexpialidocious " + HE)); assertEquals(LTR, estimateTextDir("a supercalifragilisticexpialidocious " + HE)); assertEquals(LTR, estimateHtmlDir("a supercalifragilisticexpialidocious " + HE)); assertEquals(RTL, estimateTextDir("a/b/c.d.e.f@g-h " + HE)); assertEquals(RTL, estimateHtmlDir("a/b/c.d.e.f@g-h " + HE)); assertEquals(RTL, estimateTextDir("a/b/c.d.e.f@g-h " + HE)); assertEquals(RTL, estimateHtmlDir("a/b/c.d.e.f@g-h " + HE)); assertEquals(RTL, estimateTextDir("HTML \u0648Google")); assertEquals(RTL, estimateHtmlDir("HTML \u0648Google")); assertEquals(RTL, estimateTextDir("HTML \u05D5-Google")); assertEquals(RTL, estimateHtmlDir("HTML \u05D5-Google")); assertEquals(LTR, estimateTextDir("we love " + HE + " +10!")); assertEquals(LTR, estimateHtmlDir("we love " + HE + " +10!")); assertEquals(LTR, estimateTextDir("we love " + HE + " so")); assertEquals(LTR, estimateHtmlDir("we love " + HE + " so")); assertEquals(RTL, estimateTextDir(HE + " cool 1!")); assertEquals(RTL, estimateHtmlDir(HE + " cool 1!")); assertEquals(RTL, estimateTextDir(HE + " cool " + HE)); assertEquals(RTL, estimateHtmlDir(HE + " cool " + HE)); } @Test public void testEstimateDirection_MixedWithHan() { assertEquals(RTL, estimateTextDir(HAN + ' ' + HE)); assertEquals(RTL, estimateHtmlDir(HAN + ' ' + HE)); } @Test public void testEstimateDirection_PersianNumeric() { assertEquals(NEUTRAL, estimateTextDir("\u06F1")); assertEquals(NEUTRAL, estimateHtmlDir("\u06F1")); assertEquals(NEUTRAL, estimateTextDir("\u06F1\u06F2\u06F3")); assertEquals(NEUTRAL, estimateHtmlDir("\u06F1\u06F2\u06F3")); assertEquals(NEUTRAL, estimateTextDir("\u06F1\u06F2\u06F3,\u06F4\u06F5\u06F6.\u06F7\u06F8")); assertEquals(NEUTRAL, estimateHtmlDir("\u06F1\u06F2\u06F3,\u06F4\u06F5\u06F6.\u06F7\u06F8")); assertEquals(NEUTRAL, estimateTextDir("\u06F1:\u06F2")); assertEquals(NEUTRAL, estimateHtmlDir("\u06F1:\u06F2")); assertEquals(NEUTRAL, estimateTextDir("\u06F1" + NBSP + "\u06F2")); assertEquals(NEUTRAL, estimateHtmlDir("\u06F1" + NBSP + "\u06F2")); assertEquals(NEUTRAL, estimateTextDir("\u06F1-")); assertEquals(NEUTRAL, estimateHtmlDir("\u06F1-")); assertEquals(NEUTRAL, estimateTextDir("+ \u06F1")); assertEquals(NEUTRAL, estimateHtmlDir("+ \u06F1")); assertEquals(NEUTRAL, estimateTextDir("- \u06F1")); assertEquals(NEUTRAL, estimateHtmlDir("- \u06F1")); assertEquals(NEUTRAL, estimateTextDir("-/\u06F1")); assertEquals(NEUTRAL, estimateHtmlDir("-/\u06F1")); assertEquals(NEUTRAL, estimateTextDir("-*\u06F1")); assertEquals(NEUTRAL, estimateHtmlDir("-*\u06F1")); assertEquals(LTR, estimateTextDir("-\u06F1")); assertEquals(LTR, estimateHtmlDir("-\u06F1")); assertEquals(LTR, estimateTextDir("+\u06F1")); assertEquals(LTR, estimateHtmlDir("+\u06F1")); assertEquals(LTR, estimateTextDir(MINUS + "\u06F1")); assertEquals(LTR, estimateHtmlDir(MINUS + "\u06F1")); assertEquals(LTR, estimateTextDir("(-\u06F1)")); assertEquals(LTR, estimateHtmlDir("(-\u06F1)")); assertEquals(LTR, estimateTextDir("* '+\u06F1\u06F2.\u06F3\u06F4'?")); assertEquals(LTR, estimateHtmlDir("* '+\u06F1\u06F2.\u06F3\u06F4'?")); assertEquals(LTR, estimateTextDir("--\u06F1")); assertEquals(LTR, estimateHtmlDir("--\u06F1")); assertEquals(LTR, estimateTextDir("\u06F1\u00D7\u06F1\u06F0^-\u06F6")); assertEquals(LTR, estimateHtmlDir("\u06F1\u00D7\u06F1\u06F0^-\u06F6")); assertEquals( LTR, estimateTextDir("+\u06F1 \u06F9 \u06F2\u06F3\u06F4-\u06F5\u06F6\u06F7\u06F8")); assertEquals( LTR, estimateHtmlDir("+\u06F1 \u06F9 \u06F2\u06F3\u06F4-\u06F5\u06F6\u06F7\u06F8")); assertEquals(LTR, estimateTextDir("+\u06F1\u06F9\u06F2\u06F3\u06F4\u06F5\u06F6\u06F7\u06F8")); assertEquals(LTR, estimateHtmlDir("+\u06F1\u06F9\u06F2\u06F3\u06F4\u06F5\u06F6\u06F7\u06F8")); assertEquals(LTR, estimateTextDir("\u06F0\u06F1 \u06F2\u06F3\u06F4-\u06F5\u06F6\u06F7\u06F8")); assertEquals(LTR, estimateHtmlDir("\u06F0\u06F1 \u06F2\u06F3\u06F4-\u06F5\u06F6\u06F7\u06F8")); assertEquals(LTR, estimateTextDir("\u06F2\u06F3\u06F4-\u06F5\u06F6\u06F7\u06F8")); assertEquals(LTR, estimateHtmlDir("\u06F2\u06F3\u06F4-\u06F5\u06F6\u06F7\u06F8")); assertEquals(LTR, estimateTextDir("\u06F2\u06F3\u06F4" + HYPHEN + "\u06F5\u06F6\u06F7\u06F8")); assertEquals(LTR, estimateHtmlDir("\u06F2\u06F3\u06F4" + HYPHEN + "\u06F5\u06F6\u06F7\u06F8")); assertEquals(LTR, estimateTextDir("\u06F2\u06F3/\u06F4\u06F5")); assertEquals(LTR, estimateHtmlDir("\u06F2\u06F3/\u06F4\u06F5")); assertEquals(LTR, estimateTextDir("\u06F1 \u06F2 \u06F3 \u06F4 \u06F5 \u06F6")); assertEquals(LTR, estimateHtmlDir("\u06F1 \u06F2 \u06F3 \u06F4 \u06F5 \u06F6")); assertEquals(LTR, estimateTextDir("\u06F1" + TIMES + "\u06F2")); assertEquals(LTR, estimateHtmlDir("\u06F1" + TIMES + "\u06F2")); assertEquals(LTR, estimateTextDir("\u06F1 " + TIMES + " \u06F2")); assertEquals(LTR, estimateHtmlDir("\u06F1 " + TIMES + " \u06F2")); assertEquals(LTR, estimateTextDir("\u06F1" + NBSP + TIMES + NBSP + "\u06F2")); assertEquals(LTR, estimateHtmlDir("\u06F1" + NBSP + TIMES + NBSP + "\u06F2")); assertEquals(RTL, estimateTextDir("\u06F1 \u06F2 \u06F3 \u06F4 \u06F5 \u06F6 " + FA)); assertEquals(RTL, estimateHtmlDir("\u06F1 \u06F2 \u06F3 \u06F4 \u06F5 \u06F6 " + FA)); assertEquals(LTR, estimateTextDir("\u06F1 \u06F2 \u06F3 \u06F4 \u06F5 \u06F6")); assertEquals(LTR, estimateHtmlDir("\u06F1 \u06F2 \u06F3 \u06F4 \u06F5 \u06F6")); } @Test public void testEstimateDirection_ArabicNumeric() { assertEquals(NEUTRAL, estimateTextDir("\u0661")); assertEquals(NEUTRAL, estimateHtmlDir("\u0661")); assertEquals(NEUTRAL, estimateTextDir("\u0661\u0662\u0663")); assertEquals(NEUTRAL, estimateHtmlDir("\u0661\u0662\u0663")); assertEquals(NEUTRAL, estimateTextDir("\u0661\u0662\u0663,\u0664\u0665\u0666.\u0667\u0668")); assertEquals(NEUTRAL, estimateHtmlDir("\u0661\u0662\u0663,\u0664\u0665\u0666.\u0667\u0668")); assertEquals(NEUTRAL, estimateTextDir("\u0661:\u0662")); assertEquals(NEUTRAL, estimateHtmlDir("\u0661:\u0662")); assertEquals(NEUTRAL, estimateTextDir("\u0661" + NBSP + "\u0662")); assertEquals(NEUTRAL, estimateHtmlDir("\u0661" + NBSP + "\u0662")); assertEquals(NEUTRAL, estimateTextDir("\u0661-")); assertEquals(NEUTRAL, estimateHtmlDir("\u0661-")); assertEquals(NEUTRAL, estimateTextDir("+ \u0661")); assertEquals(NEUTRAL, estimateHtmlDir("+ \u0661")); assertEquals(NEUTRAL, estimateTextDir("- \u0661")); assertEquals(NEUTRAL, estimateHtmlDir("- \u0661")); assertEquals(NEUTRAL, estimateTextDir("-/\u0661")); assertEquals(NEUTRAL, estimateHtmlDir("-/\u0661")); assertEquals(NEUTRAL, estimateTextDir("-*\u0661")); assertEquals(NEUTRAL, estimateHtmlDir("-*\u0661")); assertEquals(RTL, estimateTextDir("-\u0661")); assertEquals(RTL, estimateHtmlDir("-\u0661")); assertEquals(RTL, estimateTextDir(MINUS + "\u0661")); assertEquals(RTL, estimateHtmlDir(MINUS + "\u0661")); assertEquals(RTL, estimateTextDir("(-\u0661)")); assertEquals(RTL, estimateHtmlDir("(-\u0661)")); assertEquals(RTL, estimateTextDir("--\u0661")); assertEquals(RTL, estimateHtmlDir("--\u0661")); assertEquals(RTL, estimateTextDir("\u0661\u0627\u0633-\u0666")); assertEquals(RTL, estimateHtmlDir("\u0661\u0627\u0633-\u0666")); assertEquals( LTR, estimateTextDir( "+\u0661" + NBSP + "\u0669" + NBSP + "\u0662\u0663\u0664" + NBSP + "\u0665\u0666\u0667\u0668")); assertEquals( LTR, estimateHtmlDir( "+\u0661" + NBSP + "\u0669" + NBSP + "\u0662\u0663\u0664" + NBSP + "\u0665\u0666\u0667\u0668")); assertEquals(LTR, estimateTextDir("+\u0661\u0669\u0662\u0663\u0664\u0665\u0666\u0667\u0668")); assertEquals(LTR, estimateHtmlDir("+\u0661\u0669\u0662\u0663\u0664\u0665\u0666\u0667\u0668")); assertEquals( LTR, estimateTextDir("+\u0661 \u0669 \u0662\u0663\u0664-\u0665\u0666\u0667\u0668")); assertEquals( LTR, estimateHtmlDir("+\u0661 \u0669 \u0662\u0663\u0664-\u0665\u0666\u0667\u0668")); assertEquals(LTR, estimateTextDir("+\u0661")); assertEquals(LTR, estimateHtmlDir("+\u0661")); assertEquals(LTR, estimateTextDir("* '+\u0661\u0662.\u0663\u0664'?")); assertEquals(LTR, estimateHtmlDir("* '+\u0661\u0662.\u0663\u0664'?")); assertEquals( NEUTRAL, estimateTextDir("\u0660\u0661.\u0662\u0663\u0664.\u0665\u0666\u0667\u0668")); assertEquals( NEUTRAL, estimateHtmlDir("\u0660\u0661.\u0662\u0663\u0664.\u0665\u0666\u0667\u0668")); assertEquals( NEUTRAL, estimateTextDir("\u0660\u0661 \u0662\u0663\u0664-\u0665\u0666\u0667\u0668")); assertEquals( NEUTRAL, estimateHtmlDir("\u0660\u0661 \u0662\u0663\u0664-\u0665\u0666\u0667\u0668")); assertEquals(NEUTRAL, estimateTextDir("\u0662\u0663\u0664-\u0665\u0666\u0667\u0668")); assertEquals(NEUTRAL, estimateHtmlDir("\u0662\u0663\u0664-\u0665\u0666\u0667\u0668")); assertEquals( NEUTRAL, estimateTextDir("\u0662\u0663\u0664" + HYPHEN + "\u0665\u0666\u0667\u0668")); assertEquals( NEUTRAL, estimateHtmlDir("\u0662\u0663\u0664" + HYPHEN + "\u0665\u0666\u0667\u0668")); assertEquals(NEUTRAL, estimateTextDir("\u0662\u0663/\u0664\u0665")); assertEquals(NEUTRAL, estimateHtmlDir("\u0662\u0663/\u0664\u0665")); assertEquals(NEUTRAL, estimateTextDir("\u0661 \u0662 \u0663 \u0664 \u0665 \u0666")); assertEquals(NEUTRAL, estimateHtmlDir("\u0661 \u0662 \u0663 \u0664 \u0665 \u0666")); assertEquals(NEUTRAL, estimateTextDir("\u0661" + TIMES + "\u0662")); assertEquals(NEUTRAL, estimateHtmlDir("\u0661" + TIMES + "\u0662")); assertEquals(NEUTRAL, estimateTextDir("\u0661 " + TIMES + " \u0662")); assertEquals(NEUTRAL, estimateHtmlDir("\u0661 " + TIMES + " \u0662")); assertEquals(NEUTRAL, estimateTextDir("\u0661" + NBSP + TIMES + NBSP + "\u0662")); assertEquals(NEUTRAL, estimateHtmlDir("\u0661" + NBSP + TIMES + NBSP + "\u0662")); assertEquals(RTL, estimateTextDir("\u0661 \u0662 \u0663 \u0664 \u0665 \u0666 " + AR)); assertEquals(RTL, estimateHtmlDir("\u0661 \u0662 \u0663 \u0664 \u0665 \u0666 " + AR)); assertEquals(NEUTRAL, estimateTextDir("\u0661 \u0662 \u0663 \u0664 \u0665 \u0666")); assertEquals(NEUTRAL, estimateHtmlDir("\u0661 \u0662 \u0663 \u0664 \u0665 \u0666")); } @Test public void testEstimateDirection_AsciiNumeric() { assertEquals(NEUTRAL, estimateTextDir("1")); assertEquals(NEUTRAL, estimateHtmlDir("1")); assertEquals(NEUTRAL, estimateTextDir("123")); assertEquals(NEUTRAL, estimateHtmlDir("123")); assertEquals(NEUTRAL, estimateTextDir("123,456.78")); assertEquals(NEUTRAL, estimateHtmlDir("123,456.78")); assertEquals(NEUTRAL, estimateTextDir("1:2")); assertEquals(NEUTRAL, estimateHtmlDir("1:2")); assertEquals(NEUTRAL, estimateTextDir("1" + NBSP + "2")); assertEquals(NEUTRAL, estimateHtmlDir("1" + NBSP + "2")); assertEquals(NEUTRAL, estimateTextDir("1-")); assertEquals(NEUTRAL, estimateHtmlDir("1-")); assertEquals(NEUTRAL, estimateTextDir("+ 1")); assertEquals(NEUTRAL, estimateHtmlDir("+ 1")); assertEquals(NEUTRAL, estimateTextDir("- 1")); assertEquals(NEUTRAL, estimateHtmlDir("- 1")); assertEquals(NEUTRAL, estimateTextDir("-/1")); assertEquals(NEUTRAL, estimateHtmlDir("-/1")); assertEquals(NEUTRAL, estimateTextDir("-*1")); assertEquals(NEUTRAL, estimateHtmlDir("-*1")); assertEquals(LTR, estimateTextDir("-1")); assertEquals(LTR, estimateHtmlDir("-1")); assertEquals(LTR, estimateTextDir("+1")); assertEquals(LTR, estimateHtmlDir("+1")); assertEquals(LTR, estimateTextDir(ALT_PLUS + "1")); assertEquals(LTR, estimateHtmlDir(ALT_PLUS + "1")); assertEquals(LTR, estimateTextDir(MINUS + "1")); assertEquals(LTR, estimateHtmlDir(MINUS + "1")); assertEquals(LTR, estimateTextDir("(-1)")); assertEquals(LTR, estimateHtmlDir("(-1)")); assertEquals(LTR, estimateTextDir("* '+12.34'?")); assertEquals(LTR, estimateHtmlDir("* '+12.34'?")); assertEquals(LTR, estimateTextDir("--1")); assertEquals(LTR, estimateHtmlDir("--1")); assertEquals(LTR, estimateTextDir("1e-6")); assertEquals(LTR, estimateHtmlDir("1e-6")); assertEquals(LTR, estimateTextDir("+1 9 234-5678")); assertEquals(LTR, estimateHtmlDir("+1 9 234-5678")); assertEquals(LTR, estimateTextDir("+192345678")); assertEquals(LTR, estimateHtmlDir("+192345678")); assertEquals(LTR, estimateTextDir("01 234-5678")); assertEquals(LTR, estimateHtmlDir("01 234-5678")); assertEquals(LTR, estimateTextDir("234-5678")); assertEquals(LTR, estimateHtmlDir("234-5678")); assertEquals(LTR, estimateTextDir("234" + HYPHEN + "5678")); assertEquals(LTR, estimateHtmlDir("234" + HYPHEN + "5678")); assertEquals(LTR, estimateTextDir("23/45")); assertEquals(LTR, estimateHtmlDir("23/45")); assertEquals(LTR, estimateTextDir("1 2 3 4 5 6")); assertEquals(LTR, estimateHtmlDir("1 2 3 4 5 6")); assertEquals(LTR, estimateTextDir("1" + TIMES + "2")); assertEquals(LTR, estimateHtmlDir("1" + TIMES + "2")); assertEquals(LTR, estimateTextDir("1 " + TIMES + " 2")); assertEquals(LTR, estimateHtmlDir("1 " + TIMES + " 2")); assertEquals(LTR, estimateTextDir("1" + NBSP + TIMES + NBSP + "2")); assertEquals(LTR, estimateHtmlDir("1" + NBSP + TIMES + NBSP + "2")); assertEquals(RTL, estimateTextDir("1 2 3 4 5 6 " + HE)); assertEquals(RTL, estimateHtmlDir("1 2 3 4 5 6 " + HE)); assertEquals(LTR, estimateTextDir("1 2 3 4 5 6")); assertEquals(LTR, estimateHtmlDir("1 2 3 4 5 6")); } @Test public void testEstimateDirection_HttpUrl() { assertEquals(LTR, estimateTextDir("http://")); assertEquals(LTR, estimateHtmlDir("http://")); assertEquals(LTR, estimateTextDir("http://x")); assertEquals(LTR, estimateHtmlDir("http://x")); assertEquals(LTR, estimateTextDir("http://x/" + HE)); assertEquals(LTR, estimateHtmlDir("http://x/" + HE)); // At least for now, even all-RTL URLs are considered LTR. assertEquals( LTR, estimateTextDir( "http://\u0645\u0648\u0642\u0639.\u0648\u0632\u0627\u0631\u0629-" + "\u0627\u0644\u0627\u062A\u0635\u0627\u0644\u0627\u062A.\u0645\u0635\u0631")); assertEquals( LTR, estimateHtmlDir( "http://\u0645\u0648\u0642\u0639.\u0648\u0632\u0627\u0631\u0629-" + "\u0627\u0644\u0627\u062A\u0635\u0627\u0644\u0627\u062A.\u0645\u0635\u0631")); assertEquals( LTR, estimateTextDir("http://\u0627\u0633\u062A\u0641\u062A\u0627\u0621.\u0645\u0635\u0631")); assertEquals( LTR, estimateHtmlDir("http://\u0627\u0633\u062A\u0641\u062A\u0627\u0621.\u0645\u0635\u0631")); assertEquals(LTR, estimateTextDir("x " + HE + " y")); assertEquals(LTR, estimateHtmlDir("x " + HE + " y")); assertEquals(RTL, estimateTextDir("http:// " + HE + " http://")); assertEquals(RTL, estimateHtmlDir("http:// " + HE + " http://")); assertEquals(RTL, estimateTextDir("http://x " + HE + " http://y")); assertEquals(RTL, estimateHtmlDir("http://x " + HE + " http://y")); assertEquals(LTR, estimateTextDir("http:/ " + HE + " http:/")); assertEquals(LTR, estimateHtmlDir("http:/ " + HE + " http:/")); assertEquals(LTR, estimateTextDir("http://")); assertEquals(LTR, estimateHtmlDir("http://")); assertEquals(LTR, estimateTextDir("http://")); assertEquals(LTR, estimateHtmlDir("http://" + HE)); assertEquals(RTL, estimateTextDir(HE + " http://")); assertEquals(RTL, estimateHtmlDir(HE + " http://")); } @Test public void testEstimateDirection_HttpsUrl() { assertEquals(LTR, estimateTextDir("https://")); assertEquals(LTR, estimateHtmlDir("https://")); assertEquals(LTR, estimateTextDir("https://x")); assertEquals(LTR, estimateHtmlDir("https://x")); assertEquals(LTR, estimateTextDir("x " + HE + " y")); assertEquals(LTR, estimateHtmlDir("x " + HE + " y")); assertEquals(RTL, estimateTextDir("https:// " + HE + " https://")); assertEquals(RTL, estimateHtmlDir("https:// " + HE + " https://")); assertEquals(RTL, estimateTextDir("https://x " + HE + " https://y")); assertEquals(RTL, estimateHtmlDir("https://x " + HE + " https://y")); assertEquals(LTR, estimateTextDir("https:/ " + HE + " https:/")); assertEquals(LTR, estimateHtmlDir("https:/ " + HE + " https:/")); assertEquals(LTR, estimateTextDir("https://")); assertEquals(LTR, estimateHtmlDir("https://")); assertEquals(LTR, estimateTextDir("https://" + HE)); assertEquals(LTR, estimateHtmlDir("https://" + HE)); assertEquals(RTL, estimateTextDir(HE + " https://")); assertEquals(RTL, estimateHtmlDir(HE + " https://")); } @Test public void testEstimateDirection_Embed() { assertEquals(NEUTRAL, estimateTextDir(RLE + HE + PDF)); assertEquals(NEUTRAL, estimateHtmlDir(RLE + HE + PDF)); assertEquals(NEUTRAL, estimateTextDir(RLE + HE + PDF)); assertEquals(NEUTRAL, estimateHtmlDir(RLE + HE + PDF)); assertEquals(NEUTRAL, estimateTextDir(RLE + "L T R" + PDF)); assertEquals(NEUTRAL, estimateHtmlDir(RLE + "L T R" + PDF)); assertEquals(NEUTRAL, estimateTextDir(RLE + "L T R" + PDF)); assertEquals(NEUTRAL, estimateHtmlDir(RLE + "L T R" + PDF)); assertEquals(NEUTRAL, estimateTextDir(LRE + HE + PDF)); assertEquals(NEUTRAL, estimateHtmlDir(LRE + HE + PDF)); assertEquals(NEUTRAL, estimateTextDir(LRE + HE + PDF)); assertEquals(NEUTRAL, estimateHtmlDir(LRE + HE + PDF)); assertEquals(NEUTRAL, estimateTextDir(LRE + "." + PDF)); assertEquals(NEUTRAL, estimateHtmlDir(LRE + "." + PDF)); assertEquals(NEUTRAL, estimateTextDir(LRE + "." + PDF)); assertEquals(NEUTRAL, estimateHtmlDir(LRE + "." + PDF)); assertEquals(NEUTRAL, estimateTextDir(LRE + RLE + HE + PDF + "." + PDF)); assertEquals(NEUTRAL, estimateHtmlDir(LRE + RLE + HE + PDF + "." + PDF)); assertEquals(LTR, estimateTextDir("A" + RLE + HE + PDF)); assertEquals(LTR, estimateHtmlDir("A" + RLE + HE + PDF)); assertEquals(LTR, estimateTextDir("A" + RLE + " " + HE + PDF)); assertEquals(LTR, estimateHtmlDir("A" + RLE + " " + HE + PDF)); assertEquals(LTR, estimateTextDir("A " + RLE + HE + PDF)); assertEquals(LTR, estimateHtmlDir("A " + RLE + HE + PDF)); assertEquals(LTR, estimateTextDir(RLE + HE + PDF + "A")); assertEquals(LTR, estimateHtmlDir(RLE + HE + PDF + "A")); assertEquals(RTL, estimateTextDir(HE + PDF + " A")); assertEquals(RTL, estimateHtmlDir(HE + PDF + " A")); assertEquals(LTR, estimateTextDir(HE + PDF + " A A A A A A A A")); assertEquals(LTR, estimateHtmlDir(HE + PDF + " A A A A A A A A")); assertEquals(LTR, estimateTextDir("A" + RLE + HE)); assertEquals(LTR, estimateHtmlDir("A" + RLE + HE)); assertEquals(LTR, estimateTextDir("A" + RLE + " " + HE)); assertEquals(LTR, estimateHtmlDir("A" + RLE + " " + HE)); assertEquals(LTR, estimateTextDir("A " + RLE + HE)); assertEquals(LTR, estimateHtmlDir("A " + RLE + HE)); } @Test public void testEstimateDirection_Override() { assertEquals(RTL, estimateTextDir(RLO + HE + PDF)); assertEquals(RTL, estimateHtmlDir(RLO + HE + PDF)); assertEquals(RTL, estimateTextDir(RLO + HE + PDF)); assertEquals(RTL, estimateHtmlDir(RLO + HE + PDF)); assertEquals(RTL, estimateTextDir(RLO + "L T R" + PDF)); assertEquals(RTL, estimateHtmlDir(RLO + "L T R" + PDF)); assertEquals(RTL, estimateTextDir(RLO + "L T R" + PDF)); assertEquals(RTL, estimateHtmlDir(RLO + "L T R" + PDF)); assertEquals(LTR, estimateTextDir(LRO + HE + PDF)); assertEquals(LTR, estimateHtmlDir(LRO + HE + PDF)); assertEquals(LTR, estimateTextDir(LRO + HE + PDF)); assertEquals(LTR, estimateHtmlDir(LRO + HE + PDF)); assertEquals(RTL, estimateTextDir("A " + RLO + "L T R" + PDF)); assertEquals(RTL, estimateHtmlDir("A " + RLO + "L T R" + PDF)); } @Test public void testEstimateDirection_MarkUp() { assertEquals(LTR, estimateTextDir("<t a=1>")); assertEquals(NEUTRAL, estimateHtmlDir("<t a=1>")); assertEquals(LTR, estimateTextDir("<t a=1>")); assertEquals(NEUTRAL, estimateHtmlDir("<t a=1>")); assertEquals(LTR, estimateTextDir(HE + " <t a=1>")); assertEquals(RTL, estimateHtmlDir(HE + "<t a=1 b=2>")); assertEquals(RTL, estimateHtmlDir(HE + "<t a=1 b=2>")); assertEquals(LTR, estimateHtmlDir("I am " + HE + "<t a=1 b=2>")); assertEquals(LTR, estimateHtmlDir("foo/<b>" + HE + "</b>")); } @Test public void testEstimateDirection_Entity() { assertEquals(LTR, estimateTextDir("...&")); assertEquals(NEUTRAL, estimateHtmlDir("...&")); assertEquals(NEUTRAL, estimateHtmlDir("<span>")); assertEquals(LTR, estimateHtmlDir("<span>")); assertEquals(LTR, estimateHtmlDir("...&a")); assertEquals(LTR, estimateTextDir("a א")); // 32 is space // TODO: Uncomment these lines when we start to map entities to the characters for which they // stand. // assertEquals(RTL, estimateHtmlDir("a א")); // assertEquals(LTR, estimateHtmlDir("a a א")); // assertEquals(RTL, estimateHtmlDir("...&nosuchescape א")); } }