/*
* Copyright 2009 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.assertNull;
import com.google.template.soy.data.Dir;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/** Unit tests for BidiFormatter. */
@RunWith(JUnit4.class)
public class BidiFormatterTest {
private static final Dir RTL = Dir.RTL;
private static final Dir LTR = Dir.LTR;
private static final Dir NEUTRAL = Dir.NEUTRAL;
private static final String EN = "abba";
private static final String EN_TAG = " <br> ";
private static final String HE = "\u05e0\u05e1";
private static final String HE_TAG = " <\u05d0> ";
private static final String LRM = "\u200E";
private static final String RLM = "\u200F";
private static final String LRE = "\u202A";
private static final String RLE = "\u202B";
private static final String PDF = "\u202C";
private static final BidiFormatter LTR_FMT = BidiFormatter.getInstance(LTR);
private static final BidiFormatter RTL_FMT = BidiFormatter.getInstance(RTL);
private static final BidiFormatter UNKNOWN_FMT = BidiFormatter.getInstanceWithNoContext();
private static final BidiFormatter LTR_ALWAYS_SPAN_FMT =
new BidiFormatter.Builder(LTR).alwaysSpan(true).build();
private static final BidiFormatter RTL_ALWAYS_SPAN_FMT =
new BidiFormatter.Builder(RTL).alwaysSpan(true).build();
private static final BidiFormatter UNKNOWN_ALWAYS_SPAN_FMT =
new BidiFormatter.Builder((Dir) null).alwaysSpan(true).build();
private static final BidiFormatter LTR_STEREO_RESET_FMT =
new BidiFormatter.Builder(LTR).stereoReset(true).build();
private static final BidiFormatter RTL_STEREO_RESET_FMT =
new BidiFormatter.Builder(RTL).stereoReset(true).build();
private static final BidiFormatter LTR_STEREO_RESET_ALWAYS_SPAN_FMT =
new BidiFormatter.Builder(LTR).stereoReset(true).alwaysSpan(true).build();
// We might as well try switching the order of the with...() calls.
private static final BidiFormatter RTL_STEREO_RESET_ALWAYS_SPAN_FMT =
new BidiFormatter.Builder(RTL).alwaysSpan(true).stereoReset(true).build();
@Test
public void testGetContextDir() {
assertEquals(LTR, LTR_FMT.getContextDir());
assertEquals(RTL, RTL_FMT.getContextDir());
assertNull(UNKNOWN_FMT.getContextDir());
}
@Test
public void testIsRtlContext() {
assertEquals(false, LTR_FMT.isRtlContext());
assertEquals(true, RTL_FMT.isRtlContext());
assertEquals(false, UNKNOWN_FMT.isRtlContext());
}
@Test
public void testGetInstanceByBooleanRtlContext() {
assertEquals(LTR, BidiFormatter.getInstance(false).getContextDir());
assertEquals(RTL, BidiFormatter.getInstance(true).getContextDir());
}
@Test
public void testBuilderContextDir() {
assertNull(new BidiFormatter.Builder((Dir) null).build().getContextDir());
assertEquals(LTR, new BidiFormatter.Builder(LTR).build().getContextDir());
assertEquals(LTR, new BidiFormatter.Builder(false).build().getContextDir());
assertEquals(RTL, new BidiFormatter.Builder(RTL).build().getContextDir());
assertEquals(RTL, new BidiFormatter.Builder(true).build().getContextDir());
}
@Test
public void testEstimateDirection() {
assertEquals(RTL, BidiFormatter.estimateDirection(HE, true));
assertEquals(LTR, BidiFormatter.estimateDirection(EN, true));
assertEquals(NEUTRAL, BidiFormatter.estimateDirection(".", true));
// Text contains HTML or HTML-escaping.
assertEquals(LTR, BidiFormatter.estimateDirection(HE + "<some sort of an HTML tag/>", false));
assertEquals(RTL, BidiFormatter.estimateDirection(HE + "<some sort of an HTML tag/>", true));
assertEquals(
NEUTRAL, BidiFormatter.estimateDirection("." + "<some sort of an HTML tag/>", true));
}
@Test
public void testDirAttrValue() {
assertEquals("ltr", RTL_FMT.dirAttrValue(EN, true));
assertEquals("ltr", LTR_FMT.dirAttrValue(EN, true));
assertEquals("ltr", UNKNOWN_FMT.dirAttrValue(EN, true));
assertEquals("rtl", LTR_FMT.dirAttrValue(HE, true));
assertEquals("rtl", RTL_FMT.dirAttrValue(HE, true));
assertEquals("rtl", UNKNOWN_FMT.dirAttrValue(HE, true));
assertEquals("ltr", LTR_FMT.dirAttrValue("", true));
assertEquals("rtl", RTL_FMT.dirAttrValue("", true));
assertEquals("ltr", UNKNOWN_FMT.dirAttrValue("", true));
// Text contains HTML or HTML-escaping:
assertEquals("rtl", LTR_FMT.dirAttrValue(HE + "<some sort of an HTML tag>", true));
assertEquals("ltr", LTR_FMT.dirAttrValue(HE + "<some sort of an HTML tag>", false));
}
@Test
public void testKnownDirAttrValue() {
assertEquals("ltr", LTR_FMT.knownDirAttrValue(LTR));
assertEquals("ltr", RTL_FMT.knownDirAttrValue(LTR));
assertEquals("ltr", UNKNOWN_FMT.knownDirAttrValue(LTR));
assertEquals("rtl", LTR_FMT.knownDirAttrValue(RTL));
assertEquals("rtl", RTL_FMT.knownDirAttrValue(RTL));
assertEquals("rtl", UNKNOWN_FMT.knownDirAttrValue(RTL));
assertEquals("ltr", LTR_FMT.knownDirAttrValue(NEUTRAL));
assertEquals("rtl", RTL_FMT.knownDirAttrValue(NEUTRAL));
assertEquals("ltr", UNKNOWN_FMT.knownDirAttrValue(NEUTRAL));
}
@Test
public void testDirAttr() {
assertEquals("", LTR_FMT.dirAttr(EN));
assertEquals("dir=\"ltr\"", RTL_FMT.dirAttr(EN));
assertEquals("dir=\"ltr\"", UNKNOWN_FMT.dirAttr(EN));
assertEquals("dir=\"rtl\"", LTR_FMT.dirAttr(HE));
assertEquals("", RTL_FMT.dirAttr(HE));
assertEquals("dir=\"rtl\"", UNKNOWN_FMT.dirAttr(HE));
assertEquals("", LTR_FMT.dirAttr("."));
assertEquals("", RTL_FMT.dirAttr("."));
assertEquals("", UNKNOWN_FMT.dirAttr("."));
// Text contains HTML or HTML-escaping:
assertEquals("dir=\"rtl\"", LTR_FMT.dirAttr(HE + "<some sort of an HTML tag>", true));
assertEquals("", LTR_FMT.dirAttr(HE + "<some sort of an HTML tag>", false));
}
@Test
public void testKnownDirAttr() {
assertEquals("", LTR_FMT.knownDirAttr(LTR));
assertEquals("dir=\"ltr\"", RTL_FMT.knownDirAttr(LTR));
assertEquals("dir=\"ltr\"", UNKNOWN_FMT.knownDirAttr(LTR));
assertEquals("dir=\"rtl\"", LTR_FMT.knownDirAttr(RTL));
assertEquals("", RTL_FMT.knownDirAttr(RTL));
assertEquals("dir=\"rtl\"", UNKNOWN_FMT.knownDirAttr(RTL));
assertEquals("", LTR_FMT.knownDirAttr(NEUTRAL));
assertEquals("", RTL_FMT.knownDirAttr(NEUTRAL));
assertEquals("", UNKNOWN_FMT.knownDirAttr(NEUTRAL));
}
@Test
public void testSpanWrap() {
// Neutral directionality in whatever context.
assertEquals("neutral dir in LTR context", "& . <", LTR_FMT.spanWrap("& . <"));
assertEquals(
"neutral dir in LTR context, HTML",
HE_TAG + "." + HE_TAG,
LTR_FMT.spanWrap(HE_TAG + "." + HE_TAG, true));
assertEquals(
"neutral dir in LTR context, always span",
"<span>& . <</span>",
LTR_ALWAYS_SPAN_FMT.spanWrap("& . <"));
assertEquals("neutral dir in RTL context", "& . <", RTL_FMT.spanWrap("& . <"));
assertEquals(
"neutral dir in RTL context, HTML",
EN_TAG + "." + EN_TAG,
RTL_FMT.spanWrap(EN_TAG + "." + EN_TAG, true));
assertEquals(
"neutral dir in RTL context, always span",
"<span>& . <</span>",
RTL_ALWAYS_SPAN_FMT.spanWrap("& . <"));
assertEquals("neutral dir in unknown context", "& . <", UNKNOWN_FMT.spanWrap("& . <"));
assertEquals(
"neutral dir in unknown context, HTML",
EN_TAG + "." + EN_TAG,
UNKNOWN_FMT.spanWrap(EN_TAG + "." + EN_TAG, true));
assertEquals(
"neutral dir in unknown context, always span",
"<span>& . <</span>",
UNKNOWN_ALWAYS_SPAN_FMT.spanWrap("& . <"));
// Uniform directionality in matching context.
assertEquals(
"uniform dir matches LTR context",
"& " + EN + "<",
LTR_FMT.spanWrap("& " + EN + "<"));
assertEquals(
"uniform dir matches LTR context, HTML",
HE_TAG + EN + HE_TAG,
LTR_FMT.spanWrap(HE_TAG + EN + HE_TAG, true));
assertEquals(
"uniform dir matches LTR context, always span",
"<span>& " + EN + "<</span>",
LTR_ALWAYS_SPAN_FMT.spanWrap("& " + EN + "<"));
assertEquals(
"neutral treated as matching LTR context", ".", LTR_FMT.spanWrapWithKnownDir(LTR, "."));
assertEquals(
"uniform dir matches RTL context",
"& " + HE + "<",
RTL_FMT.spanWrap("& " + HE + "<"));
assertEquals(
"uniform dir matches RTL context, HTML",
EN_TAG + HE + EN_TAG,
RTL_FMT.spanWrap(EN_TAG + HE + EN_TAG, true));
assertEquals(
"uniform dir matches RTL context, always span",
"<span>& " + HE + "<</span>",
RTL_ALWAYS_SPAN_FMT.spanWrap("& " + HE + "<"));
assertEquals(
"neutral treated as matching RTL context", ".", RTL_FMT.spanWrapWithKnownDir(RTL, "."));
// Uniform directionality in unknown context.
assertEquals(
"uniform LTR in unknown context",
"<span dir=\"ltr\">." + EN + ".</span>",
UNKNOWN_FMT.spanWrap("." + EN + "."));
assertEquals(
"neutral treated as LTR in unknown context",
"<span dir=\"ltr\">" + "." + "</span>",
UNKNOWN_FMT.spanWrapWithKnownDir(LTR, "."));
assertEquals(
"uniform RTL in unknown context",
"<span dir=\"rtl\">." + HE + ".</span>",
UNKNOWN_FMT.spanWrap("." + HE + "."));
assertEquals(
"neutral treated as RTL in unknown context",
"<span dir=\"rtl\">" + "." + "</span>",
UNKNOWN_FMT.spanWrapWithKnownDir(RTL, "."));
// Uniform directionality in opposite context.
assertEquals(
"uniform dir opposite to LTR context",
"<span dir=\"rtl\">." + HE + ".</span>" + LRM,
LTR_FMT.spanWrap("." + HE + "."));
assertEquals(
"uniform dir opposite to LTR context, HTML",
"<span dir=\"rtl\">" + EN_TAG + HE + EN_TAG + "</span>" + LRM,
LTR_FMT.spanWrap(EN_TAG + HE + EN_TAG, true));
assertEquals(
"uniform dir opposite to LTR context, stereo reset",
LRM + "<span dir=\"rtl\">." + HE + ".</span>" + LRM,
LTR_STEREO_RESET_FMT.spanWrap("." + HE + "."));
assertEquals(
"uniform dir opposite to LTR context, stereo reset, HTML",
LRM + "<span dir=\"rtl\">" + EN_TAG + HE + EN_TAG + "</span>" + LRM,
LTR_STEREO_RESET_FMT.spanWrap(EN_TAG + HE + EN_TAG, true));
assertEquals(
"uniform dir opposite to LTR context, no isolation",
"<span dir=\"rtl\">." + HE + ".</span>",
LTR_FMT.spanWrap("." + HE + ".", false, false));
assertEquals(
"uniform dir opposite to LTR context, stereo reset, no isolation",
"<span dir=\"rtl\">." + HE + ".</span>",
LTR_STEREO_RESET_FMT.spanWrap("." + HE + ".", false, false));
assertEquals(
"neutral treated as opposite to LTR context",
"<span dir=\"rtl\">" + "." + "</span>" + LRM,
LTR_FMT.spanWrapWithKnownDir(RTL, "."));
assertEquals(
"uniform dir opposite to RTL context",
"<span dir=\"ltr\">." + EN + ".</span>" + RLM,
RTL_FMT.spanWrap("." + EN + "."));
assertEquals(
"uniform dir opposite to RTL context, HTML",
"<span dir=\"ltr\">" + HE_TAG + EN + HE_TAG + "</span>" + RLM,
RTL_FMT.spanWrap(HE_TAG + EN + HE_TAG, true));
assertEquals(
"uniform dir opposite to RTL context, stereo reset",
RLM + "<span dir=\"ltr\">." + EN + ".</span>" + RLM,
RTL_STEREO_RESET_FMT.spanWrap("." + EN + "."));
assertEquals(
"uniform dir opposite to RTL context, stereo reset, HTML",
RLM + "<span dir=\"ltr\">" + HE_TAG + EN + HE_TAG + "</span>" + RLM,
RTL_STEREO_RESET_FMT.spanWrap(HE_TAG + EN + HE_TAG, true));
assertEquals(
"uniform dir opposite to RTL context, no isolation",
"<span dir=\"ltr\">." + EN + ".</span>",
RTL_FMT.spanWrap("." + EN + ".", false, false));
assertEquals(
"uniform dir opposite to RTL context, stereo reset, no isolation",
"<span dir=\"ltr\">." + EN + ".</span>",
RTL_STEREO_RESET_FMT.spanWrap("." + EN + ".", false, false));
assertEquals(
"neutral treated as opposite to RTL context",
"<span dir=\"ltr\">" + "." + "</span>" + RLM,
RTL_FMT.spanWrapWithKnownDir(LTR, "."));
// "Known" unknown directionality is estimated.
assertEquals(
"known unknown dir matching LTR context",
"." + EN + ".",
LTR_FMT.spanWrapWithKnownDir(null, "." + EN + "."));
assertEquals(
"known unknown dir opposite to LTR context",
"<span dir=\"rtl\">." + HE + ".</span>" + LRM,
LTR_FMT.spanWrapWithKnownDir(null, "." + HE + "."));
assertEquals(
"known unknown dir matching RTL context",
"." + HE + ".",
RTL_FMT.spanWrapWithKnownDir(null, "." + HE + "."));
assertEquals(
"known unknown dir opposite to RTL context",
"<span dir=\"ltr\">." + EN + ".</span>" + RLM,
RTL_FMT.spanWrapWithKnownDir(null, "." + EN + "."));
// We test mixed-directionality cases only on spanWrapInKnownDir() because the estimation logic
// is outside the sphere of BidiFormatter, and different estimators will treat them differently.
// Overall directionality matching context, but with opposite exit directionality.
assertEquals(
"exit dir opposite to LTR context",
EN + HE + LRM,
LTR_FMT.spanWrapWithKnownDir(LTR, EN + HE));
assertEquals(
"exit dir opposite to LTR context, HTML",
EN + HE + EN_TAG + LRM,
LTR_FMT.spanWrapWithKnownDir(LTR, EN + HE + EN_TAG, true));
assertEquals(
"exit dir opposite to LTR context, stereo reset",
EN + HE + LRM,
LTR_STEREO_RESET_FMT.spanWrapWithKnownDir(LTR, EN + HE));
assertEquals(
"exit dir opposite to LTR context, stereo reset, HTML",
EN + HE + EN_TAG + LRM,
LTR_STEREO_RESET_FMT.spanWrapWithKnownDir(LTR, EN + HE + EN_TAG, true));
assertEquals(
"exit dir opposite to LTR context, no isolation",
EN + HE,
LTR_FMT.spanWrapWithKnownDir(LTR, EN + HE, false, false));
assertEquals(
"exit dir opposite to LTR context, stereo reset, no isolation",
EN + HE,
LTR_STEREO_RESET_FMT.spanWrapWithKnownDir(LTR, EN + HE, false, false));
assertEquals(
"exit dir opposite to LTR context, always span",
"<span>" + EN + HE + "</span>" + LRM,
LTR_ALWAYS_SPAN_FMT.spanWrapWithKnownDir(LTR, EN + HE));
assertEquals(
"exit dir opposite to RTL context",
HE + EN + RLM,
RTL_FMT.spanWrapWithKnownDir(RTL, HE + EN));
assertEquals(
"exit dir opposite to RTL context, HTML",
HE + EN + HE_TAG + RLM,
RTL_FMT.spanWrapWithKnownDir(RTL, HE + EN + HE_TAG, true));
assertEquals(
"exit dir opposite to RTL context, stereo reset",
HE + EN + RLM,
RTL_STEREO_RESET_FMT.spanWrapWithKnownDir(RTL, HE + EN));
assertEquals(
"exit dir opposite to RTL context, stereo reset, HTML",
HE + EN + HE_TAG + RLM,
RTL_STEREO_RESET_FMT.spanWrapWithKnownDir(RTL, HE + EN + HE_TAG, true));
assertEquals(
"exit dir opposite to RTL context, no isolation",
HE + EN,
RTL_FMT.spanWrapWithKnownDir(RTL, HE + EN, false, false));
assertEquals(
"exit dir opposite to RTL context, stereo reset, no isolation",
HE + EN,
RTL_STEREO_RESET_FMT.spanWrapWithKnownDir(RTL, HE + EN, false, false));
assertEquals(
"exit dir opposite to RTL context, always span",
"<span>" + HE + EN + "</span>" + RLM,
RTL_ALWAYS_SPAN_FMT.spanWrapWithKnownDir(RTL, HE + EN));
// Overall directionality matching context, but with opposite entry directionality.
assertEquals(
"entry dir opposite to LTR context", HE + EN, LTR_FMT.spanWrapWithKnownDir(LTR, HE + EN));
assertEquals(
"entry dir opposite to LTR context, HTML",
EN_TAG + HE + EN,
LTR_FMT.spanWrapWithKnownDir(LTR, EN_TAG + HE + EN, true));
assertEquals(
"entry dir opposite to LTR context, stereo reset",
LRM + HE + EN,
LTR_STEREO_RESET_FMT.spanWrapWithKnownDir(LTR, HE + EN));
assertEquals(
"entry dir opposite to LTR context, stereo reset, HTML",
LRM + EN_TAG + HE + EN,
LTR_STEREO_RESET_FMT.spanWrapWithKnownDir(LTR, EN_TAG + HE + EN, true));
assertEquals(
"entry dir opposite to LTR context, no isolation",
HE + EN,
LTR_FMT.spanWrapWithKnownDir(LTR, HE + EN, false, false));
assertEquals(
"entry dir opposite to LTR context, stereo reset, no isolation",
HE + EN,
LTR_STEREO_RESET_FMT.spanWrapWithKnownDir(LTR, HE + EN, false, false));
assertEquals(
"entry dir opposite to LTR context, always span",
"<span>" + HE + EN + "</span>",
LTR_ALWAYS_SPAN_FMT.spanWrapWithKnownDir(LTR, HE + EN));
assertEquals(
"entry dir opposite to LTR context, always span, stereo reset",
LRM + "<span>" + HE + EN + "</span>",
LTR_STEREO_RESET_ALWAYS_SPAN_FMT.spanWrapWithKnownDir(LTR, HE + EN));
assertEquals(
"entry dir opposite to RTL context", EN + HE, RTL_FMT.spanWrapWithKnownDir(RTL, EN + HE));
assertEquals(
"entry dir opposite to RTL context, HTML",
HE_TAG + EN + HE,
RTL_FMT.spanWrapWithKnownDir(RTL, HE_TAG + EN + HE, true));
assertEquals(
"entry dir opposite to RTL context, stereo reset",
RLM + EN + HE,
RTL_STEREO_RESET_FMT.spanWrapWithKnownDir(RTL, EN + HE));
assertEquals(
"entry dir opposite to RTL context, stereo reset, HTML",
RLM + HE_TAG + EN + HE,
RTL_STEREO_RESET_FMT.spanWrapWithKnownDir(RTL, HE_TAG + EN + HE, true));
assertEquals(
"entry dir opposite to RTL context, no isolation",
EN + HE,
RTL_FMT.spanWrapWithKnownDir(RTL, EN + HE, false, false));
assertEquals(
"entry dir opposite to RTL context, stereo reset, no isolation",
EN + HE,
RTL_STEREO_RESET_FMT.spanWrapWithKnownDir(RTL, EN + HE, false, false));
assertEquals(
"entry dir opposite to RTL context, always span",
"<span>" + EN + HE + "</span>",
RTL_ALWAYS_SPAN_FMT.spanWrapWithKnownDir(RTL, EN + HE));
assertEquals(
"entry dir opposite to RTL context, always span, stereo reset",
RLM + "<span>" + EN + HE + "</span>",
RTL_STEREO_RESET_ALWAYS_SPAN_FMT.spanWrapWithKnownDir(RTL, EN + HE));
// Overall directionality matching context, but with opposite entry and exit directionality.
assertEquals(
"entry and exit dir opposite to LTR context",
HE + EN + HE + LRM,
LTR_FMT.spanWrapWithKnownDir(LTR, HE + EN + HE));
assertEquals(
"entry and exit dir opposite to LTR context, HTML",
EN_TAG + HE + EN + HE + EN_TAG + LRM,
LTR_FMT.spanWrapWithKnownDir(LTR, EN_TAG + HE + EN + HE + EN_TAG, true));
assertEquals(
"entry and exit dir opposite to LTR context, stereo reset",
LRM + HE + EN + HE + LRM,
LTR_STEREO_RESET_FMT.spanWrapWithKnownDir(LTR, HE + EN + HE));
assertEquals(
"entry and exit dir opposite to LTR context, stereo reset, HTML",
LRM + EN_TAG + HE + EN + HE + EN_TAG + LRM,
LTR_STEREO_RESET_FMT.spanWrapWithKnownDir(LTR, EN_TAG + HE + EN + HE + EN_TAG, true));
assertEquals(
"entry and exit dir opposite to LTR context, stereo reset, always span",
LRM + "<span>" + HE + EN + HE + "</span>" + LRM,
LTR_STEREO_RESET_ALWAYS_SPAN_FMT.spanWrapWithKnownDir(LTR, HE + EN + HE));
assertEquals(
"entry and exit dir opposite to LTR context, no isolation",
HE + EN + HE,
LTR_FMT.spanWrapWithKnownDir(LTR, HE + EN + HE, false, false));
assertEquals(
"entry and exit dir opposite to RTL context",
EN + HE + EN + RLM,
RTL_FMT.spanWrapWithKnownDir(RTL, EN + HE + EN));
assertEquals(
"entry and exit dir opposite to RTL context, HTML",
HE_TAG + EN + HE + EN + HE_TAG + RLM,
RTL_FMT.spanWrapWithKnownDir(RTL, HE_TAG + EN + HE + EN + HE_TAG, true));
assertEquals(
"entry and exit dir opposite to RTL context, stereo reset",
RLM + EN + HE + EN + RLM,
RTL_STEREO_RESET_FMT.spanWrapWithKnownDir(RTL, EN + HE + EN));
assertEquals(
"entry and exit dir opposite to RTL context, stereo reset, HTML",
RLM + HE_TAG + EN + HE + EN + HE_TAG + RLM,
RTL_STEREO_RESET_FMT.spanWrapWithKnownDir(RTL, HE_TAG + EN + HE + EN + HE_TAG, true));
assertEquals(
"entry and exit dir opposite to RTL context, stereo reset, always span",
RLM + "<span>" + EN + HE + EN + "</span>" + RLM,
RTL_STEREO_RESET_ALWAYS_SPAN_FMT.spanWrapWithKnownDir(RTL, EN + HE + EN));
assertEquals(
"entry and exit dir opposite to RTL context, no isolation",
EN + HE + EN,
RTL_FMT.spanWrapWithKnownDir(RTL, EN + HE + EN, false, false));
// Entry and exit directionality matching context, but with opposite overall directionality.
assertEquals(
"overall dir (but not entry or exit dir) opposite to LTR context",
"<span dir=\"rtl\">" + EN + HE + EN + "</span>" + LRM,
LTR_FMT.spanWrapWithKnownDir(RTL, EN + HE + EN));
assertEquals(
"overall dir (but not entry or exit dir) opposite to LTR context, stereo reset",
LRM + "<span dir=\"rtl\">" + EN + HE + EN + "</span>" + LRM,
LTR_STEREO_RESET_FMT.spanWrapWithKnownDir(RTL, EN + HE + EN));
assertEquals(
"overall dir (but not entry or exit dir) opposite to LTR context, no isolation",
"<span dir=\"rtl\">" + EN + HE + EN + "</span>",
LTR_FMT.spanWrapWithKnownDir(RTL, EN + HE + EN, false, false));
assertEquals(
"overall dir (but not entry or exit dir) opposite to RTL context",
"<span dir=\"ltr\">" + HE + EN + HE + "</span>" + RLM,
RTL_FMT.spanWrapWithKnownDir(LTR, HE + EN + HE));
assertEquals(
"overall dir (but not entry or exit dir) opposite to RTL context, stereo reset",
RLM + "<span dir=\"ltr\">" + HE + EN + HE + "</span>" + RLM,
RTL_STEREO_RESET_FMT.spanWrapWithKnownDir(LTR, HE + EN + HE));
assertEquals(
"overall dir (but not entry or exit dir) opposite to RTL context, no isolation",
"<span dir=\"ltr\">" + HE + EN + HE + "</span>",
RTL_FMT.spanWrapWithKnownDir(LTR, HE + EN + HE, false, false));
}
@Test
public void testUnicodeWrap() {
// Neutral directionality in whatever context.
assertEquals("neutral dir in LTR context", "& . <", LTR_FMT.unicodeWrap("& . <"));
assertEquals(
"neutral dir in LTR context, HTML",
HE_TAG + "." + HE_TAG,
LTR_FMT.unicodeWrap(HE_TAG + "." + HE_TAG, true));
assertEquals(
"neutral dir in LTR context, always span",
"& . <",
LTR_ALWAYS_SPAN_FMT.unicodeWrap("& . <"));
assertEquals("neutral dir in RTL context", "& . <", RTL_FMT.unicodeWrap("& . <"));
assertEquals(
"neutral dir in RTL context, HTML",
EN_TAG + "." + EN_TAG,
RTL_FMT.unicodeWrap(EN_TAG + "." + EN_TAG, true));
assertEquals(
"neutral dir in RTL context, always span",
"& . <",
RTL_ALWAYS_SPAN_FMT.unicodeWrap("& . <"));
assertEquals("neutral dir in unknown context", "& . <", UNKNOWN_FMT.unicodeWrap("& . <"));
assertEquals(
"neutral dir in unknown context, HTML",
EN_TAG + "." + EN_TAG,
UNKNOWN_FMT.unicodeWrap(EN_TAG + "." + EN_TAG, true));
assertEquals(
"neutral dir in unknown context, always span",
"& . <",
UNKNOWN_ALWAYS_SPAN_FMT.unicodeWrap("& . <"));
// Uniform directionality in matching context.
assertEquals(
"uniform dir matches LTR context", "& " + EN + "<", LTR_FMT.unicodeWrap("& " + EN + "<"));
assertEquals(
"uniform dir matches LTR context, HTML",
HE_TAG + EN + HE_TAG,
LTR_FMT.unicodeWrap(HE_TAG + EN + HE_TAG, true));
assertEquals(
"uniform dir matches LTR context, always span",
"& " + EN + "<",
LTR_ALWAYS_SPAN_FMT.unicodeWrap("& " + EN + "<"));
assertEquals(
"neutral treated as matching LTR context", ".", LTR_FMT.unicodeWrapWithKnownDir(LTR, "."));
assertEquals(
"uniform dir matches RTL context", "& " + HE + "<", RTL_FMT.unicodeWrap("& " + HE + "<"));
assertEquals(
"uniform dir matches RTL context, HTML",
EN_TAG + HE + EN_TAG,
RTL_FMT.unicodeWrap(EN_TAG + HE + EN_TAG, true));
assertEquals(
"uniform dir matches RTL context, always span",
"& " + HE + "<",
RTL_ALWAYS_SPAN_FMT.unicodeWrap("& " + HE + "<"));
assertEquals(
"neutral treated as matching RTL context", ".", RTL_FMT.unicodeWrapWithKnownDir(RTL, "."));
// Uniform directionality in unknown context.
assertEquals(
"uniform LTR in unknown context",
LRE + "." + EN + "." + PDF,
UNKNOWN_FMT.unicodeWrap("." + EN + "."));
assertEquals(
"uniform LTR in unknown context, no isolation",
LRE + "." + EN + "." + PDF,
UNKNOWN_FMT.unicodeWrap("." + EN + ".", false, false));
assertEquals(
"neutral treated as LTR in unknown context",
LRE + "." + PDF,
UNKNOWN_FMT.unicodeWrapWithKnownDir(LTR, "."));
assertEquals(
"uniform RTL in unknown context",
RLE + "." + HE + "." + PDF,
UNKNOWN_FMT.unicodeWrap("." + HE + "."));
assertEquals(
"uniform RTL in unknown context, no isolation",
RLE + "." + HE + "." + PDF,
UNKNOWN_FMT.unicodeWrap("." + HE + ".", false, false));
assertEquals(
"neutral treated as RTL in unknown context",
RLE + "." + PDF,
UNKNOWN_FMT.unicodeWrapWithKnownDir(RTL, "."));
// Uniform directionality in opposite context.
assertEquals(
"uniform dir opposite to LTR context",
RLE + "." + HE + "." + PDF + LRM,
LTR_FMT.unicodeWrap("." + HE + "."));
assertEquals(
"uniform dir opposite to LTR context, HTML",
RLE + EN_TAG + HE + EN_TAG + PDF + LRM,
LTR_FMT.unicodeWrap(EN_TAG + HE + EN_TAG, true));
assertEquals(
"uniform dir opposite to LTR context, stereo reset",
LRM + RLE + "." + HE + "." + PDF + LRM,
LTR_STEREO_RESET_FMT.unicodeWrap("." + HE + "."));
assertEquals(
"uniform dir opposite to LTR context, stereo reset, HTML",
LRM + RLE + EN_TAG + HE + EN_TAG + PDF + LRM,
LTR_STEREO_RESET_FMT.unicodeWrap(EN_TAG + HE + EN_TAG, true));
assertEquals(
"uniform dir opposite to LTR context, no isolation",
RLE + "." + HE + "." + PDF,
LTR_FMT.unicodeWrap("." + HE + ".", false, false));
assertEquals(
"uniform dir opposite to LTR context, stereo reset, no isolation",
RLE + "." + HE + "." + PDF,
LTR_STEREO_RESET_FMT.unicodeWrap("." + HE + ".", false, false));
assertEquals(
"neutral treated as opposite to LTR context",
RLE + "." + PDF + LRM,
LTR_FMT.unicodeWrapWithKnownDir(RTL, "."));
assertEquals(
"uniform dir opposite to RTL context",
LRE + "." + EN + "." + PDF + RLM,
RTL_FMT.unicodeWrap("." + EN + "."));
assertEquals(
"uniform dir opposite to RTL context, HTML",
LRE + HE_TAG + EN + HE_TAG + PDF + RLM,
RTL_FMT.unicodeWrap(HE_TAG + EN + HE_TAG, true));
assertEquals(
"uniform dir opposite to RTL context, stereo reset",
RLM + LRE + "." + EN + "." + PDF + RLM,
RTL_STEREO_RESET_FMT.unicodeWrap("." + EN + "."));
assertEquals(
"uniform dir opposite to RTL context, stereo reset, HTML",
RLM + LRE + HE_TAG + EN + HE_TAG + PDF + RLM,
RTL_STEREO_RESET_FMT.unicodeWrap(HE_TAG + EN + HE_TAG, true));
assertEquals(
"uniform dir opposite to RTL context, no isolation",
LRE + "." + EN + "." + PDF,
RTL_FMT.unicodeWrap("." + EN + ".", false, false));
assertEquals(
"uniform dir opposite to RTL context, stereo reset, no isolation",
LRE + "." + EN + "." + PDF,
RTL_STEREO_RESET_FMT.unicodeWrap("." + EN + ".", false, false));
assertEquals(
"neutral treated as opposite to RTL context",
LRE + "." + PDF + RLM,
RTL_FMT.unicodeWrapWithKnownDir(LTR, "."));
// "Known" unknown directionality is estimated.
assertEquals(
"known unknown dir matching LTR context",
"." + EN + ".",
LTR_FMT.unicodeWrapWithKnownDir(null, "." + EN + "."));
assertEquals(
"known unknown dir opposite to LTR context",
RLE + "." + HE + "." + PDF + LRM,
LTR_FMT.unicodeWrapWithKnownDir(null, "." + HE + "."));
assertEquals(
"known unknown dir matching RTL context",
"." + HE + ".",
RTL_FMT.unicodeWrapWithKnownDir(null, "." + HE + "."));
assertEquals(
"known unknown dir opposite to RTL context",
LRE + "." + EN + "." + PDF + RLM,
RTL_FMT.unicodeWrapWithKnownDir(null, "." + EN + "."));
// We test mixed-directionality cases only on unicodeWrapInKnownDir() because the estimation
// logic is outside the sphere of BidiFormatter, and different estimators will treat them
// differently.
// Overall directionality matching context, but with opposite exit directionality.
assertEquals(
"exit dir opposite to LTR context",
EN + HE + LRM,
LTR_FMT.unicodeWrapWithKnownDir(LTR, EN + HE));
assertEquals(
"exit dir opposite to LTR context, HTML",
EN + HE + EN_TAG + LRM,
LTR_FMT.unicodeWrapWithKnownDir(LTR, EN + HE + EN_TAG, true));
assertEquals(
"exit dir opposite to LTR context, stereo reset",
EN + HE + LRM,
LTR_STEREO_RESET_FMT.unicodeWrapWithKnownDir(LTR, EN + HE));
assertEquals(
"exit dir opposite to LTR context, stereo reset, HTML",
EN + HE + EN_TAG + LRM,
LTR_STEREO_RESET_FMT.unicodeWrapWithKnownDir(LTR, EN + HE + EN_TAG, true));
assertEquals(
"exit dir opposite to LTR context, no isolation",
EN + HE,
LTR_FMT.unicodeWrapWithKnownDir(LTR, EN + HE, false, false));
assertEquals(
"exit dir opposite to LTR context, stereo reset, no isolation",
EN + HE,
LTR_STEREO_RESET_FMT.unicodeWrapWithKnownDir(LTR, EN + HE, false, false));
assertEquals(
"exit dir opposite to LTR context, always span",
EN + HE + LRM,
LTR_ALWAYS_SPAN_FMT.unicodeWrapWithKnownDir(LTR, EN + HE));
assertEquals(
"exit dir opposite to RTL context",
HE + EN + RLM,
RTL_FMT.unicodeWrapWithKnownDir(RTL, HE + EN));
assertEquals(
"exit dir opposite to RTL context, HTML",
HE + EN + HE_TAG + RLM,
RTL_FMT.unicodeWrapWithKnownDir(RTL, HE + EN + HE_TAG, true));
assertEquals(
"exit dir opposite to RTL context, stereo reset",
HE + EN + RLM,
RTL_STEREO_RESET_FMT.unicodeWrapWithKnownDir(RTL, HE + EN));
assertEquals(
"exit dir opposite to RTL context, stereo reset, HTML",
HE + EN + HE_TAG + RLM,
RTL_STEREO_RESET_FMT.unicodeWrapWithKnownDir(RTL, HE + EN + HE_TAG, true));
assertEquals(
"exit dir opposite to RTL context, no isolation",
HE + EN,
RTL_FMT.unicodeWrapWithKnownDir(RTL, HE + EN, false, false));
assertEquals(
"exit dir opposite to RTL context, stereo reset, no isolation",
HE + EN,
RTL_STEREO_RESET_FMT.unicodeWrapWithKnownDir(RTL, HE + EN, false, false));
assertEquals(
"exit dir opposite to RTL context, always span",
HE + EN + RLM,
RTL_ALWAYS_SPAN_FMT.unicodeWrapWithKnownDir(RTL, HE + EN));
// Overall directionality matching context, but with opposite entry directionality.
assertEquals(
"entry dir opposite to LTR context",
HE + EN,
LTR_FMT.unicodeWrapWithKnownDir(LTR, HE + EN));
assertEquals(
"entry dir opposite to LTR context, HTML",
EN_TAG + HE + EN,
LTR_FMT.unicodeWrapWithKnownDir(LTR, EN_TAG + HE + EN, true));
assertEquals(
"entry dir opposite to LTR context, stereo reset",
LRM + HE + EN,
LTR_STEREO_RESET_FMT.unicodeWrapWithKnownDir(LTR, HE + EN));
assertEquals(
"entry dir opposite to LTR context, stereo reset, HTML",
LRM + EN_TAG + HE + EN,
LTR_STEREO_RESET_FMT.unicodeWrapWithKnownDir(LTR, EN_TAG + HE + EN, true));
assertEquals(
"entry dir opposite to LTR context, no isolation",
HE + EN,
LTR_FMT.unicodeWrapWithKnownDir(LTR, HE + EN, false, false));
assertEquals(
"entry dir opposite to LTR context, stereo reset, no isolation",
HE + EN,
LTR_STEREO_RESET_FMT.unicodeWrapWithKnownDir(LTR, HE + EN, false, false));
assertEquals(
"entry dir opposite to RTL context",
EN + HE,
RTL_FMT.unicodeWrapWithKnownDir(RTL, EN + HE));
assertEquals(
"entry dir opposite to RTL context, HTML",
HE_TAG + EN + HE,
RTL_FMT.unicodeWrapWithKnownDir(RTL, HE_TAG + EN + HE, true));
assertEquals(
"entry dir opposite to RTL context, stereo reset",
RLM + EN + HE,
RTL_STEREO_RESET_FMT.unicodeWrapWithKnownDir(RTL, EN + HE));
assertEquals(
"entry dir opposite to RTL context, stereo reset, HTML",
RLM + HE_TAG + EN + HE,
RTL_STEREO_RESET_FMT.unicodeWrapWithKnownDir(RTL, HE_TAG + EN + HE, true));
assertEquals(
"entry dir opposite to RTL context, no isolation",
EN + HE,
RTL_FMT.unicodeWrapWithKnownDir(RTL, EN + HE, false, false));
assertEquals(
"entry dir opposite to RTL context, stereo reset, no isolation",
EN + HE,
RTL_STEREO_RESET_FMT.unicodeWrapWithKnownDir(RTL, EN + HE, false, false));
// Overall directionality matching context, but with opposite entry and exit directionality.
assertEquals(
"entry and exit dir opposite to LTR context",
HE + EN + HE + LRM,
LTR_FMT.unicodeWrapWithKnownDir(LTR, HE + EN + HE));
assertEquals(
"entry and exit dir opposite to LTR context, HTML",
EN_TAG + HE + EN + HE + EN_TAG + LRM,
LTR_FMT.unicodeWrapWithKnownDir(LTR, EN_TAG + HE + EN + HE + EN_TAG, true));
assertEquals(
"entry and exit dir opposite to LTR context, stereo reset",
LRM + HE + EN + HE + LRM,
LTR_STEREO_RESET_FMT.unicodeWrapWithKnownDir(LTR, HE + EN + HE));
assertEquals(
"entry and exit dir opposite to LTR context, stereo reset, HTML",
LRM + EN_TAG + HE + EN + HE + EN_TAG + LRM,
LTR_STEREO_RESET_FMT.unicodeWrapWithKnownDir(LTR, EN_TAG + HE + EN + HE + EN_TAG, true));
assertEquals(
"entry and exit dir opposite to LTR context, stereo reset, always span",
LRM + HE + EN + HE + LRM,
LTR_STEREO_RESET_ALWAYS_SPAN_FMT.unicodeWrapWithKnownDir(LTR, HE + EN + HE));
assertEquals(
"entry and exit dir opposite to LTR context, no isolation",
HE + EN + HE,
LTR_FMT.unicodeWrapWithKnownDir(LTR, HE + EN + HE, false, false));
assertEquals(
"entry and exit dir opposite to RTL context",
EN + HE + EN + RLM,
RTL_FMT.unicodeWrapWithKnownDir(RTL, EN + HE + EN));
assertEquals(
"entry and exit dir opposite to RTL context, HTML",
HE_TAG + EN + HE + EN + HE_TAG + RLM,
RTL_FMT.unicodeWrapWithKnownDir(RTL, HE_TAG + EN + HE + EN + HE_TAG, true));
assertEquals(
"entry and exit dir opposite to RTL context, stereo reset",
RLM + EN + HE + EN + RLM,
RTL_STEREO_RESET_FMT.unicodeWrapWithKnownDir(RTL, EN + HE + EN));
assertEquals(
"entry and exit dir opposite to RTL context, stereo reset, HTML",
RLM + HE_TAG + EN + HE + EN + HE_TAG + RLM,
RTL_STEREO_RESET_FMT.unicodeWrapWithKnownDir(RTL, HE_TAG + EN + HE + EN + HE_TAG, true));
assertEquals(
"entry and exit dir opposite to RTL context, stereo reset, always span",
RLM + EN + HE + EN + RLM,
RTL_STEREO_RESET_ALWAYS_SPAN_FMT.unicodeWrapWithKnownDir(RTL, EN + HE + EN));
assertEquals(
"entry and exit dir opposite to RTL context, no isolation",
EN + HE + EN,
RTL_FMT.unicodeWrapWithKnownDir(RTL, EN + HE + EN, false, false));
// Entry and exit directionality matching context, but with opposite overall directionality.
assertEquals(
"overall dir (but not entry or exit dir) opposite to LTR context",
RLE + EN + HE + EN + PDF + LRM,
LTR_FMT.unicodeWrapWithKnownDir(RTL, EN + HE + EN));
assertEquals(
"overall dir (but not entry or exit dir) opposite to LTR context, stereo reset",
LRM + RLE + EN + HE + EN + PDF + LRM,
LTR_STEREO_RESET_FMT.unicodeWrapWithKnownDir(RTL, EN + HE + EN));
assertEquals(
"overall dir (but not entry or exit dir) opposite to LTR context, no isolation",
RLE + EN + HE + EN + PDF,
LTR_FMT.unicodeWrapWithKnownDir(RTL, EN + HE + EN, false, false));
assertEquals(
"overall dir (but not entry or exit dir) opposite to RTL context",
LRE + HE + EN + HE + PDF + RLM,
RTL_FMT.unicodeWrapWithKnownDir(LTR, HE + EN + HE));
assertEquals(
"overall dir (but not entry or exit dir) opposite to RTL context, stereo reset",
RLM + LRE + HE + EN + HE + PDF + RLM,
RTL_STEREO_RESET_FMT.unicodeWrapWithKnownDir(LTR, HE + EN + HE));
assertEquals(
"overall dir (but not entry or exit dir) opposite to RTL context, no isolation",
LRE + HE + EN + HE + PDF,
RTL_FMT.unicodeWrapWithKnownDir(LTR, HE + EN + HE, false, false));
}
@Test
public void testMarkAfter() {
assertEquals("uniform dir matches LTR context, HTML", "", LTR_FMT.markAfter(EN + HE_TAG, true));
assertEquals("uniform dir matches RTL context, HTML", "", RTL_FMT.markAfter(HE + EN_TAG, true));
assertEquals("uniform LTR in unknown context", "", UNKNOWN_FMT.markAfter(EN));
assertEquals("uniform RTL in unknown context", "", UNKNOWN_FMT.markAfter(HE));
assertEquals(
"exit dir opposite to LTR context, HTML",
LRM,
LTR_FMT.markAfterKnownDir(LTR, EN + HE + EN_TAG, true));
assertEquals(
"exit dir opposite to RTL context, HTML",
RLM,
RTL_FMT.markAfterKnownDir(RTL, HE + EN + HE_TAG, true));
assertEquals(
"overall dir (but not exit dir) opposite to LTR context",
LRM,
LTR_FMT.markAfterKnownDir(RTL, HE + EN));
assertEquals(
"overall dir (but not exit dir) opposite to RTL context",
RLM,
RTL_FMT.markAfterKnownDir(LTR, EN + HE));
}
@Test
public void testMarkBefore() {
assertEquals(
"uniform dir matches LTR context, HTML", "", LTR_FMT.markBefore(HE_TAG + EN, true));
assertEquals(
"uniform dir matches RTL context, HTML", "", RTL_FMT.markBefore(EN_TAG + HE, true));
assertEquals("uniform LTR in unknown context", "", UNKNOWN_FMT.markBefore(EN));
assertEquals("uniform RTL in unknown context", "", UNKNOWN_FMT.markBefore(HE));
assertEquals(
"entry dir opposite to LTR context, HTML",
LRM,
LTR_FMT.markBeforeKnownDir(LTR, EN_TAG + HE + EN, true));
assertEquals(
"entry dir opposite to RTL context, HTML",
RLM,
RTL_FMT.markBeforeKnownDir(RTL, HE_TAG + EN + HE, true));
assertEquals(
"overall dir (but not entry dir) opposite to LTR context",
LRM,
LTR_FMT.markBeforeKnownDir(RTL, EN + HE));
assertEquals(
"overall dir (but not entry dir) opposite to RTL context",
RLM,
RTL_FMT.markBeforeKnownDir(LTR, HE + EN));
}
@Test
public void testMark() {
assertEquals(LRM, LTR_FMT.mark());
assertEquals(RLM, RTL_FMT.mark());
assertEquals("", UNKNOWN_FMT.mark());
}
@Test
public void testStartEdge() {
assertEquals(BidiUtils.LEFT, LTR_FMT.startEdge());
assertEquals(BidiUtils.RIGHT, RTL_FMT.startEdge());
assertEquals(BidiUtils.LEFT, UNKNOWN_FMT.startEdge());
}
@Test
public void testEndEdge() {
assertEquals(BidiUtils.RIGHT, LTR_FMT.endEdge());
assertEquals(BidiUtils.LEFT, RTL_FMT.endEdge());
assertEquals(BidiUtils.RIGHT, UNKNOWN_FMT.endEdge());
}
}