Esempio n. 1
0
TEST_F(VisiblePositionTest, ShadowV0DistributedNodes) {
  const char* bodyContent =
      "<p id='host'>00<b id='one'>11</b><b id='two'>22</b>33</p>";
  const char* shadowContent =
      "<a><span id='s4'>44</span><content select=#two></content><span "
      "id='s5'>55</span><content select=#one></content><span "
      "id='s6'>66</span></a>";
  setBodyContent(bodyContent);
  ShadowRoot* shadowRoot = setShadowContent(shadowContent, "host");

  Element* body = document().body();
  Element* one = body->querySelector("#one");
  Element* two = body->querySelector("#two");
  Element* four = shadowRoot->querySelector("#s4");
  Element* five = shadowRoot->querySelector("#s5");

  EXPECT_EQ(Position(one->firstChild(), 0),
            canonicalPositionOf(Position(one, 0)));
  EXPECT_EQ(Position(one->firstChild(), 0),
            createVisiblePosition(Position(one, 0)).deepEquivalent());
  EXPECT_EQ(Position(one->firstChild(), 2),
            canonicalPositionOf(Position(two, 0)));
  EXPECT_EQ(Position(one->firstChild(), 2),
            createVisiblePosition(Position(two, 0)).deepEquivalent());

  EXPECT_EQ(PositionInFlatTree(five->firstChild(), 2),
            canonicalPositionOf(PositionInFlatTree(one, 0)));
  EXPECT_EQ(PositionInFlatTree(five->firstChild(), 2),
            createVisiblePosition(PositionInFlatTree(one, 0)).deepEquivalent());
  EXPECT_EQ(PositionInFlatTree(four->firstChild(), 2),
            canonicalPositionOf(PositionInFlatTree(two, 0)));
  EXPECT_EQ(PositionInFlatTree(four->firstChild(), 2),
            createVisiblePosition(PositionInFlatTree(two, 0)).deepEquivalent());
}
TEST_F(PositionTest, NodeAsRangeLastNodeShadow)
{
    const char* bodyContent = "<p id='host'>00<b id='one'>11</b><b id='two'>22</b>33</p>";
    const char* shadowContent = "<a id='a'><content select=#two></content><content select=#one></content></a>";
    setBodyContent(bodyContent);
    RefPtrWillBeRawPtr<ShadowRoot> shadowRoot = setShadowContent(shadowContent, "host");

    Node* host = document().getElementById("host");
    Node* n1 = document().getElementById("one");
    Node* n2 = document().getElementById("two");
    Node* t0 = EditingStrategy::firstChild(*host);
    Node* t1 = EditingStrategy::firstChild(*n1);
    Node* t2 = EditingStrategy::firstChild(*n2);
    Node* t3 = EditingStrategy::lastChild(*host);
    Node* a = shadowRoot->getElementById("a");

    EXPECT_EQ(t0, Position::inParentBeforeNode(*n1).nodeAsRangeLastNode());
    EXPECT_EQ(t1, Position::inParentBeforeNode(*n2).nodeAsRangeLastNode());
    EXPECT_EQ(t1, Position::inParentAfterNode(*n1).nodeAsRangeLastNode());
    EXPECT_EQ(t2, Position::inParentAfterNode(*n2).nodeAsRangeLastNode());
    EXPECT_EQ(t3, Position::afterNode(host).nodeAsRangeLastNode());

    EXPECT_EQ(t2, PositionInFlatTree::inParentBeforeNode(*n1).nodeAsRangeLastNode());
    EXPECT_EQ(a, PositionInFlatTree::inParentBeforeNode(*n2).nodeAsRangeLastNode());
    EXPECT_EQ(t1, PositionInFlatTree::inParentAfterNode(*n1).nodeAsRangeLastNode());
    EXPECT_EQ(t2, PositionInFlatTree::inParentAfterNode(*n2).nodeAsRangeLastNode());
    EXPECT_EQ(t1, PositionInFlatTree::afterNode(host).nodeAsRangeLastNode());
}
TEST_F(EditingUtilitiesTest, isFirstPositionAfterTable)
{
    const char* bodyContent = "<div contenteditable id=host><table id=table><tr><td>1</td></tr></table><b id=two>22</b></div>";
    const char* shadowContent = "<content select=#two></content><content select=#table></content>";
    setBodyContent(bodyContent);
    setShadowContent(shadowContent, "host");
    updateLayoutAndStyleForPainting();
    Node* host = document().getElementById("host");
    Node* table = document().getElementById("table");

    EXPECT_EQ(table, isFirstPositionAfterTable(createVisiblePosition(Position::afterNode(table))));
    EXPECT_EQ(table, isFirstPositionAfterTable(createVisiblePosition(PositionInComposedTree::afterNode(table))));

    EXPECT_EQ(table, isFirstPositionAfterTable(createVisiblePosition(Position::lastPositionInNode(table))));
    EXPECT_EQ(table, isFirstPositionAfterTable(createVisiblePosition(PositionInComposedTree::lastPositionInNode(table))));

    EXPECT_EQ(nullptr, isFirstPositionAfterTable(createVisiblePosition(Position(host, 2))));
    EXPECT_EQ(table, isFirstPositionAfterTable(createVisiblePosition(PositionInComposedTree(host, 2))));

    EXPECT_EQ(nullptr, isFirstPositionAfterTable(createVisiblePosition(Position::afterNode(host))));
    EXPECT_EQ(nullptr, isFirstPositionAfterTable(createVisiblePosition(PositionInComposedTree::afterNode(host))));

    EXPECT_EQ(nullptr, isFirstPositionAfterTable(createVisiblePosition(Position::lastPositionInNode(host))));
    EXPECT_EQ(table, isFirstPositionAfterTable(createVisiblePosition(PositionInComposedTree::lastPositionInNode(host))));
}
TEST_F(SimplifiedBackwardsTextIteratorTest, characterAt) {
  const char* bodyContent =
      "<a id=host><b id=one>one</b> not appeared <b id=two>two</b></a>";
  const char* shadowContent =
      "three <content select=#two></content> <content select=#one></content> "
      "zero";
  setBodyContent(bodyContent);
  setShadowContent(shadowContent, "host");

  Element* host = document().getElementById("host");

  EphemeralRangeTemplate<EditingStrategy> range1(
      EphemeralRangeTemplate<EditingStrategy>::rangeOfContents(*host));
  SimplifiedBackwardsTextIteratorAlgorithm<EditingStrategy> backIter1(
      range1.startPosition(), range1.endPosition());
  const char* message1 =
      "|backIter1| should emit 'one' and 'two' in reverse order.";
  EXPECT_EQ('o', backIter1.characterAt(0)) << message1;
  EXPECT_EQ('w', backIter1.characterAt(1)) << message1;
  EXPECT_EQ('t', backIter1.characterAt(2)) << message1;
  backIter1.advance();
  EXPECT_EQ('e', backIter1.characterAt(0)) << message1;
  EXPECT_EQ('n', backIter1.characterAt(1)) << message1;
  EXPECT_EQ('o', backIter1.characterAt(2)) << message1;

  EphemeralRangeTemplate<EditingInFlatTreeStrategy> range2(
      EphemeralRangeTemplate<EditingInFlatTreeStrategy>::rangeOfContents(
          *host));
  SimplifiedBackwardsTextIteratorAlgorithm<EditingInFlatTreeStrategy> backIter2(
      range2.startPosition(), range2.endPosition());
  const char* message2 =
      "|backIter2| should emit 'three ', 'two', ' ', 'one' and ' zero' in "
      "reverse order.";
  EXPECT_EQ('o', backIter2.characterAt(0)) << message2;
  EXPECT_EQ('r', backIter2.characterAt(1)) << message2;
  EXPECT_EQ('e', backIter2.characterAt(2)) << message2;
  EXPECT_EQ('z', backIter2.characterAt(3)) << message2;
  EXPECT_EQ(' ', backIter2.characterAt(4)) << message2;
  backIter2.advance();
  EXPECT_EQ('e', backIter2.characterAt(0)) << message2;
  EXPECT_EQ('n', backIter2.characterAt(1)) << message2;
  EXPECT_EQ('o', backIter2.characterAt(2)) << message2;
  backIter2.advance();
  EXPECT_EQ(' ', backIter2.characterAt(0)) << message2;
  backIter2.advance();
  EXPECT_EQ('o', backIter2.characterAt(0)) << message2;
  EXPECT_EQ('w', backIter2.characterAt(1)) << message2;
  EXPECT_EQ('t', backIter2.characterAt(2)) << message2;
  backIter2.advance();
  EXPECT_EQ(' ', backIter2.characterAt(0)) << message2;
  EXPECT_EQ('e', backIter2.characterAt(1)) << message2;
  EXPECT_EQ('e', backIter2.characterAt(2)) << message2;
  EXPECT_EQ('r', backIter2.characterAt(3)) << message2;
  EXPECT_EQ('h', backIter2.characterAt(4)) << message2;
  EXPECT_EQ('t', backIter2.characterAt(5)) << message2;
}
TEST_F(PositionTest, ToPositionInFlatTreeWithEmptyShadowRoot)
{
    const char* bodyContent = "<p id='host'>00<b id='one'>11</b>22</p>";
    const char* shadowContent = "";
    setBodyContent(bodyContent);
    RefPtrWillBeRawPtr<ShadowRoot> shadowRoot = setShadowContent(shadowContent, "host");
    RefPtrWillBeRawPtr<Element> host = document().getElementById("host");

    EXPECT_EQ(PositionInFlatTree(host, PositionAnchorType::AfterChildren), toPositionInFlatTree(Position(shadowRoot.get(), 0)));
}
Esempio n. 6
0
TEST_F(PositionTest, ToPositionInComposedTreeWithShadowRootContainingSingleContent)
{
    const char* bodyContent = "<p id='host'>00<b id='one'>11</b>22</p>";
    const char* shadowContent = "<content select=#one></content>";
    setBodyContent(bodyContent);
    RefPtrWillBeRawPtr<ShadowRoot> shadowRoot = setShadowContent(shadowContent, "host");
    RefPtrWillBeRawPtr<Element> host = document().getElementById("host");

    EXPECT_EQ(PositionInComposedTree(host.get(), 0), toPositionInComposedTree(Position(shadowRoot.get(), 0)));
    EXPECT_EQ(PositionInComposedTree(host.get(), PositionAnchorType::AfterChildren), toPositionInComposedTree(Position(shadowRoot.get(), 1)));
}
Esempio n. 7
0
TEST_F(PositionTest, ToPositionInFlatTreeWithShadowRootContainingSingleContent)
{
    const char* bodyContent = "<p id='host'>00<b id='one'>11</b>22</p>";
    const char* shadowContent = "<content select=#one></content>";
    setBodyContent(bodyContent);
    ShadowRoot* shadowRoot = setShadowContent(shadowContent, "host");
    Element* host = document().getElementById("host");

    EXPECT_EQ(PositionInFlatTree(host, 0), toPositionInFlatTree(Position(shadowRoot, 0)));
    EXPECT_EQ(PositionInFlatTree(host, PositionAnchorType::AfterChildren), toPositionInFlatTree(Position(shadowRoot, 1)));
}
TEST_F(EditingUtilitiesTest, directionOfEnclosingBlock)
{
    const char* bodyContent = "<p id='host'><b id='one'></b><b id='two'>22</b></p>";
    const char* shadowContent = "<content select=#two></content><p dir=rtl><content select=#one></content><p>";
    setBodyContent(bodyContent);
    setShadowContent(shadowContent, "host");
    updateLayoutAndStyleForPainting();
    Node* one = document().getElementById("one");

    EXPECT_EQ(LTR, directionOfEnclosingBlock(Position(one, 0)));
    EXPECT_EQ(RTL, directionOfEnclosingBlock(PositionInComposedTree(one, 0)));
}
TEST_F(NodeTest, canStartSelectionWithShadowDOM)
{
    const char* bodyContent = "<div id=host><span id=one>one</span></div>";
    const char* shadowContent = "<a href='http://www.msn.com'><content></content></a>";
    setBodyContent(bodyContent);
    setShadowContent(shadowContent, "host");
    updateLayoutAndStyleForPainting();
    Node* one = document().getElementById("one");

    EXPECT_FALSE(one->canStartSelection());
    EXPECT_FALSE(one->firstChild()->canStartSelection());
}
TEST_F(EditingUtilitiesTest, NextNodeIndex)
{
    const char* bodyContent = "<p id='host'>00<b id='one'>11</b><b id='two'>22</b>33</p>";
    const char* shadowContent = "<content select=#two></content><content select=#one></content>";
    setBodyContent(bodyContent);
    setShadowContent(shadowContent, "host");
    Node* host = document().getElementById("host");
    Node* two = document().getElementById("two");

    EXPECT_EQ(Position(host, 3), nextPositionOf(Position(two, 2), PositionMoveType::CodePoint));
    EXPECT_EQ(PositionInComposedTree(host, 1), nextPositionOf(PositionInComposedTree(two, 2), PositionMoveType::CodePoint));
}
Esempio n. 11
0
TEST_F(PositionTest, ToPositionInFlatTreeWithActiveInsertionPoint)
{
    const char* bodyContent = "<p id='host'>00<b id='one'>11</b>22</p>";
    const char* shadowContent = "<a id='a'><content select=#one id='content'></content><content></content></a>";
    setBodyContent(bodyContent);
    RefPtrWillBeRawPtr<ShadowRoot> shadowRoot = setShadowContent(shadowContent, "host");
    RefPtrWillBeRawPtr<Element> anchor = shadowRoot->getElementById("a");

    EXPECT_EQ(PositionInFlatTree(anchor.get(), 0), toPositionInFlatTree(Position(anchor.get(), 0)));
    EXPECT_EQ(PositionInFlatTree(anchor.get(), 1), toPositionInFlatTree(Position(anchor.get(), 1)));
    EXPECT_EQ(PositionInFlatTree(anchor, PositionAnchorType::AfterChildren), toPositionInFlatTree(Position(anchor.get(), 2)));
}
TEST_F(EditingUtilitiesTest, NextVisuallyDistinctCandidate)
{
    const char* bodyContent = "<p id='host'>00<b id='one'>11</b><b id='two'>22</b><b id='three'>33</b></p>";
    const char* shadowContent = "<content select=#two></content><content select=#one></content><content select=#three></content>";
    setBodyContent(bodyContent);
    setShadowContent(shadowContent, "host");
    updateLayoutAndStyleForPainting();
    Node* one = document().getElementById("one");
    Node* two = document().getElementById("two");
    Node* three = document().getElementById("three");

    EXPECT_EQ(Position(two->firstChild(), 1), nextVisuallyDistinctCandidate(Position(one, 1)));
    EXPECT_EQ(PositionInComposedTree(three->firstChild(), 1), nextVisuallyDistinctCandidate(PositionInComposedTree(one, 1)));
}
TEST_F(EditingUtilitiesTest, enclosingNodeOfType)
{
    const char* bodyContent = "<p id='host'><b id='one'>11</b></p>";
    const char* shadowContent = "<content select=#two></content><div id='three'><content select=#one></div></content>";
    setBodyContent(bodyContent);
    RefPtrWillBeRawPtr<ShadowRoot> shadowRoot = setShadowContent(shadowContent, "host");
    updateLayoutAndStyleForPainting();
    Node* host = document().getElementById("host");
    Node* one = document().getElementById("one");
    Node* three = shadowRoot->getElementById("three");

    EXPECT_EQ(host, enclosingNodeOfType(Position(one, 0), isEnclosingBlock));
    EXPECT_EQ(three, enclosingNodeOfType(PositionInComposedTree(one, 0), isEnclosingBlock));
}
TEST_F(SimplifiedBackwardsTextIteratorTest, SubrangeWithReplacedElements)
{
    static const char* bodyContent = "<a id=host><b id=one>one</b> not appeared <b id=two>two</b></a>";
    const char* shadowContent = "three <content select=#two></content> <content select=#one></content> zero";
    setBodyContent(bodyContent);
    setShadowContent(shadowContent, "host");
    updateLayoutAndStyleForPainting();

    Element* host = document().getElementById("host");

    // We should not apply DOM tree version to containing shadow tree in
    // general. To record current behavior, we have this test. even if it
    // isn't intuitive.
    EXPECT_EQ("onetwo", extractString<EditingStrategy>(*host));
    EXPECT_EQ("three two one zero", extractString<EditingInComposedTreeStrategy>(*host));
}
Esempio n. 15
0
TEST_F(VisiblePositionTest, ShadowV0DistributedNodes)
{
    const char* bodyContent = "<p id='host'>00<b id='one'>11</b><b id='two'>22</b>33</p>";
    const char* shadowContent = "<a><span id='s4'>44</span><content select=#two></content><span id='s5'>55</span><content select=#one></content><span id='s6'>66</span></a>";
    setBodyContent(bodyContent);
    RefPtrWillBeRawPtr<ShadowRoot> shadowRoot = setShadowContent(shadowContent, "host");

    RefPtrWillBeRawPtr<Element> body = document().body();
    RefPtrWillBeRawPtr<Element> one = body->querySelector("#one", ASSERT_NO_EXCEPTION);
    RefPtrWillBeRawPtr<Element> two = body->querySelector("#two", ASSERT_NO_EXCEPTION);
    RefPtrWillBeRawPtr<Element> four = shadowRoot->querySelector("#s4", ASSERT_NO_EXCEPTION);
    RefPtrWillBeRawPtr<Element> five = shadowRoot->querySelector("#s5", ASSERT_NO_EXCEPTION);

    EXPECT_EQ(Position(one->firstChild(), 0), canonicalPositionOf(Position(one, 0)));
    EXPECT_EQ(Position(one->firstChild(), 0), createVisiblePosition(Position(one, 0)).deepEquivalent());
    EXPECT_EQ(Position(one->firstChild(), 2), canonicalPositionOf(Position(two.get(), 0)));
    EXPECT_EQ(Position(one->firstChild(), 2), createVisiblePosition(Position(two.get(), 0)).deepEquivalent());

    EXPECT_EQ(PositionInComposedTree(five->firstChild(), 2), canonicalPositionOf(PositionInComposedTree(one.get(), 0)));
    EXPECT_EQ(PositionInComposedTree(five->firstChild(), 2), createVisiblePosition(PositionInComposedTree(one.get(), 0)).deepEquivalent());
    EXPECT_EQ(PositionInComposedTree(four->firstChild(), 2), canonicalPositionOf(PositionInComposedTree(two.get(), 0)));
    EXPECT_EQ(PositionInComposedTree(four->firstChild(), 2), createVisiblePosition(PositionInComposedTree(two.get(), 0)).deepEquivalent());
}
TEST_F(EditingUtilitiesTest, firstEditablePositionAfterPositionInRoot)
{
    const char* bodyContent = "<p id='host' contenteditable><b id='one'>1</b><b id='two'>22</b></p>";
    const char* shadowContent = "<content select=#two></content><content select=#one></content><b id='three'>333</b>";
    setBodyContent(bodyContent);
    RefPtrWillBeRawPtr<ShadowRoot> shadowRoot = setShadowContent(shadowContent, "host");
    updateLayoutAndStyleForPainting();
    Element* host = document().getElementById("host");
    Node* one = document().getElementById("one");
    Node* two = document().getElementById("two");
    Node* three = shadowRoot->getElementById("three");

    EXPECT_EQ(Position(one, 0), firstEditablePositionAfterPositionInRoot(Position(one, 0), *host));
    EXPECT_EQ(Position(one->firstChild(), 0), firstEditableVisiblePositionAfterPositionInRoot(Position(one, 0), *host).deepEquivalent());

    EXPECT_EQ(PositionInComposedTree(one, 0), firstEditablePositionAfterPositionInRoot(PositionInComposedTree(one, 0), *host));
    EXPECT_EQ(PositionInComposedTree(two->firstChild(), 2), firstEditableVisiblePositionAfterPositionInRoot(PositionInComposedTree(one, 0), *host).deepEquivalent());

    EXPECT_EQ(Position::firstPositionInNode(host), firstEditablePositionAfterPositionInRoot(Position(three, 0), *host));
    EXPECT_EQ(Position(one->firstChild(), 0), firstEditableVisiblePositionAfterPositionInRoot(Position(three, 0), *host).deepEquivalent());
    EXPECT_EQ(PositionInComposedTree::afterNode(host), firstEditablePositionAfterPositionInRoot(PositionInComposedTree(three, 0), *host));
    EXPECT_EQ(PositionInComposedTree::lastPositionInNode(host), firstEditableVisiblePositionAfterPositionInRoot(PositionInComposedTree(three, 0), *host).deepEquivalent());
}
TEST_F(VisibleUnitsTest, inSameLine)
{
    const char* bodyContent = "<p id='host'>00<b id='one'>11</b><b id='two'>22</b>33</p>";
    const char* shadowContent = "<div><span id='s4'>44</span><content select=#two></content><br><span id='s5'>55</span><br><content select=#one></content><span id='s6'>66</span></div>";
    setBodyContent(bodyContent);
    RefPtrWillBeRawPtr<ShadowRoot> shadowRoot = setShadowContent(shadowContent);
    updateLayoutAndStyleForPainting();

    RefPtrWillBeRawPtr<Element> body = document().body();
    RefPtrWillBeRawPtr<Element> one = body->querySelector("#one", ASSERT_NO_EXCEPTION);
    RefPtrWillBeRawPtr<Element> two = body->querySelector("#two", ASSERT_NO_EXCEPTION);
    RefPtrWillBeRawPtr<Element> four = shadowRoot->querySelector("#s4", ASSERT_NO_EXCEPTION);
    RefPtrWillBeRawPtr<Element> five = shadowRoot->querySelector("#s5", ASSERT_NO_EXCEPTION);

    EXPECT_TRUE(inSameLine(positionWithAffinityInDOMTree(*one, 0), positionWithAffinityInDOMTree(*two, 0)));
    EXPECT_TRUE(inSameLine(positionWithAffinityInDOMTree(*one->firstChild(), 0), positionWithAffinityInDOMTree(*two->firstChild(), 0)));
    EXPECT_FALSE(inSameLine(positionWithAffinityInDOMTree(*one->firstChild(), 0), positionWithAffinityInDOMTree(*five->firstChild(), 0)));
    EXPECT_FALSE(inSameLine(positionWithAffinityInDOMTree(*two->firstChild(), 0), positionWithAffinityInDOMTree(*four->firstChild(), 0)));

    EXPECT_FALSE(inSameLine(positionWithAffinityInComposedTree(*one, 0), positionWithAffinityInComposedTree(*two, 0)));
    EXPECT_FALSE(inSameLine(positionWithAffinityInComposedTree(*one->firstChild(), 0), positionWithAffinityInComposedTree(*two->firstChild(), 0)));
    EXPECT_FALSE(inSameLine(positionWithAffinityInComposedTree(*one->firstChild(), 0), positionWithAffinityInComposedTree(*five->firstChild(), 0)));
    EXPECT_TRUE(inSameLine(positionWithAffinityInComposedTree(*two->firstChild(), 0), positionWithAffinityInComposedTree(*four->firstChild(), 0)));
}
TEST_F(SimplifiedBackwardsTextIteratorTest, copyTextTo) {
  const char* bodyContent =
      "<a id=host><b id=one>one</b> not appeared <b id=two>two</b></a>";
  const char* shadowContent =
      "three <content select=#two></content> <content select=#one></content> "
      "zero";
  setBodyContent(bodyContent);
  setShadowContent(shadowContent, "host");

  Element* host = document().getElementById("host");
  const char* message =
      "|backIter%d| should have emitted '%s' in reverse order.";

  EphemeralRangeTemplate<EditingStrategy> range1(
      EphemeralRangeTemplate<EditingStrategy>::rangeOfContents(*host));
  SimplifiedBackwardsTextIteratorAlgorithm<EditingStrategy> backIter1(
      range1.startPosition(), range1.endPosition());
  BackwardsTextBuffer output1;
  backIter1.copyTextTo(&output1, 0, 2);
  EXPECT_EQ("wo", String(output1.data(), output1.size()))
      << String::format(message, 1, "wo").utf8().data();
  backIter1.copyTextTo(&output1, 2, 1);
  EXPECT_EQ("two", String(output1.data(), output1.size()))
      << String::format(message, 1, "two").utf8().data();
  backIter1.advance();
  backIter1.copyTextTo(&output1, 0, 1);
  EXPECT_EQ("etwo", String(output1.data(), output1.size()))
      << String::format(message, 1, "etwo").utf8().data();
  backIter1.copyTextTo(&output1, 1, 2);
  EXPECT_EQ("onetwo", String(output1.data(), output1.size()))
      << String::format(message, 1, "onetwo").utf8().data();

  EphemeralRangeTemplate<EditingInFlatTreeStrategy> range2(
      EphemeralRangeTemplate<EditingInFlatTreeStrategy>::rangeOfContents(
          *host));
  SimplifiedBackwardsTextIteratorAlgorithm<EditingInFlatTreeStrategy> backIter2(
      range2.startPosition(), range2.endPosition());
  BackwardsTextBuffer output2;
  backIter2.copyTextTo(&output2, 0, 2);
  EXPECT_EQ("ro", String(output2.data(), output2.size()))
      << String::format(message, 2, "ro").utf8().data();
  backIter2.copyTextTo(&output2, 2, 3);
  EXPECT_EQ(" zero", String(output2.data(), output2.size()))
      << String::format(message, 2, " zero").utf8().data();
  backIter2.advance();
  backIter2.copyTextTo(&output2, 0, 1);
  EXPECT_EQ("e zero", String(output2.data(), output2.size()))
      << String::format(message, 2, "e zero").utf8().data();
  backIter2.copyTextTo(&output2, 1, 2);
  EXPECT_EQ("one zero", String(output2.data(), output2.size()))
      << String::format(message, 2, "one zero").utf8().data();
  backIter2.advance();
  backIter2.copyTextTo(&output2, 0, 1);
  EXPECT_EQ(" one zero", String(output2.data(), output2.size()))
      << String::format(message, 2, " one zero").utf8().data();
  backIter2.advance();
  backIter2.copyTextTo(&output2, 0, 2);
  EXPECT_EQ("wo one zero", String(output2.data(), output2.size()))
      << String::format(message, 2, "wo one zero").utf8().data();
  backIter2.copyTextTo(&output2, 2, 1);
  EXPECT_EQ("two one zero", String(output2.data(), output2.size()))
      << String::format(message, 2, "two one zero").utf8().data();
  backIter2.advance();
  backIter2.copyTextTo(&output2, 0, 3);
  EXPECT_EQ("ee two one zero", String(output2.data(), output2.size()))
      << String::format(message, 2, "ee two one zero").utf8().data();
  backIter2.copyTextTo(&output2, 3, 3);
  EXPECT_EQ("three two one zero", String(output2.data(), output2.size()))
      << String::format(message, 2, "three two one zero").utf8().data();
}