blob: f12b603f50694b9e7a64b1f11785bfc83f36a1ba [file] [log] [blame]
// 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/forward_grapheme_boundary_state_machine.h"
#include "testing/gtest/include/gtest/gtest.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 forward_grapheme_boundary_state_machine_test {
// Notations:
// | indicates inidicates initial offset position.
// SOT indicates start of text.
// EOT indicates end 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
const UChar32 kRisU = 0x1F1FA;
// U+1F1F8 is REGIONAL INDICATOR SYMBOL LETTER S
const UChar32 kRisS = 0x1F1F8;
class ForwardGraphemeBoundaryStatemachineTest
: public GraphemeStateMachineTestBase {
protected:
ForwardGraphemeBoundaryStatemachineTest() = default;
~ForwardGraphemeBoundaryStatemachineTest() override = default;
private:
DISALLOW_COPY_AND_ASSIGN(ForwardGraphemeBoundaryStatemachineTest);
};
TEST_F(ForwardGraphemeBoundaryStatemachineTest, DoNothingCase) {
ForwardGraphemeBoundaryStateMachine machine;
EXPECT_EQ(0, machine.FinalizeAndGetBoundaryOffset());
EXPECT_EQ(0, machine.FinalizeAndGetBoundaryOffset());
}
TEST_F(ForwardGraphemeBoundaryStatemachineTest, PrecedingText) {
ForwardGraphemeBoundaryStateMachine machine;
// Preceding text should not affect the result except for flags.
// SOT + | + 'a' + 'a'
EXPECT_EQ("SRF", ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints('a', 'a')));
EXPECT_EQ(1, machine.FinalizeAndGetBoundaryOffset());
// SOT + [U] + | + 'a' + 'a'
EXPECT_EQ("RRSRF", ProcessSequenceForward(&machine, AsCodePoints(kRisU),
AsCodePoints('a', 'a')));
EXPECT_EQ(1, machine.FinalizeAndGetBoundaryOffset());
// SOT + [U] + [S] + | + 'a' + 'a'
EXPECT_EQ("RRRRSRF",
ProcessSequenceForward(&machine, AsCodePoints(kRisU, kRisS),
AsCodePoints('a', 'a')));
EXPECT_EQ(1, machine.FinalizeAndGetBoundaryOffset());
// U+0000 + | + 'a' + 'a'
EXPECT_EQ("SRF", ProcessSequenceForward(&machine, AsCodePoints(0),
AsCodePoints('a', 'a')));
EXPECT_EQ(1, machine.FinalizeAndGetBoundaryOffset());
// U+0000 + [U] + | + 'a' + 'a'
EXPECT_EQ("RRSRF", ProcessSequenceForward(&machine, AsCodePoints(0, kRisU),
AsCodePoints('a', 'a')));
EXPECT_EQ(1, machine.FinalizeAndGetBoundaryOffset());
// U+0000 + [U] + [S] + | + 'a' + 'a'
EXPECT_EQ("RRRRSRF",
ProcessSequenceForward(&machine, AsCodePoints(0, kRisU, kRisS),
AsCodePoints('a', 'a')));
EXPECT_EQ(1, machine.FinalizeAndGetBoundaryOffset());
// 'a' + | + 'a' + 'a'
EXPECT_EQ("SRF", ProcessSequenceForward(&machine, AsCodePoints('a'),
AsCodePoints('a', 'a')));
EXPECT_EQ(1, machine.FinalizeAndGetBoundaryOffset());
// 'a' + [U] + | + 'a' + 'a'
EXPECT_EQ("RRSRF", ProcessSequenceForward(&machine, AsCodePoints('a', kRisU),
AsCodePoints('a', 'a')));
EXPECT_EQ(1, machine.FinalizeAndGetBoundaryOffset());
// 'a' + [U] + [S] + | + 'a' + 'a'
EXPECT_EQ("RRRRSRF",
ProcessSequenceForward(&machine, AsCodePoints('a', kRisU, kRisS),
AsCodePoints('a', 'a')));
EXPECT_EQ(1, machine.FinalizeAndGetBoundaryOffset());
// U+1F441 + | + 'a' + 'a'
EXPECT_EQ("RSRF", ProcessSequenceForward(&machine, AsCodePoints(kEye),
AsCodePoints('a', 'a')));
EXPECT_EQ(1, machine.FinalizeAndGetBoundaryOffset());
// U+1F441 + [U] + | + 'a' + 'a'
EXPECT_EQ("RRRSRF",
ProcessSequenceForward(&machine, AsCodePoints(kEye, kRisU),
AsCodePoints('a', 'a')));
EXPECT_EQ(1, machine.FinalizeAndGetBoundaryOffset());
// U+1F441 + [U] + [S] + | + 'a' + 'a'
EXPECT_EQ("RRRRRSRF",
ProcessSequenceForward(&machine, AsCodePoints(kEye, kRisU, kRisS),
AsCodePoints('a', 'a')));
EXPECT_EQ(1, machine.FinalizeAndGetBoundaryOffset());
// Broken surrogates in preceding text.
// [Lead] + | + 'a' + 'a'
EXPECT_EQ("SRF", ProcessSequenceForward(&machine, AsCodePoints(kLead),
AsCodePoints('a', 'a')));
EXPECT_EQ(1, machine.FinalizeAndGetBoundaryOffset());
// [Lead] + [U] + | + 'a' + 'a'
EXPECT_EQ("RRSRF",
ProcessSequenceForward(&machine, AsCodePoints(kLead, kRisU),
AsCodePoints('a', 'a')));
EXPECT_EQ(1, machine.FinalizeAndGetBoundaryOffset());
// [Lead] + [U] + [S] + | + 'a' + 'a'
EXPECT_EQ("RRRRSRF",
ProcessSequenceForward(&machine, AsCodePoints(kLead, kRisU, kRisS),
AsCodePoints('a', 'a')));
EXPECT_EQ(1, machine.FinalizeAndGetBoundaryOffset());
// 'a' + [Trail] + | + 'a' + 'a'
EXPECT_EQ("RSRF", ProcessSequenceForward(&machine, AsCodePoints('a', kTrail),
AsCodePoints('a', 'a')));
EXPECT_EQ(1, machine.FinalizeAndGetBoundaryOffset());
// 'a' + [Trail] + [U] + | + 'a' + 'a'
EXPECT_EQ("RRRSRF",
ProcessSequenceForward(&machine, AsCodePoints('a', kTrail, kRisU),
AsCodePoints('a', 'a')));
EXPECT_EQ(1, machine.FinalizeAndGetBoundaryOffset());
// 'a' + [Trail] + [U] + [S] + | + 'a' + 'a'
EXPECT_EQ("RRRRRSRF", ProcessSequenceForward(
&machine, AsCodePoints('a', kTrail, kRisU, kRisS),
AsCodePoints('a', 'a')));
EXPECT_EQ(1, machine.FinalizeAndGetBoundaryOffset());
// [Trail] + [Trail] + | + 'a' + 'a'
EXPECT_EQ("RSRF",
ProcessSequenceForward(&machine, AsCodePoints(kTrail, kTrail),
AsCodePoints('a', 'a')));
EXPECT_EQ(1, machine.FinalizeAndGetBoundaryOffset());
// [Trail] + [Trail] + [U] + | + 'a' + 'a'
EXPECT_EQ("RRRSRF", ProcessSequenceForward(
&machine, AsCodePoints(kTrail, kTrail, kRisU),
AsCodePoints('a', 'a')));
EXPECT_EQ(1, machine.FinalizeAndGetBoundaryOffset());
// [Trail] + [Trail] + [U] + [S] + | + 'a' + 'a'
EXPECT_EQ("RRRRRSRF",
ProcessSequenceForward(&machine,
AsCodePoints(kTrail, kTrail, kRisU, kRisS),
AsCodePoints('a', 'a')));
EXPECT_EQ(1, machine.FinalizeAndGetBoundaryOffset());
// SOT + [Trail] + | + 'a' + 'a'
EXPECT_EQ("RSRF", ProcessSequenceForward(&machine, AsCodePoints(kTrail),
AsCodePoints('a', 'a')));
EXPECT_EQ(1, machine.FinalizeAndGetBoundaryOffset());
// SOT + [Trail] + [U] + | + 'a' + 'a'
EXPECT_EQ("RRRSRF",
ProcessSequenceForward(&machine, AsCodePoints(kTrail, kRisU),
AsCodePoints('a', 'a')));
EXPECT_EQ(1, machine.FinalizeAndGetBoundaryOffset());
// SOT + [Trail] + [U] + [S] + | + 'a' + 'a'
EXPECT_EQ("RRRRRSRF",
ProcessSequenceForward(&machine, AsCodePoints(kTrail, kRisU, kRisS),
AsCodePoints('a', 'a')));
EXPECT_EQ(1, machine.FinalizeAndGetBoundaryOffset());
}
TEST_F(ForwardGraphemeBoundaryStatemachineTest, BrokenSurrogatePair) {
ForwardGraphemeBoundaryStateMachine machine;
// SOT + | + [Trail]
EXPECT_EQ("SF", ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kTrail)));
EXPECT_EQ(1, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + [Lead] + 'a'
EXPECT_EQ("SRF", ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kLead, 'a')));
EXPECT_EQ(1, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + [Lead] + [Lead]
EXPECT_EQ("SRF", ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kLead, kLead)));
EXPECT_EQ(1, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + [Lead] + EOT
EXPECT_EQ("SR", ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kLead)));
EXPECT_EQ(1, machine.FinalizeAndGetBoundaryOffset());
}
TEST_F(ForwardGraphemeBoundaryStatemachineTest, BreakImmediately_BMP) {
ForwardGraphemeBoundaryStateMachine machine;
// SOT + | + U+0000 + U+0000
EXPECT_EQ("SRF", ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(0, 0)));
EXPECT_EQ(1, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + 'a' + 'a'
EXPECT_EQ("SRF", ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints('a', 'a')));
EXPECT_EQ(1, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + 'a' + U+1F441
EXPECT_EQ("SRRF", ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints('a', kEye)));
EXPECT_EQ(1, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + 'a' + EOT
EXPECT_EQ("SR", ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints('a')));
EXPECT_EQ(1, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + 'a' + [Trail]
EXPECT_EQ("SRF", ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints('a', kTrail)));
EXPECT_EQ(1, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + 'a' + [Lead] + 'a'
EXPECT_EQ("SRRF", ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints('a', kLead, 'a')));
EXPECT_EQ(1, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + 'a' + [Lead] + [Lead]
EXPECT_EQ("SRRF", ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints('a', kLead, kLead)));
EXPECT_EQ(1, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + 'a' + [Lead] + EOT
EXPECT_EQ("SRR", ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints('a', kLead)));
EXPECT_EQ(1, machine.FinalizeAndGetBoundaryOffset());
}
TEST_F(ForwardGraphemeBoundaryStatemachineTest,
BreakImmediately_Supplementary) {
ForwardGraphemeBoundaryStateMachine machine;
// SOT + | + U+1F441 + 'a'
EXPECT_EQ("SRRF", ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kEye, 'a')));
EXPECT_EQ(2, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + U+1F441 + U+1F441
EXPECT_EQ("SRRRF", ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kEye, kEye)));
EXPECT_EQ(2, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + U+1F441 + EOT
EXPECT_EQ("SRR", ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kEye)));
EXPECT_EQ(2, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + U+1F441 + [Trail]
EXPECT_EQ("SRRF", ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kEye, kTrail)));
EXPECT_EQ(2, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + U+1F441 + [Lead] + 'a'
EXPECT_EQ("SRRRF", ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kEye, kLead, 'a')));
EXPECT_EQ(2, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + U+1F441 + [Lead] + [Lead]
EXPECT_EQ("SRRRF", ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kEye, kLead, kLead)));
EXPECT_EQ(2, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + U+1F441 + [Lead] + EOT
EXPECT_EQ("SRRR", ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kEye, kLead)));
EXPECT_EQ(2, machine.FinalizeAndGetBoundaryOffset());
}
TEST_F(ForwardGraphemeBoundaryStatemachineTest,
NotBreakImmediatelyAfter_BMP_BMP) {
ForwardGraphemeBoundaryStateMachine machine;
// SOT + | + U+231A + U+FE0F + 'a'
EXPECT_EQ("SRRF", ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kWatch, kVS16, 'a')));
EXPECT_EQ(2, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + U+231A + U+FE0F + U+1F441
EXPECT_EQ("SRRRF", ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kWatch, kVS16, kEye)));
EXPECT_EQ(2, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + U+231A + U+FE0F + EOT
EXPECT_EQ("SRR", ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kWatch, kVS16)));
EXPECT_EQ(2, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + U+231A + U+FE0F + [Trail]
EXPECT_EQ("SRRF",
ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kWatch, kVS16, kTrail)));
EXPECT_EQ(2, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + U+231A + U+FE0F + [Lead] + 'a'
EXPECT_EQ("SRRRF",
ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kWatch, kVS16, kLead, 'a')));
EXPECT_EQ(2, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + U+231A + U+FE0F + [Lead] + [Lead]
EXPECT_EQ("SRRRF",
ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kWatch, kVS16, kLead, kLead)));
EXPECT_EQ(2, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + U+231A + U+FE0F + [Lead] + EOT
EXPECT_EQ("SRRR", ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kWatch, kVS16, kLead)));
EXPECT_EQ(2, machine.FinalizeAndGetBoundaryOffset());
}
TEST_F(ForwardGraphemeBoundaryStatemachineTest,
NotBreakImmediatelyAfter_Supplementary_BMP) {
ForwardGraphemeBoundaryStateMachine machine;
// SOT + | + U+1F441 + U+FE0F + 'a'
EXPECT_EQ("SRRRF", ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kEye, kVS16, 'a')));
EXPECT_EQ(3, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + U+1F441 + U+FE0F + U+1F441
EXPECT_EQ("SRRRRF", ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kEye, kVS16, kEye)));
EXPECT_EQ(3, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + U+1F441 + U+FE0F + EOT
EXPECT_EQ("SRRR", ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kEye, kVS16)));
EXPECT_EQ(3, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + U+1F441 + U+FE0F + [Trail]
EXPECT_EQ("SRRRF", ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kEye, kVS16, kTrail)));
EXPECT_EQ(3, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + U+1F441 + U+FE0F + [Lead] + 'a'
EXPECT_EQ("SRRRRF",
ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kEye, kVS16, kLead, 'a')));
EXPECT_EQ(3, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + U+1F441 + U+FE0F + [Lead] + [Lead]
EXPECT_EQ("SRRRRF",
ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kEye, kVS16, kLead, kLead)));
EXPECT_EQ(3, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + U+1F441 + U+FE0F + [Lead] + EOT
EXPECT_EQ("SRRRR", ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kEye, kVS16, kLead)));
EXPECT_EQ(3, machine.FinalizeAndGetBoundaryOffset());
}
TEST_F(ForwardGraphemeBoundaryStatemachineTest,
NotBreakImmediatelyAfter_BMP_Supplementary) {
ForwardGraphemeBoundaryStateMachine machine;
// SOT + | + U+845B + U+E0100 + 'a'
EXPECT_EQ("SRRRF", ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kHanBMP, kVS17, 'a')));
EXPECT_EQ(3, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + U+845B + U+E0100 + U+1F441
EXPECT_EQ("SRRRRF",
ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kHanBMP, kVS17, kEye)));
EXPECT_EQ(3, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + U+845B + U+E0100 + EOT
EXPECT_EQ("SRRR", ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kHanBMP, kVS17)));
EXPECT_EQ(3, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + U+845B + U+E0100 + [Trail]
EXPECT_EQ("SRRRF",
ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kHanBMP, kVS17, kTrail)));
EXPECT_EQ(3, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + U+845B + U+E0100 + [Lead] + 'a'
EXPECT_EQ("SRRRRF",
ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kHanBMP, kVS17, kLead, 'a')));
EXPECT_EQ(3, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + U+845B + U+E0100 + [Lead] + [Lead]
EXPECT_EQ("SRRRRF",
ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kHanBMP, kVS17, kLead, kLead)));
EXPECT_EQ(3, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + U+845B + U+E0100 + [Lead] + EOT
EXPECT_EQ("SRRRR",
ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kHanBMP, kVS17, kLead)));
EXPECT_EQ(3, machine.FinalizeAndGetBoundaryOffset());
}
TEST_F(ForwardGraphemeBoundaryStatemachineTest,
NotBreakImmediatelyAfter_Supplementary_Supplementary) {
ForwardGraphemeBoundaryStateMachine machine;
// SOT + | + U+20000 + U+E0100 + 'a'
EXPECT_EQ("SRRRRF",
ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kHanSIP, kVS17, 'a')));
EXPECT_EQ(4, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + U+20000 + U+E0100 + U+1F441
EXPECT_EQ("SRRRRRF",
ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kHanSIP, kVS17, kEye)));
EXPECT_EQ(4, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + U+20000 + U+E0100 + EOT
EXPECT_EQ("SRRRR", ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kHanSIP, kVS17)));
EXPECT_EQ(4, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + U+20000 + U+E0100 + [Trail]
EXPECT_EQ("SRRRRF",
ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kHanSIP, kVS17, kTrail)));
EXPECT_EQ(4, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + U+20000 + U+E0100 + [Lead] + 'a'
EXPECT_EQ("SRRRRRF",
ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kHanSIP, kVS17, kLead, 'a')));
EXPECT_EQ(4, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + U+20000 + U+E0100 + [Lead] + [Lead]
EXPECT_EQ("SRRRRRF",
ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kHanSIP, kVS17, kLead, kLead)));
EXPECT_EQ(4, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + U+20000 + U+E0100 + [Lead] + EOT
EXPECT_EQ("SRRRRR",
ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kHanSIP, kVS17, kLead)));
EXPECT_EQ(4, machine.FinalizeAndGetBoundaryOffset());
}
TEST_F(ForwardGraphemeBoundaryStatemachineTest, MuchLongerCase) {
ForwardGraphemeBoundaryStateMachine machine;
const UChar32 kMan = WTF::unicode::kManCharacter;
const UChar32 kZwj = WTF::unicode::kZeroWidthJoinerCharacter;
const UChar32 kHeart = WTF::unicode::kHeavyBlackHeartCharacter;
const UChar32 kKiss = WTF::unicode::kKissMarkCharacter;
// U+1F468 U+200D U+2764 U+FE0F U+200D U+1F48B U+200D U+1F468 is a valid ZWJ
// emoji sequence.
// SOT + | + ZWJ Emoji Sequence + 'a'
EXPECT_EQ("SRRRRRRRRRRRF",
ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kMan, kZwj, kHeart, kVS16, kZwj,
kKiss, kZwj, kMan, 'a')));
EXPECT_EQ(11, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + ZWJ Emoji Sequence + U+1F441
EXPECT_EQ("SRRRRRRRRRRRRF",
ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kMan, kZwj, kHeart, kVS16, kZwj,
kKiss, kZwj, kMan, kEye)));
EXPECT_EQ(11, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + ZWJ Emoji Sequence + EOT
EXPECT_EQ("SRRRRRRRRRRR",
ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kMan, kZwj, kHeart, kVS16, kZwj,
kKiss, kZwj, kMan)));
EXPECT_EQ(11, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + ZWJ Emoji Sequence + [Trail]
EXPECT_EQ("SRRRRRRRRRRRF",
ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kMan, kZwj, kHeart, kVS16, kZwj,
kKiss, kZwj, kMan, kTrail)));
EXPECT_EQ(11, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + ZWJ Emoji Sequence + [Lead] + 'a'
EXPECT_EQ("SRRRRRRRRRRRRF", ProcessSequenceForward(
&machine, AsCodePoints(),
AsCodePoints(kMan, kZwj, kHeart, kVS16, kZwj,
kKiss, kZwj, kMan, kLead, 'a')));
EXPECT_EQ(11, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + ZWJ Emoji Sequence + [Lead] + [Lead]
EXPECT_EQ(
"SRRRRRRRRRRRRF",
ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kMan, kZwj, kHeart, kVS16, kZwj,
kKiss, kZwj, kMan, kLead, kLead)));
EXPECT_EQ(11, machine.FinalizeAndGetBoundaryOffset());
// SOT + | + ZWJ Emoji Sequence + [Lead] + EOT
EXPECT_EQ("SRRRRRRRRRRRR",
ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kMan, kZwj, kHeart, kVS16, kZwj,
kKiss, kZwj, kMan, kLead)));
EXPECT_EQ(11, machine.FinalizeAndGetBoundaryOffset());
// Preceding text should not affect the result except for flags.
// 'a' + | + ZWJ Emoji Sequence + [Lead] + EOT
EXPECT_EQ("SRRRRRRRRRRRF",
ProcessSequenceForward(&machine, AsCodePoints('a'),
AsCodePoints(kMan, kZwj, kHeart, kVS16, kZwj,
kKiss, kZwj, kMan, 'a')));
EXPECT_EQ(11, machine.FinalizeAndGetBoundaryOffset());
// U+1F441 + | + ZWJ Emoji Sequence + [Lead] + EOT
EXPECT_EQ("RSRRRRRRRRRRRF",
ProcessSequenceForward(&machine, AsCodePoints(kEye),
AsCodePoints(kMan, kZwj, kHeart, kVS16, kZwj,
kKiss, kZwj, kMan, 'a')));
EXPECT_EQ(11, machine.FinalizeAndGetBoundaryOffset());
// [Lead] + | + ZWJ Emoji Sequence + [Lead] + EOT
EXPECT_EQ("SRRRRRRRRRRRF",
ProcessSequenceForward(&machine, AsCodePoints(kLead),
AsCodePoints(kMan, kZwj, kHeart, kVS16, kZwj,
kKiss, kZwj, kMan, 'a')));
EXPECT_EQ(11, machine.FinalizeAndGetBoundaryOffset());
// 'a' + [Trail] + | + ZWJ Emoji Sequence + [Lead] + EOT
EXPECT_EQ("RSRRRRRRRRRRRF",
ProcessSequenceForward(&machine, AsCodePoints('a', kTrail),
AsCodePoints(kMan, kZwj, kHeart, kVS16, kZwj,
kKiss, kZwj, kMan, 'a')));
EXPECT_EQ(11, machine.FinalizeAndGetBoundaryOffset());
// [Trail] + [Trail] + | + ZWJ Emoji Sequence + [Lead] + EOT
EXPECT_EQ("RSRRRRRRRRRRRF",
ProcessSequenceForward(&machine, AsCodePoints(kTrail, kTrail),
AsCodePoints(kMan, kZwj, kHeart, kVS16, kZwj,
kKiss, kZwj, kMan, 'a')));
EXPECT_EQ(11, machine.FinalizeAndGetBoundaryOffset());
// SOT + [Trail] + | + ZWJ Emoji Sequence + [Lead] + EOT
EXPECT_EQ("RSRRRRRRRRRRRF",
ProcessSequenceForward(&machine, AsCodePoints(kTrail),
AsCodePoints(kMan, kZwj, kHeart, kVS16, kZwj,
kKiss, kZwj, kMan, 'a')));
EXPECT_EQ(11, machine.FinalizeAndGetBoundaryOffset());
// 'a' + [U] + | + ZWJ Emoji Sequence + [Lead] + EOT
EXPECT_EQ("RRSRRRRRRRRRRRF",
ProcessSequenceForward(&machine, AsCodePoints('a', kRisU),
AsCodePoints(kMan, kZwj, kHeart, kVS16, kZwj,
kKiss, kZwj, kMan, 'a')));
EXPECT_EQ(11, machine.FinalizeAndGetBoundaryOffset());
// 'a' + [U] + [S] + | + ZWJ Emoji Sequence + [Lead] + EOT
EXPECT_EQ("RRRRSRRRRRRRRRRRF",
ProcessSequenceForward(&machine, AsCodePoints('a', kRisU, kRisS),
AsCodePoints(kMan, kZwj, kHeart, kVS16, kZwj,
kKiss, kZwj, kMan, 'a')));
EXPECT_EQ(11, machine.FinalizeAndGetBoundaryOffset());
}
TEST_F(ForwardGraphemeBoundaryStatemachineTest, singleFlags) {
ForwardGraphemeBoundaryStateMachine machine;
// SOT + | + [U] + [S]
EXPECT_EQ("SRRRF", ProcessSequenceForward(&machine, AsCodePoints(),
AsCodePoints(kRisU, kRisS)));
EXPECT_EQ(4, machine.FinalizeAndGetBoundaryOffset());
// 'a' + | + [U] + [S]
EXPECT_EQ("SRRRF", ProcessSequenceForward(&machine, AsCodePoints('a'),
AsCodePoints(kRisU, kRisS)));
EXPECT_EQ(4, machine.FinalizeAndGetBoundaryOffset());
// U+1F441 + | + [U] + [S]
EXPECT_EQ("RSRRRF", ProcessSequenceForward(&machine, AsCodePoints(kEye),
AsCodePoints(kRisU, kRisS)));
EXPECT_EQ(4, machine.FinalizeAndGetBoundaryOffset());
// [Lead] + | + [U] + [S]
EXPECT_EQ("SRRRF", ProcessSequenceForward(&machine, AsCodePoints(kLead),
AsCodePoints(kRisU, kRisS)));
EXPECT_EQ(4, machine.FinalizeAndGetBoundaryOffset());
// 'a' + [Trail] + | + [U] + [S]
EXPECT_EQ("RSRRRF",
ProcessSequenceForward(&machine, AsCodePoints('a', kTrail),
AsCodePoints(kRisU, kRisS)));
EXPECT_EQ(4, machine.FinalizeAndGetBoundaryOffset());
// [Trail] + [Trail] + | + [U] + [S]
EXPECT_EQ("RSRRRF",
ProcessSequenceForward(&machine, AsCodePoints(kTrail, kTrail),
AsCodePoints(kRisU, kRisS)));
EXPECT_EQ(4, machine.FinalizeAndGetBoundaryOffset());
// SOT + [Trail] + | + [U] + [S]
EXPECT_EQ("RSRRRF", ProcessSequenceForward(&machine, AsCodePoints(kTrail),
AsCodePoints(kRisU, kRisS)));
EXPECT_EQ(4, machine.FinalizeAndGetBoundaryOffset());
}
TEST_F(ForwardGraphemeBoundaryStatemachineTest, twoFlags) {
ForwardGraphemeBoundaryStateMachine machine;
// SOT + [U] + [S] + | + [U] + [S]
EXPECT_EQ("RRRRSRRRF",
ProcessSequenceForward(&machine, AsCodePoints(kRisU, kRisS),
AsCodePoints(kRisU, kRisS)));
EXPECT_EQ(4, machine.FinalizeAndGetBoundaryOffset());
// 'a' + [U] + [S] + | + [U] + [S]
EXPECT_EQ("RRRRSRRRF",
ProcessSequenceForward(&machine, AsCodePoints('a', kRisU, kRisS),
AsCodePoints(kRisU, kRisS)));
EXPECT_EQ(4, machine.FinalizeAndGetBoundaryOffset());
// U+1F441 + [U] + [S] + | + [U] + [S]
EXPECT_EQ("RRRRRSRRRF",
ProcessSequenceForward(&machine, AsCodePoints(kEye, kRisU, kRisS),
AsCodePoints(kRisU, kRisS)));
EXPECT_EQ(4, machine.FinalizeAndGetBoundaryOffset());
// [Lead] + [U] + [S] + | + [U] + [S]
EXPECT_EQ("RRRRSRRRF",
ProcessSequenceForward(&machine, AsCodePoints(kLead, kRisU, kRisS),
AsCodePoints(kRisU, kRisS)));
EXPECT_EQ(4, machine.FinalizeAndGetBoundaryOffset());
// 'a' + [Trail] + [U] + [S] + | + [U] + [S]
EXPECT_EQ("RRRRRSRRRF", ProcessSequenceForward(
&machine, AsCodePoints('a', kTrail, kRisU, kRisS),
AsCodePoints(kRisU, kRisS)));
EXPECT_EQ(4, machine.FinalizeAndGetBoundaryOffset());
// [Trail] + [Trail] + [U] + [S] + | + [U] + [S]
EXPECT_EQ("RRRRRSRRRF",
ProcessSequenceForward(&machine,
AsCodePoints(kTrail, kTrail, kRisU, kRisS),
AsCodePoints(kRisU, kRisS)));
EXPECT_EQ(4, machine.FinalizeAndGetBoundaryOffset());
// SOT + [Trail] + [U] + [S] + | + [U] + [S]
EXPECT_EQ("RRRRRSRRRF",
ProcessSequenceForward(&machine, AsCodePoints(kTrail, kRisU, kRisS),
AsCodePoints(kRisU, kRisS)));
EXPECT_EQ(4, machine.FinalizeAndGetBoundaryOffset());
}
TEST_F(ForwardGraphemeBoundaryStatemachineTest, oddNumberedFlags) {
ForwardGraphemeBoundaryStateMachine machine;
// SOT + [U] + | + [S] + [S]
EXPECT_EQ("RRSRRRF", ProcessSequenceForward(&machine, AsCodePoints(kRisU),
AsCodePoints(kRisS, kRisU)));
EXPECT_EQ(2, machine.FinalizeAndGetBoundaryOffset());
// 'a' + [U] + | + [S] + [S]
EXPECT_EQ("RRSRRRF",
ProcessSequenceForward(&machine, AsCodePoints('a', kRisU),
AsCodePoints(kRisS, kRisU)));
EXPECT_EQ(2, machine.FinalizeAndGetBoundaryOffset());
// U+1F441 + [U] + | + [S] + [S]
EXPECT_EQ("RRRSRRRF",
ProcessSequenceForward(&machine, AsCodePoints(kEye, kRisU),
AsCodePoints(kRisS, kRisU)));
EXPECT_EQ(2, machine.FinalizeAndGetBoundaryOffset());
// [Lead] + [U] + | + [S] + [S]
EXPECT_EQ("RRSRRRF",
ProcessSequenceForward(&machine, AsCodePoints(kLead, kRisU),
AsCodePoints(kRisS, kRisU)));
EXPECT_EQ(2, machine.FinalizeAndGetBoundaryOffset());
// 'a' + [Trail] + [U] + | + [S] + [S]
EXPECT_EQ("RRRSRRRF",
ProcessSequenceForward(&machine, AsCodePoints('a', kTrail, kRisU),
AsCodePoints(kRisS, kRisU)));
EXPECT_EQ(2, machine.FinalizeAndGetBoundaryOffset());
// [Trail] + [Trail] + [U] + | + [S] + [S]
EXPECT_EQ("RRRSRRRF", ProcessSequenceForward(
&machine, AsCodePoints(kTrail, kTrail, kRisU),
AsCodePoints(kRisS, kRisU)));
EXPECT_EQ(2, machine.FinalizeAndGetBoundaryOffset());
// SOT + [Trail] + [U] + | + [S] + [S]
EXPECT_EQ("RRRSRRRF",
ProcessSequenceForward(&machine, AsCodePoints(kTrail, kRisU),
AsCodePoints(kRisS, kRisU)));
EXPECT_EQ(2, machine.FinalizeAndGetBoundaryOffset());
}
} // namespace forward_grapheme_boundary_state_machine_test
} // namespace blink