blob: 82fca820d368f28efd04f02d23307fb4744e075a [file] [log] [blame]
// Copyright 2017 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 <string>
#include "third_party/blink/renderer/platform/text/text_boundaries.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
class TextBoundariesTest : public testing::Test {};
namespace {
std::pair<String, int> ParsePositionMarker(const std::string input8) {
String input16 = String::FromUTF8(input8.data(), input8.size());
input16.Ensure16Bit();
const size_t position = input16.find('|');
DCHECK(position != kNotFound) << input8 << " should have position marker(|).";
String output = input16.Left(position) + input16.Substring(position + 1);
output.Ensure16Bit();
return {output, position};
}
std::string MakeResultText(const String& text, int start, int end) {
StringBuilder builder;
if (start < 0 && end < 0) {
builder.Append(text);
} else if (start < 0) {
builder.Append(text.Left(end));
builder.Append('^');
builder.Append(text.Substring(end));
} else if (end < 0) {
builder.Append(text.Left(start));
builder.Append('|');
builder.Append(text.Substring(start));
} else {
builder.Append(text.Left(start));
builder.Append('^');
builder.Append(text.Substring(start, end - start));
builder.Append('|');
}
builder.Append(text.Substring(end));
return builder.ToString().Utf8();
}
// Returns word boundray with start(^) and end(|) markes from text with
// position(|) marker.
std::string TryFindWordBackward(const std::string input8) {
std::pair<String, int> string_and_offset = ParsePositionMarker(input8);
const String text16 = string_and_offset.first;
const int position = string_and_offset.second;
std::pair<int, int> start_and_end =
FindWordBackward(text16.Characters16(), text16.length(), position);
return MakeResultText(text16, start_and_end.first, start_and_end.second);
}
// Returns word boundray with start(^) and end(|) markes from text with
// position(|) marker.
std::string TryFindWordForward(const std::string input8) {
std::pair<String, int> string_and_offset = ParsePositionMarker(input8);
const String text16 = string_and_offset.first;
const int position = string_and_offset.second;
std::pair<int, int> start_and_end =
FindWordForward(text16.Characters16(), text16.length(), position);
return MakeResultText(text16, start_and_end.first, start_and_end.second);
}
} // namespace
TEST_F(TextBoundariesTest, BackwardBasic) {
EXPECT_EQ("^|abc def", TryFindWordBackward("|abc def"));
EXPECT_EQ("^abc| def", TryFindWordBackward("a|bc def"));
EXPECT_EQ("^abc| def", TryFindWordBackward("ab|c def"));
EXPECT_EQ("^abc| def", TryFindWordBackward("abc| def"));
EXPECT_EQ("abc^ |def", TryFindWordBackward("abc |def"));
EXPECT_EQ("abc ^def|", TryFindWordBackward("abc d|ef"));
EXPECT_EQ("abc ^def|", TryFindWordBackward("abc de|f"));
EXPECT_EQ("abc ^def|", TryFindWordBackward("abc def|"));
}
TEST_F(TextBoundariesTest, ForwardBasic) {
EXPECT_EQ("^abc| def", TryFindWordForward("|abc def"));
EXPECT_EQ("^abc| def", TryFindWordForward("a|bc def"));
EXPECT_EQ("^abc| def", TryFindWordForward("ab|c def"));
EXPECT_EQ("abc^ |def", TryFindWordForward("abc| def"));
EXPECT_EQ("abc ^def|", TryFindWordForward("abc |def"));
EXPECT_EQ("abc ^def|", TryFindWordForward("abc d|ef"));
EXPECT_EQ("abc ^def|", TryFindWordForward("abc de|f"));
EXPECT_EQ("abc def^|", TryFindWordForward("abc def|"));
}
TEST_F(TextBoundariesTest, ForwardBiDi) {
EXPECT_EQ(u8"^\u0620\u0621\u0622| \u0623\u0624\u0625",
TryFindWordForward(u8"|\u0620\u0621\u0622 \u0623\u0624\u0625"));
EXPECT_EQ(u8"^\u0620\u0621\u0622| \u0623\u0624\u0625",
TryFindWordForward(u8"\u0620|\u0621\u0622 \u0623\u0624\u0625"));
EXPECT_EQ(u8"^\u0620\u0621\u0622| \u0623\u0624\u0625",
TryFindWordForward(u8"\u0620\u0621|\u0622 \u0623\u0624\u0625"));
EXPECT_EQ(u8"\u0620\u0621\u0622^ |\u0623\u0624\u0625",
TryFindWordForward(u8"\u0620\u0621\u0622| \u0623\u0624\u0625"));
EXPECT_EQ(u8"\u0620\u0621\u0622 ^\u0623\u0624\u0625|",
TryFindWordForward(u8"\u0620\u0621\u0622 |\u0623\u0624\u0625"));
EXPECT_EQ(u8"\u0620\u0621\u0622 \u0623\u0624\u0625^|",
TryFindWordForward(u8"\u0620\u0621\u0622 \u0623\u0624\u0625|"));
}
TEST_F(TextBoundariesTest, ForwardBiDiMixed) {
EXPECT_EQ(u8"^abc\u0620\u0621\u0622|",
TryFindWordForward(u8"|abc\u0620\u0621\u0622"));
EXPECT_EQ(u8"^abc\u0620\u0621\u0622|",
TryFindWordForward(u8"ab|c\u0620\u0621\u0622"));
EXPECT_EQ(u8"^abc\u0620\u0621\u0622|",
TryFindWordForward(u8"abc|\u0620\u0621\u0622"))
<< "At L1/L2 boundary";
EXPECT_EQ(u8"^abc\u0620\u0621\u0622|",
TryFindWordForward(u8"abc\u0620|\u0621\u0622"));
EXPECT_EQ(u8"^\u0620\u0621\u0622xyz|",
TryFindWordForward(u8"|\u0620\u0621\u0622xyz"));
EXPECT_EQ(u8"^\u0620\u0621\u0622xyz|",
TryFindWordForward(u8"\u0620|\u0621\u0622xyz"));
EXPECT_EQ(u8"^\u0620\u0621\u0622xyz|",
TryFindWordForward(u8"\u0620\u0621\u0622|xyz"))
<< "At L2/L1 boundary";
EXPECT_EQ(u8"^\u0620\u0621\u0622xyz|",
TryFindWordForward(u8"\u0620\u0621\u0622xy|z"));
}
TEST_F(TextBoundariesTest, ForwardOne) {
EXPECT_EQ("^a|", TryFindWordForward("|a"));
EXPECT_EQ("a^|", TryFindWordForward("a|")) << "No word after |";
}
TEST_F(TextBoundariesTest, ForwardParenthesis) {
EXPECT_EQ("^(|abc)", TryFindWordForward("|(abc)"));
EXPECT_EQ("(^abc|)", TryFindWordForward("(|abc)"));
EXPECT_EQ("(^abc|)", TryFindWordForward("(a|bc)"));
EXPECT_EQ("(^abc|)", TryFindWordForward("(ab|c)"));
EXPECT_EQ("(abc)^|", TryFindWordForward("(abc)|")) << "No word after |";
}
TEST_F(TextBoundariesTest, ForwardPunctuations) {
EXPECT_EQ("^abc|,,", TryFindWordForward("|abc,,"));
EXPECT_EQ("abc^,|,", TryFindWordForward("abc|,,"));
}
// A sequence of whitespaces is treated as a single word.
// See http://unicode.org/reports/tr29/#WB3d .
TEST_F(TextBoundariesTest, ForwardWhitespaces) {
EXPECT_EQ("^ |abc def ", TryFindWordForward("| abc def "));
EXPECT_EQ("^ |abc def ", TryFindWordForward(" | abc def "));
EXPECT_EQ(" ^abc| def ", TryFindWordForward(" |abc def "));
EXPECT_EQ(" ^abc| def ", TryFindWordForward(" a|bc def "));
EXPECT_EQ(" ^abc| def ", TryFindWordForward(" ab|c def "));
EXPECT_EQ(" abc^ |def ", TryFindWordForward(" abc| def "));
EXPECT_EQ(" abc^ |def ", TryFindWordForward(" abc | def "));
EXPECT_EQ(" abc ^def| ", TryFindWordForward(" abc |def "));
EXPECT_EQ(" abc ^def| ", TryFindWordForward(" abc d|ef "));
EXPECT_EQ(" abc ^def| ", TryFindWordForward(" abc de|f "));
EXPECT_EQ(" abc def^ |", TryFindWordForward(" abc def| "));
EXPECT_EQ(" abc def^ |", TryFindWordForward(" abc def | "));
EXPECT_EQ(" abc def ^|", TryFindWordForward(" abc def |"))
<< "No word after |";
}
TEST_F(TextBoundariesTest, ForwardZero) {
EXPECT_EQ("^|", TryFindWordForward("|"));
}
} // namespace blink