Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(345)

Unified Diff: third_party/WebKit/Source/core/editing/state_machines/BackspaceStateMachineTest.cpp

Issue 1844663002: Implement backspace state machine for complex emoji sequence. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Move char definitions to CharacterNames.h Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/editing/state_machines/BackspaceStateMachineTest.cpp
diff --git a/third_party/WebKit/Source/core/editing/state_machines/BackspaceStateMachineTest.cpp b/third_party/WebKit/Source/core/editing/state_machines/BackspaceStateMachineTest.cpp
index cfdd8a1e573a4e38254f288bcd6f43795e43864c..16d8f0c842dd5a4e141d033a37a3886228150658 100644
--- a/third_party/WebKit/Source/core/editing/state_machines/BackspaceStateMachineTest.cpp
+++ b/third_party/WebKit/Source/core/editing/state_machines/BackspaceStateMachineTest.cpp
@@ -5,6 +5,7 @@
#include "core/editing/state_machines/BackspaceStateMachine.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "wtf/text/Unicode.h"
namespace blink {
@@ -49,8 +50,8 @@ TEST(BackspaceStateMachineTest, SurrogatePair)
BackspaceStateMachine machine;
// U+1F5FA(WORLD MAP) is \uD83D\uDDFA in UTF-16.
- uint16_t leadSurrogate = 0xD83D;
- uint16_t trailSurrogate = 0xDDFA;
+ const UChar leadSurrogate = 0xD83D;
+ const UChar trailSurrogate = 0xDDFA;
EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(trailSurrogate));
EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(leadSurrogate));
@@ -83,4 +84,787 @@ TEST(BackspaceStateMachineTest, SurrogatePair)
EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
}
+TEST(BackspaceStateMachineTest, CRLF)
+{
+ BackspaceStateMachine machine;
+
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit('\r'));
+ EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
+
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit('\n'));
+ EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
+
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit('\n'));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(' '));
+ EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
+
+ // CR LF should be deleted at the same time.
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit('\n'));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit('\r'));
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+}
+
+TEST(BackspaceStateMachineTest, KeyCap)
+{
+ BackspaceStateMachine machine;
+
+ const UChar keycap = 0x20E3;
+ const UChar vs16 = 0xFE0F;
+ const UChar notKeycapBaseLead = 0xD83C;
+ const UChar notKeycapBaseTrail = 0xDCCF;
+
+ // keycapBase + keycap
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(keycap));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit('0'));
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+
+ // keycapBase + VS + keycap
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(keycap));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs16));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit('0'));
+ EXPECT_EQ(-3, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-3, machine.finalizeAndGetBoundaryOffset());
+
+ // Followings are edge cases. Remove only keycap character.
+ // Not keycapBase + keycap
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(keycap));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit('a'));
+ EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
+
+ // Not keycapBase + VS + keycap
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(keycap));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs16));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit('a'));
+ EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
+
+ // Not keycapBase(surrogate pair) + keycap
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(keycap));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(notKeycapBaseTrail));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(notKeycapBaseLead));
+ EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
+
+ // Not keycapBase(surrogate pair) + VS + keycap
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(keycap));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs16));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(notKeycapBaseTrail));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(notKeycapBaseLead));
+ EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
+
+ // Sot + keycap
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(keycap));
+ EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
+
+ // Sot + VS + keycap
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(keycap));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs16));
+ EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
+}
+
+TEST(BackspaceStateMachineTest, EmojiModifier)
+{
+ BackspaceStateMachine machine;
+
+ const UChar emojiModifierLead = 0xD83C;
+ const UChar emojiModifierTrail = 0xDFFB;
+ const UChar emojiModifierBase = 0x261D;
+ const UChar emojiModifierBaseLead = 0xD83D;
+ const UChar emojiModifierBaseTrail = 0xDC66;
+ const UChar notEmojiModifierBaseLead = 0xD83C;
+ const UChar notEmojiModifierBaseTrail = 0xDCCF;
+ const UChar vs16 = 0xFE0F;
+
+ // EMOJI_MODIFIER_BASE + EMOJI_MODIFIER
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(emojiModifierTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(emojiModifierLead));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(emojiModifierBase));
+ EXPECT_EQ(-3, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-3, machine.finalizeAndGetBoundaryOffset());
+
+ // EMOJI_MODIFIER_BASE(surrogate pairs) + EMOJI_MODIFIER
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(emojiModifierTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(emojiModifierLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(emojiModifierBaseTrail));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(emojiModifierBaseLead));
+ EXPECT_EQ(-4, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-4, machine.finalizeAndGetBoundaryOffset());
+
+ // EMOJI_MODIFIER_BASE + VS + EMOJI_MODIFIER
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(emojiModifierTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(emojiModifierLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs16));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(emojiModifierBase));
+ EXPECT_EQ(-4, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-4, machine.finalizeAndGetBoundaryOffset());
+
+ // EMOJI_MODIFIER_BASE(surrogate pairs) + VS + EMOJI_MODIFIER
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(emojiModifierTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(emojiModifierLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs16));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(emojiModifierBaseTrail));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(emojiModifierBaseLead));
+ EXPECT_EQ(-5, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-5, machine.finalizeAndGetBoundaryOffset());
+
+ // Followings are edge cases. Remove only emoji modifier.
+ // Not EMOJI_MODIFIER_BASE + EMOJI_MODIFIER
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(emojiModifierTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(emojiModifierLead));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit('a'));
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+
+ // Not EMOJI_MODIFIER_BASE(surrogate pairs) + EMOJI_MODIFIER
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(emojiModifierTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(emojiModifierLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(notEmojiModifierBaseTrail));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(notEmojiModifierBaseLead));
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+
+ // Not EMOJI_MODIFIER_BASE + VS + EMOJI_MODIFIER
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(emojiModifierTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(emojiModifierLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs16));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit('a'));
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+
+ // Not EMOJI_MODIFIER_BASE(surrogate pairs) + VS + EMOJI_MODIFIER
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(emojiModifierTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(emojiModifierLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs16));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(notEmojiModifierBaseTrail));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(notEmojiModifierBaseLead));
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+
+ // Sot + EMOJI_MODIFIER
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(emojiModifierTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(emojiModifierLead));
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+
+ // Sot + VS + EMOJI_MODIFIER
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(emojiModifierTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(emojiModifierLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs16));
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+}
+
+TEST(BackspaceStateMachineTest, RegionalIndicator)
+{
+ BackspaceStateMachine machine;
+
+ const UChar regionalIndicatorULead = 0xD83C;
+ const UChar regionalIndicatorUTrail = 0xDDFA;
+ const UChar regionalIndicatorSLead = 0xD83C;
+ const UChar regionalIndicatorSTrail = 0xDDF8;
+ const UChar notRegionalIndicatorLead = 0xD83C;
+ const UChar notRegionalIndicatorTrail = 0xDCCF;
+
+ // Not RI + RI + RI
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorUTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorULead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorSTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorSLead));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit('a'));
+ EXPECT_EQ(-4, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-4, machine.finalizeAndGetBoundaryOffset());
+
+ // Not RI(surrogate pairs) + RI + RI
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorUTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorULead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorSTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorSLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(notRegionalIndicatorTrail));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(notRegionalIndicatorLead));
+ EXPECT_EQ(-4, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-4, machine.finalizeAndGetBoundaryOffset());
+
+ // Sot + RI + RI
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorUTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorULead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorSTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorSLead));
+ EXPECT_EQ(-4, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-4, machine.finalizeAndGetBoundaryOffset());
+
+ // Not RI + RI + RI + RI + RI
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorUTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorULead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorSTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorSLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorUTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorULead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorSTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorSLead));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit('a'));
+ EXPECT_EQ(-4, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-4, machine.finalizeAndGetBoundaryOffset());
+
+ // Not RI(surrogate pairs) + RI + RI + RI + RI
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorUTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorULead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorSTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorSLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorUTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorULead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorSTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorSLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(notRegionalIndicatorTrail));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(notRegionalIndicatorLead));
+ EXPECT_EQ(-4, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-4, machine.finalizeAndGetBoundaryOffset());
+
+ // Sot + RI + RI + RI + RI
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorUTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorULead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorSTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorSLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorUTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorULead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorSTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorSLead));
+ EXPECT_EQ(-4, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-4, machine.finalizeAndGetBoundaryOffset());
+
+ // Followings are edge cases. Delete last regional indicator only.
+ // Not RI + RI
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorUTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorULead));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit('a'));
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+
+ // Not RI(surrogate pairs) + RI
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorUTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorULead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(notRegionalIndicatorTrail));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(notRegionalIndicatorLead));
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+
+ // Sot + RI
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorUTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorULead));
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+
+ // Not RI + RI + RI + RI
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorUTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorULead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorSTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorSLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorUTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorULead));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit('a'));
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+
+ // Not RI(surrogate pairs) + RI + RI + RI
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorUTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorULead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorSTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorSLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorUTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorULead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(notRegionalIndicatorTrail));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(notRegionalIndicatorLead));
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+
+ // Sot + RI + RI + RI
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorUTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorULead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorSTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorSLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorUTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(regionalIndicatorULead));
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+}
+
+TEST(BackspaceStateMachineTest, VariationSequencec)
+{
+ BackspaceStateMachine machine;
+
+ UChar vs16 = 0xFE0F;
+ UChar vs16Base = '0';
+ UChar vs16BaseLead = 0xD83C;
+ UChar vs16BaseTrail = 0xDD70;
+
+ UChar vs17Lead = 0xDB40;
+ UChar vs17Trail = 0xDD00;
+ UChar vs17Base = 0x3402;
+ UChar vs17BaseLead = 0xD841;
+ UChar vs17BaseTrail = 0xDC8C;
+
+ UChar mongolianVs = 0x180B;
+ UChar mongolianVsBase = 0x1820;
+ // Variation selectors can't be a base of variation sequence.
+ UChar notvsBase = 0xFE00;
+ UChar notvsBaseLead = 0xDB40;
+ UChar notvsBaseTrail = 0xDD01;
+
+ // VS_BASE + VS
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs16));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(vs16Base));
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+
+ // VS_BASE + VS(surrogate pairs)
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs17Trail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs17Lead));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(vs17Base));
+ EXPECT_EQ(-3, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-3, machine.finalizeAndGetBoundaryOffset());
+
+ // VS_BASE(surrogate pairs) + VS
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs16));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs16BaseTrail));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(vs16BaseLead));
+ EXPECT_EQ(-3, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-3, machine.finalizeAndGetBoundaryOffset());
+
+ // VS_BASE(surrogate pairs) + VS(surrogate pairs)
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs17Trail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs17Lead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs17BaseTrail));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(vs17BaseLead));
+ EXPECT_EQ(-4, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-4, machine.finalizeAndGetBoundaryOffset());
+
+ // mongolianVsBase + mongolianVs
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(mongolianVs));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(mongolianVsBase));
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+
+ // Followings are edge case. Delete only variation selector.
+ // Not VS_BASE + VS
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs16));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(notvsBase));
+ EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
+
+ // Not VS_BASE + VS(surrogate pairs)
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs17Trail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs17Lead));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(notvsBase));
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+
+ // Not VS_BASE(surrogate pairs) + VS
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs16));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(notvsBaseTrail));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(notvsBaseLead));
+ EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
+
+ // Not VS_BASE(surrogate pairs) + VS(surrogate pairs)
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs17Trail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs17Lead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(notvsBaseTrail));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(notvsBaseLead));
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+
+ // Not VS_BASE + MONGOLIAN_VS
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(mongolianVs));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(notvsBase));
+ EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
+
+ // Not VS_BASE(surrogate pairs) + MONGOLIAN_VS
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(mongolianVs));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(notvsBaseTrail));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(notvsBaseLead));
+ EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
+
+ // Sot + VS
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs16));
+ EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
+
+ // Sot + VS(surrogate pair)
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs17Trail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs17Lead));
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+
+ // Sot + MONGOLIAN_VS
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(mongolianVs));
+ EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
+}
+
+TEST(BackspaceStateMachineTest, ZWJSequence)
+{
+ BackspaceStateMachine machine;
+
+ const UChar zwj = 0x200D;
+ const UChar eyeLead = 0xD83D;
+ const UChar eyeTrail = 0xDC41;
+ const UChar leftSpeachBubbleLead = 0xD83D;
+ const UChar leftSpeachBubbleTrail = 0xDDE8;
+ const UChar manLead = 0xD83D;
+ const UChar manTrail = 0xDC68;
+ const UChar boyLead = 0xD83D;
+ const UChar boyTrail = 0xDC66;
+ const UChar heart = 0x2764;
+ const UChar kissLead = 0xD83D;
+ const UChar killTrail = 0xDC8B;
+ const UChar vs16 = 0xFE0F;
+ const UChar other = 'a';
+ const UChar otherLead = 0xD83C;
+ const UChar otherTrail = 0xDCCF;
+
+ // Followings are chosen from valid zwj sequcne.
+ // See http://www.unicode.org/Public/emoji/2.0//emoji-zwj-sequences.txt
+
+ // others + ZWJ_EMOJI + ZWJ + ZWJ_EMOJI
+ // As an example, use EYE + ZWJ + LEFT_SPEACH_BUBBLE
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(leftSpeachBubbleTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(leftSpeachBubbleLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(zwj));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(eyeTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(eyeLead));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(other));
+ EXPECT_EQ(-5, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-5, machine.finalizeAndGetBoundaryOffset());
+
+ // others(surrogate pairs) + ZWJ_EMOJI + ZWJ + ZWJ_EMOJI
+ // As an example, use EYE + ZWJ + LEFT_SPEACH_BUBBLE
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(leftSpeachBubbleTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(leftSpeachBubbleLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(zwj));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(eyeTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(eyeLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(otherTrail));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(otherLead));
+ EXPECT_EQ(-5, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-5, machine.finalizeAndGetBoundaryOffset());
+
+ // Sot + ZWJ_EMOJI + ZWJ + ZWJ_EMOJI
+ // As an example, use EYE + ZWJ + LEFT_SPEACH_BUBBLE
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(leftSpeachBubbleTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(leftSpeachBubbleLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(zwj));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(eyeTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(eyeLead));
+ EXPECT_EQ(-5, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-5, machine.finalizeAndGetBoundaryOffset());
+
+ // others + ZWJ_EMOJI + ZWJ + ZWJ_EMOJI + ZWJ + ZWJ_EMOJI
+ // As an example, use MAN + ZWJ + heart + ZWJ + MAN
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(zwj));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(heart));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(zwj));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manLead));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(other));
+ EXPECT_EQ(-7, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-7, machine.finalizeAndGetBoundaryOffset());
+
+ // others(surrogate pairs) + ZWJ_EMOJI + ZWJ + ZWJ_EMOJI + ZWJ + ZWJ_EMOJI
+ // As an example, use MAN + ZWJ + heart + ZWJ + MAN
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(zwj));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(heart));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(zwj));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(otherTrail));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(otherLead));
+ EXPECT_EQ(-7, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-7, machine.finalizeAndGetBoundaryOffset());
+
+ // Sot + ZWJ_EMOJI + ZWJ + ZWJ_EMOJI + ZWJ + ZWJ_EMOJI
+ // As an example, use MAN + ZWJ + heart + ZWJ + MAN
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(zwj));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(heart));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(zwj));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manLead));
+ EXPECT_EQ(-7, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-7, machine.finalizeAndGetBoundaryOffset());
+
+ // others + ZWJ_EMOJI + ZWJ + ZWJ_EMOJI + VS + ZWJ + ZWJ_EMOJI
+ // As an example, use MAN + ZWJ + heart + vs16 + ZWJ + MAN
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(zwj));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs16));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(heart));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(zwj));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manLead));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(other));
+ EXPECT_EQ(-8, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-8, machine.finalizeAndGetBoundaryOffset());
+
+ // others(surrogate pairs) + ZWJ_EMOJI + ZWJ + ZWJ_EMOJI + VS + ZWJ + ZWJ_EMOJI
+ // As an example, use MAN + ZWJ + heart + vs16 + ZWJ + MAN
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(zwj));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs16));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(heart));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(zwj));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(otherTrail));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(otherLead));
+ EXPECT_EQ(-8, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-8, machine.finalizeAndGetBoundaryOffset());
+
+ // Sot + ZWJ_EMOJI + ZWJ + ZWJ_EMOJI + VS + ZWJ + ZWJ_EMOJI
+ // As an example, use MAN + ZWJ + heart + vs16 + ZWJ + MAN
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(zwj));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs16));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(heart));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(zwj));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manLead));
+ EXPECT_EQ(-8, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-8, machine.finalizeAndGetBoundaryOffset());
+
+ // others + ZWJ_EMOJI + ZWJ + ZWJ_EMOJI + ZWJ + ZWJ_EMOJI + ZWJ + ZWJ_EMOJI
+ // As an example, use MAN + ZWJ + MAN + ZWJ + boy + ZWJ + BOY
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(boyTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(boyLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(zwj));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(boyTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(boyLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(zwj));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(zwj));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manLead));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(other));
+ EXPECT_EQ(-11, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-11, machine.finalizeAndGetBoundaryOffset());
+
+ // others(surrogate pairs) + ZWJ_EMOJI + ZWJ + ZWJ_EMOJI + ZWJ + ZWJ_EMOJI + ZWJ + ZWJ_EMOJI
+ // As an example, use MAN + ZWJ + MAN + ZWJ + boy + ZWJ + BOY
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(boyTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(boyLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(zwj));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(boyTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(boyLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(zwj));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(zwj));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(otherTrail));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(otherLead));
+ EXPECT_EQ(-11, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-11, machine.finalizeAndGetBoundaryOffset());
+
+ // Sot + ZWJ_EMOJI + ZWJ + ZWJ_EMOJI + ZWJ + ZWJ_EMOJI + ZWJ + ZWJ_EMOJI
+ // As an example, use MAN + ZWJ + MAN + ZWJ + boy + ZWJ + BOY
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(boyTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(boyLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(zwj));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(boyTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(boyLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(zwj));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(zwj));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manLead));
+ EXPECT_EQ(-11, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-11, machine.finalizeAndGetBoundaryOffset());
+
+ // others + ZWJ_EMOJI + ZWJ + ZWJ_EMOJI + VS + ZWJ + ZWJ_EMOJI + ZWJ + ZWJ_EMOJI
+ // As an example, use MAN + ZWJ + heart + VS + ZWJ + KISS + ZWJ + MAN
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(zwj));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(killTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(kissLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(zwj));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs16));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(heart));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(zwj));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manLead));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(other));
+ EXPECT_EQ(-11, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-11, machine.finalizeAndGetBoundaryOffset());
+
+ // others(surrogate pairs) + ZWJ_EMOJI + ZWJ + ZWJ_EMOJI + VS + ZWJ + ZWJ_EMOJI + ZWJ + ZWJ_EMOJI
+ // As an example, use MAN + ZWJ + heart + VS + ZWJ + KISS + ZWJ + MAN
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(zwj));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(killTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(kissLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(zwj));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs16));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(heart));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(zwj));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(otherTrail));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(otherLead));
+ EXPECT_EQ(-11, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-11, machine.finalizeAndGetBoundaryOffset());
+
+ // Sot + ZWJ_EMOJI + ZWJ + ZWJ_EMOJI + VS + ZWJ + ZWJ_EMOJI + ZWJ + ZWJ_EMOJI
+ // As an example, use MAN + ZWJ + heart + VS + ZWJ + KISS + ZWJ + MAN
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(zwj));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(killTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(kissLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(zwj));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(vs16));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(heart));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(zwj));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manLead));
+ EXPECT_EQ(-11, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-11, machine.finalizeAndGetBoundaryOffset());
+
+ // Followings are not edge cases but good to check.
+ // If leading character is not zwj, delete only ZWJ_EMOJI.
+ // other + ZWJ_EMOJI
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(heart));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(other));
+ EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
+
+ // other(surrogate pairs) + ZWJ_EMOJI
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(heart));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(otherTrail));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(otherLead));
+ EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
+
+ // Sot + ZWJ_EMOJI
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(heart));
+ EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
+
+ // other + ZWJ_EMOJI(surrogate pairs)
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manLead));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(other));
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+
+ // other(surrogate pairs) + ZWJ_EMOJI(surrogate pairs)
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manLead));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(otherTrail));
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(otherLead));
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+
+ // Sot + ZWJ_EMOJI(surrogate pairs)
+ machine.reset();
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manTrail));
+ EXPECT_EQ(kNeedMoreCodeUnit, machine.feedPrecedingCodeUnit(manLead));
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+ EXPECT_EQ(-2, machine.finalizeAndGetBoundaryOffset());
+
+ // Followings are edge case.
+ // It is hard to list all edge case patterns. Check only over deleting by ZWJ.
+ // any + ZWJ: should delete only last ZWJ.
+ machine.reset();
+ EXPECT_EQ(kFinished, machine.feedPrecedingCodeUnit(zwj));
+ EXPECT_EQ(-1, machine.finalizeAndGetBoundaryOffset());
+}
} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698