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))); }
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))); }
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)); }
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)); }
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(); }