| // Copyright 2016 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "third_party/blink/renderer/core/editing/state_machines/backward_grapheme_boundary_state_machine.h" |
| |
| #include "third_party/blink/renderer/core/editing/state_machines/state_machine_test_util.h" |
| #include "third_party/blink/renderer/platform/wtf/text/character_names.h" |
| |
| namespace blink { |
| |
| namespace backward_grapheme_boundary_state_machine_test { |
| |
| // Notations: |
| // SOT indicates start of text. |
| // [Lead] indicates broken lonely lead surrogate. |
| // [Trail] indicates broken lonely trail surrogate. |
| // [U] indicates regional indicator symbol U. |
| // [S] indicates regional indicator symbol S. |
| |
| // kWatch kVS16, kEye kVS16 are valid standardized variants. |
| const UChar32 kWatch = 0x231A; |
| const UChar32 kEye = WTF::unicode::kEyeCharacter; |
| const UChar32 kVS16 = 0xFE0F; |
| |
| // kHanBMP KVS17, kHanSIP kVS17 are valie IVD sequences. |
| const UChar32 kHanBMP = 0x845B; |
| const UChar32 kHanSIP = 0x20000; |
| const UChar32 kVS17 = 0xE0100; |
| |
| // Following lead/trail values are used for invalid surrogate pairs. |
| const UChar kLead = 0xD83D; |
| const UChar kTrail = 0xDC66; |
| |
| // U+1F1FA is REGIONAL INDICATOR SYMBOL LETTER U |
| // U+1F1F8 is REGIONAL INDICATOR SYMBOL LETTER S |
| const UChar32 kRisU = 0x1F1FA; |
| const UChar32 kRisS = 0x1F1F8; |
| |
| class BackwardGraphemeBoundaryStatemachineTest |
| : public GraphemeStateMachineTestBase { |
| protected: |
| BackwardGraphemeBoundaryStatemachineTest() = default; |
| ~BackwardGraphemeBoundaryStatemachineTest() override = default; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(BackwardGraphemeBoundaryStatemachineTest); |
| }; |
| |
| TEST_F(BackwardGraphemeBoundaryStatemachineTest, DoNothingCase) { |
| BackwardGraphemeBoundaryStateMachine machine; |
| |
| EXPECT_EQ(0, machine.FinalizeAndGetBoundaryOffset()); |
| EXPECT_EQ(0, machine.FinalizeAndGetBoundaryOffset()); |
| } |
| |
| TEST_F(BackwardGraphemeBoundaryStatemachineTest, BrokenSurrogatePair) { |
| BackwardGraphemeBoundaryStateMachine machine; |
| |
| // [Lead] |
| EXPECT_EQ("F", ProcessSequenceBackward(&machine, AsCodePoints(kLead))); |
| EXPECT_EQ(-1, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // 'a' + [Trail] |
| EXPECT_EQ("RF", ProcessSequenceBackward(&machine, AsCodePoints('a', kTrail))); |
| EXPECT_EQ(-1, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // [Trail] + [Trail] |
| EXPECT_EQ("RF", |
| ProcessSequenceBackward(&machine, AsCodePoints(kTrail, kTrail))); |
| EXPECT_EQ(-1, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // SOT + [Trail] |
| EXPECT_EQ("RF", ProcessSequenceBackward(&machine, AsCodePoints(kTrail))); |
| EXPECT_EQ(-1, machine.FinalizeAndGetBoundaryOffset()); |
| } |
| |
| TEST_F(BackwardGraphemeBoundaryStatemachineTest, BreakImmediately_BMP) { |
| BackwardGraphemeBoundaryStateMachine machine; |
| |
| // U+0000 + U+0000 |
| EXPECT_EQ("RF", ProcessSequenceBackward(&machine, AsCodePoints(0, 0))); |
| EXPECT_EQ(-1, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // 'a' + 'a' |
| EXPECT_EQ("RF", ProcessSequenceBackward(&machine, AsCodePoints('a', 'a'))); |
| EXPECT_EQ(-1, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // U+1F441 + 'a' |
| EXPECT_EQ("RRF", ProcessSequenceBackward(&machine, AsCodePoints(kEye, 'a'))); |
| EXPECT_EQ(-1, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // SOT + 'a' |
| EXPECT_EQ("RF", ProcessSequenceBackward(&machine, AsCodePoints('a'))); |
| EXPECT_EQ(-1, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // Broken surrogates. |
| // [Lead] + 'a' |
| EXPECT_EQ("RF", ProcessSequenceBackward(&machine, AsCodePoints(kLead, 'a'))); |
| EXPECT_EQ(-1, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // 'a' + [Trail] + 'a' |
| EXPECT_EQ("RRF", |
| ProcessSequenceBackward(&machine, AsCodePoints('a', kTrail, 'a'))); |
| EXPECT_EQ(-1, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // [Trail] + [Trail] + 'a' |
| EXPECT_EQ("RRF", ProcessSequenceBackward(&machine, |
| AsCodePoints(kTrail, kTrail, 'a'))); |
| EXPECT_EQ(-1, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // SOT + [Trail] + 'a' |
| EXPECT_EQ("RRF", |
| ProcessSequenceBackward(&machine, AsCodePoints(kTrail, 'a'))); |
| EXPECT_EQ(-1, machine.FinalizeAndGetBoundaryOffset()); |
| } |
| |
| TEST_F(BackwardGraphemeBoundaryStatemachineTest, |
| BreakImmediately_SupplementaryPlane) { |
| BackwardGraphemeBoundaryStateMachine machine; |
| |
| // 'a' + U+1F441 |
| EXPECT_EQ("RRF", ProcessSequenceBackward(&machine, AsCodePoints('a', kEye))); |
| EXPECT_EQ(-2, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // U+1F441 + U+1F441 |
| EXPECT_EQ("RRRF", |
| ProcessSequenceBackward(&machine, AsCodePoints(kEye, kEye))); |
| EXPECT_EQ(-2, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // SOT + U+1F441 |
| EXPECT_EQ("RRF", ProcessSequenceBackward(&machine, AsCodePoints(kEye))); |
| EXPECT_EQ(-2, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // Broken surrogates. |
| // [Lead] + U+1F441 |
| EXPECT_EQ("RRF", |
| ProcessSequenceBackward(&machine, AsCodePoints(kLead, kEye))); |
| EXPECT_EQ(-2, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // 'a' + [Trail] + U+1F441 |
| EXPECT_EQ("RRRF", |
| ProcessSequenceBackward(&machine, AsCodePoints('a', kTrail, kEye))); |
| EXPECT_EQ(-2, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // [Trail] + [Trail] + U+1F441 |
| EXPECT_EQ("RRRF", ProcessSequenceBackward( |
| &machine, AsCodePoints(kTrail, kTrail, kEye))); |
| EXPECT_EQ(-2, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // SOT + [Trail] + U+1F441 |
| EXPECT_EQ("RRRF", |
| ProcessSequenceBackward(&machine, AsCodePoints(kTrail, kEye))); |
| EXPECT_EQ(-2, machine.FinalizeAndGetBoundaryOffset()); |
| } |
| |
| TEST_F(BackwardGraphemeBoundaryStatemachineTest, |
| NotBreakImmediatelyBefore_BMP_BMP) { |
| BackwardGraphemeBoundaryStateMachine machine; |
| |
| // 'a' + U+231A + U+FE0F |
| EXPECT_EQ("RRF", ProcessSequenceBackward(&machine, |
| AsCodePoints('a', kWatch, kVS16))); |
| EXPECT_EQ(-2, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // U+1F441 + U+231A + U+FE0F |
| EXPECT_EQ("RRRF", ProcessSequenceBackward(&machine, |
| AsCodePoints(kEye, kWatch, kVS16))); |
| EXPECT_EQ(-2, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // SOT + U+231A + U+FE0F |
| EXPECT_EQ("RRF", |
| ProcessSequenceBackward(&machine, AsCodePoints(kWatch, kVS16))); |
| EXPECT_EQ(-2, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // [Lead] + U+231A + U+FE0F |
| EXPECT_EQ("RRF", ProcessSequenceBackward(&machine, |
| AsCodePoints(kLead, kWatch, kVS16))); |
| EXPECT_EQ(-2, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // 'a' + [Trail] + U+231A + U+FE0F |
| EXPECT_EQ("RRRF", ProcessSequenceBackward( |
| &machine, AsCodePoints('a', kTrail, kWatch, kVS16))); |
| EXPECT_EQ(-2, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // [Trail] + [Trail] + U+231A + U+FE0F |
| EXPECT_EQ("RRRF", ProcessSequenceBackward( |
| &machine, AsCodePoints(kTrail, kTrail, kWatch, kVS16))); |
| EXPECT_EQ(-2, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // SOT + [Trail] + U+231A + U+FE0F |
| EXPECT_EQ("RRRF", ProcessSequenceBackward( |
| &machine, AsCodePoints(kTrail, kWatch, kVS16))); |
| EXPECT_EQ(-2, machine.FinalizeAndGetBoundaryOffset()); |
| } |
| |
| TEST_F(BackwardGraphemeBoundaryStatemachineTest, |
| NotBreakImmediatelyBefore_Supplementary_BMP) { |
| BackwardGraphemeBoundaryStateMachine machine; |
| |
| // 'a' + U+1F441 + U+FE0F |
| EXPECT_EQ("RRRF", |
| ProcessSequenceBackward(&machine, AsCodePoints('a', kEye, kVS16))); |
| EXPECT_EQ(-3, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // U+1F441 + U+1F441 + U+FE0F |
| EXPECT_EQ("RRRRF", |
| ProcessSequenceBackward(&machine, AsCodePoints(kEye, kEye, kVS16))); |
| EXPECT_EQ(-3, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // SOT + U+1F441 + U+FE0F |
| EXPECT_EQ("RRRF", |
| ProcessSequenceBackward(&machine, AsCodePoints(kEye, kVS16))); |
| EXPECT_EQ(-3, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // [Lead] + U+1F441 + U+FE0F |
| EXPECT_EQ("RRRF", ProcessSequenceBackward(&machine, |
| AsCodePoints(kLead, kEye, kVS16))); |
| EXPECT_EQ(-3, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // 'a' + [Trail] + U+1F441 + U+FE0F |
| EXPECT_EQ("RRRRF", ProcessSequenceBackward( |
| &machine, AsCodePoints('a', kTrail, kEye, kVS16))); |
| EXPECT_EQ(-3, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // [Trail] + [Trail] + U+1F441 + U+FE0F |
| EXPECT_EQ("RRRRF", ProcessSequenceBackward( |
| &machine, AsCodePoints(kTrail, kTrail, kEye, kVS16))); |
| EXPECT_EQ(-3, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // SOT + [Trail] + U+1F441 + U+FE0F |
| EXPECT_EQ("RRRRF", ProcessSequenceBackward( |
| &machine, AsCodePoints(kTrail, kEye, kVS16))); |
| EXPECT_EQ(-3, machine.FinalizeAndGetBoundaryOffset()); |
| } |
| |
| TEST_F(BackwardGraphemeBoundaryStatemachineTest, |
| NotBreakImmediatelyBefore_BMP_Supplementary) { |
| BackwardGraphemeBoundaryStateMachine machine; |
| |
| // 'a' + U+845B + U+E0100 |
| EXPECT_EQ("RRRF", ProcessSequenceBackward(&machine, |
| AsCodePoints('a', kHanBMP, kVS17))); |
| EXPECT_EQ(-3, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // U+1F441 + U+845B + U+E0100 |
| EXPECT_EQ("RRRRF", ProcessSequenceBackward( |
| &machine, AsCodePoints(kEye, kHanBMP, kVS17))); |
| EXPECT_EQ(-3, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // SOT + U+845B + U+E0100 |
| EXPECT_EQ("RRRF", |
| ProcessSequenceBackward(&machine, AsCodePoints(kHanBMP, kVS17))); |
| EXPECT_EQ(-3, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // [Lead] + U+845B + U+E0100 |
| EXPECT_EQ("RRRF", ProcessSequenceBackward( |
| &machine, AsCodePoints(kLead, kHanBMP, kVS17))); |
| EXPECT_EQ(-3, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // 'a' + [Trail] + U+845B + U+E0100 |
| EXPECT_EQ("RRRRF", ProcessSequenceBackward( |
| &machine, AsCodePoints('a', kTrail, kHanBMP, kVS17))); |
| EXPECT_EQ(-3, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // [Trail] + [Trail] + U+845B + U+E0100 |
| EXPECT_EQ("RRRRF", |
| ProcessSequenceBackward( |
| &machine, AsCodePoints(kTrail, kTrail, kHanBMP, kVS17))); |
| EXPECT_EQ(-3, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // SOT + [Trail] + U+845B + U+E0100 |
| EXPECT_EQ("RRRRF", ProcessSequenceBackward( |
| &machine, AsCodePoints(kTrail, kHanBMP, kVS17))); |
| EXPECT_EQ(-3, machine.FinalizeAndGetBoundaryOffset()); |
| } |
| |
| TEST_F(BackwardGraphemeBoundaryStatemachineTest, |
| NotBreakImmediatelyBefore_Supplementary_Supplementary) { |
| BackwardGraphemeBoundaryStateMachine machine; |
| |
| // 'a' + U+20000 + U+E0100 |
| EXPECT_EQ("RRRRF", ProcessSequenceBackward( |
| &machine, AsCodePoints('a', kHanSIP, kVS17))); |
| EXPECT_EQ(-4, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // U+1F441 + U+20000 + U+E0100 |
| EXPECT_EQ("RRRRRF", ProcessSequenceBackward( |
| &machine, AsCodePoints(kEye, kHanSIP, kVS17))); |
| EXPECT_EQ(-4, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // SOT + U+20000 + U+E0100 |
| EXPECT_EQ("RRRRF", |
| ProcessSequenceBackward(&machine, AsCodePoints(kHanSIP, kVS17))); |
| EXPECT_EQ(-4, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // [Lead] + U+20000 + U+E0100 |
| EXPECT_EQ("RRRRF", ProcessSequenceBackward( |
| &machine, AsCodePoints(kLead, kHanSIP, kVS17))); |
| EXPECT_EQ(-4, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // 'a' + [Trail] + U+20000 + U+E0100 |
| EXPECT_EQ("RRRRRF", ProcessSequenceBackward( |
| &machine, AsCodePoints('a', kTrail, kHanSIP, kVS17))); |
| EXPECT_EQ(-4, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // [Trail] + [Trail] + U+20000 + U+E0100 |
| EXPECT_EQ("RRRRRF", |
| ProcessSequenceBackward( |
| &machine, AsCodePoints(kTrail, kTrail, kHanSIP, kVS17))); |
| EXPECT_EQ(-4, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // SOT + [Trail] + U+20000 + U+E0100 |
| EXPECT_EQ("RRRRRF", ProcessSequenceBackward( |
| &machine, AsCodePoints(kTrail, kHanSIP, kVS17))); |
| EXPECT_EQ(-4, machine.FinalizeAndGetBoundaryOffset()); |
| } |
| |
| TEST_F(BackwardGraphemeBoundaryStatemachineTest, MuchLongerCase) { |
| const UChar32 kMan = WTF::unicode::kManCharacter; |
| const UChar32 kZwj = WTF::unicode::kZeroWidthJoinerCharacter; |
| const UChar32 kHeart = WTF::unicode::kHeavyBlackHeartCharacter; |
| const UChar32 kKiss = WTF::unicode::kKissMarkCharacter; |
| |
| BackwardGraphemeBoundaryStateMachine machine; |
| |
| // U+1F468 U+200D U+2764 U+FE0F U+200D U+1F48B U+200D U+1F468 is a valid ZWJ |
| // emoji sequence. |
| // 'a' + ZWJ Emoji Sequence |
| EXPECT_EQ("RRRRRRRRRRRF", |
| ProcessSequenceBackward( |
| &machine, AsCodePoints('a', kMan, kZwj, kHeart, kVS16, kZwj, |
| kKiss, kZwj, kMan))); |
| EXPECT_EQ(-11, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // U+1F441 + ZWJ Emoji Sequence |
| EXPECT_EQ("RRRRRRRRRRRRF", |
| ProcessSequenceBackward( |
| &machine, AsCodePoints(kEye, kMan, kZwj, kHeart, kVS16, kZwj, |
| kKiss, kZwj, kMan))); |
| EXPECT_EQ(-11, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // SOT + ZWJ Emoji Sequence |
| EXPECT_EQ( |
| "RRRRRRRRRRRF", |
| ProcessSequenceBackward(&machine, AsCodePoints(kMan, kZwj, kHeart, kVS16, |
| kZwj, kKiss, kZwj, kMan))); |
| EXPECT_EQ(-11, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // [Lead] + ZWJ Emoji Sequence |
| EXPECT_EQ("RRRRRRRRRRRF", |
| ProcessSequenceBackward( |
| &machine, AsCodePoints(kLead, kMan, kZwj, kHeart, kVS16, kZwj, |
| kKiss, kZwj, kMan))); |
| EXPECT_EQ(-11, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // 'a' + [Trail] + ZWJ Emoji Sequence |
| EXPECT_EQ("RRRRRRRRRRRRF", |
| ProcessSequenceBackward( |
| &machine, AsCodePoints('a', kTrail, kMan, kZwj, kHeart, kVS16, |
| kZwj, kKiss, kZwj, kMan))); |
| EXPECT_EQ(-11, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // [Trail] + [Trail] + ZWJ Emoji Sequence |
| EXPECT_EQ("RRRRRRRRRRRRF", |
| ProcessSequenceBackward( |
| &machine, AsCodePoints(kTrail, kTrail, kMan, kZwj, kHeart, |
| kVS16, kZwj, kKiss, kZwj, kMan))); |
| EXPECT_EQ(-11, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // SOT + [Trail] + ZWJ Emoji Sequence |
| EXPECT_EQ("RRRRRRRRRRRRF", |
| ProcessSequenceBackward( |
| &machine, AsCodePoints(kTrail, kMan, kZwj, kHeart, kVS16, kZwj, |
| kKiss, kZwj, kMan))); |
| EXPECT_EQ(-11, machine.FinalizeAndGetBoundaryOffset()); |
| } |
| |
| TEST_F(BackwardGraphemeBoundaryStatemachineTest, Flags_singleFlag) { |
| BackwardGraphemeBoundaryStateMachine machine; |
| |
| // 'a' + [U] + [S] |
| EXPECT_EQ("RRRRF", |
| ProcessSequenceBackward(&machine, AsCodePoints('a', kRisU, kRisS))); |
| EXPECT_EQ(-4, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // U+1F441 + [U] + [S] |
| EXPECT_EQ("RRRRRF", ProcessSequenceBackward( |
| &machine, AsCodePoints(kEye, kRisU, kRisS))); |
| EXPECT_EQ(-4, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // SOT + [U] + [S] |
| EXPECT_EQ("RRRRF", |
| ProcessSequenceBackward(&machine, AsCodePoints(kRisU, kRisS))); |
| EXPECT_EQ(-4, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // [Lead] + [U] + [S] |
| EXPECT_EQ("RRRRF", ProcessSequenceBackward( |
| &machine, AsCodePoints(kLead, kRisU, kRisS))); |
| EXPECT_EQ(-4, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // 'a' + [Trail] + [U] + [S] |
| EXPECT_EQ("RRRRRF", ProcessSequenceBackward( |
| &machine, AsCodePoints('a', kTrail, kRisU, kRisS))); |
| EXPECT_EQ(-4, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // [Trail] + [Trail] + [U] + [S] |
| EXPECT_EQ("RRRRRF", |
| ProcessSequenceBackward( |
| &machine, AsCodePoints(kTrail, kTrail, kRisU, kRisS))); |
| EXPECT_EQ(-4, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // SOT + [Trail] + [U] + [S] |
| EXPECT_EQ("RRRRRF", ProcessSequenceBackward( |
| &machine, AsCodePoints(kTrail, kRisU, kRisS))); |
| EXPECT_EQ(-4, machine.FinalizeAndGetBoundaryOffset()); |
| } |
| |
| TEST_F(BackwardGraphemeBoundaryStatemachineTest, Flags_twoFlags) { |
| BackwardGraphemeBoundaryStateMachine machine; |
| |
| // 'a' + [U] + [S] + [U] + [S] |
| EXPECT_EQ("RRRRRRRRF", |
| ProcessSequenceBackward( |
| &machine, AsCodePoints('a', kRisU, kRisS, kRisU, kRisS))); |
| EXPECT_EQ(-4, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // U+1F441 + [U] + [S] + [U] + [S] |
| EXPECT_EQ("RRRRRRRRRF", |
| ProcessSequenceBackward( |
| &machine, AsCodePoints(kEye, kRisU, kRisS, kRisU, kRisS))); |
| EXPECT_EQ(-4, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // SOT + [U] + [S] + [U] + [S] |
| EXPECT_EQ("RRRRRRRRF", |
| ProcessSequenceBackward(&machine, |
| AsCodePoints(kRisU, kRisS, kRisU, kRisS))); |
| EXPECT_EQ(-4, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // [Lead] + [U] + [S] + [U] + [S] |
| EXPECT_EQ("RRRRRRRRF", |
| ProcessSequenceBackward( |
| &machine, AsCodePoints(kLead, kRisU, kRisS, kRisU, kRisS))); |
| EXPECT_EQ(-4, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // 'a' + [Trail] + [U] + [S] + [U] + [S] |
| EXPECT_EQ("RRRRRRRRRF", ProcessSequenceBackward( |
| &machine, AsCodePoints('a', kTrail, kRisU, kRisS, |
| kRisU, kRisS))); |
| EXPECT_EQ(-4, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // [Trail] + [Trail] + [U] + [S] + [U] + [S] |
| EXPECT_EQ("RRRRRRRRRF", ProcessSequenceBackward( |
| &machine, AsCodePoints(kTrail, kTrail, kRisU, |
| kRisS, kRisU, kRisS))); |
| EXPECT_EQ(-4, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // SOT + [Trail] + [U] + [S] + [U] + [S] |
| EXPECT_EQ("RRRRRRRRRF", |
| ProcessSequenceBackward( |
| &machine, AsCodePoints(kTrail, kRisU, kRisS, kRisU, kRisS))); |
| EXPECT_EQ(-4, machine.FinalizeAndGetBoundaryOffset()); |
| } |
| |
| TEST_F(BackwardGraphemeBoundaryStatemachineTest, Flags_oddNumberedRIS) { |
| BackwardGraphemeBoundaryStateMachine machine; |
| |
| // 'a' + [U] + [S] + [U] |
| EXPECT_EQ("RRRRRRF", ProcessSequenceBackward( |
| &machine, AsCodePoints('a', kRisU, kRisS, kRisU))); |
| EXPECT_EQ(-2, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // U+1F441 + [U] + [S] + [U] |
| EXPECT_EQ("RRRRRRRF", ProcessSequenceBackward( |
| &machine, AsCodePoints(kEye, kRisU, kRisS, kRisU))); |
| EXPECT_EQ(-2, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // SOT + [U] + [S] + [U] |
| EXPECT_EQ("RRRRRRF", ProcessSequenceBackward( |
| &machine, AsCodePoints(kRisU, kRisS, kRisU))); |
| EXPECT_EQ(-2, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // [Lead] + [U] + [S] + [U] |
| EXPECT_EQ("RRRRRRF", ProcessSequenceBackward( |
| &machine, AsCodePoints(kLead, kRisU, kRisS, kRisU))); |
| EXPECT_EQ(-2, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // 'a' + [Trail] + [U] + [S] + [U] |
| EXPECT_EQ("RRRRRRRF", |
| ProcessSequenceBackward( |
| &machine, AsCodePoints('a', kTrail, kRisU, kRisS, kRisU))); |
| EXPECT_EQ(-2, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // [Trail] + [Trail] + [U] + [S] + [U] |
| EXPECT_EQ("RRRRRRRF", |
| ProcessSequenceBackward( |
| &machine, AsCodePoints(kTrail, kTrail, kRisU, kRisS, kRisU))); |
| EXPECT_EQ(-2, machine.FinalizeAndGetBoundaryOffset()); |
| |
| // SOT + [Trail] + [U] + [S] + [U] |
| EXPECT_EQ("RRRRRRRF", |
| ProcessSequenceBackward(&machine, |
| AsCodePoints(kTrail, kRisU, kRisS, kRisU))); |
| EXPECT_EQ(-2, machine.FinalizeAndGetBoundaryOffset()); |
| } |
| |
| } // namespace backward_grapheme_boundary_state_machine_test |
| |
| } // namespace blink |