| // 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 "base/i18n/bidi_line_iterator.h" |
| |
| #include "base/macros.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace base { |
| namespace i18n { |
| namespace { |
| |
| class BiDiLineIteratorTest : public testing::TestWithParam<TextDirection> { |
| public: |
| BiDiLineIteratorTest() = default; |
| |
| BiDiLineIterator* iterator() { return &iterator_; } |
| |
| private: |
| BiDiLineIterator iterator_; |
| |
| DISALLOW_COPY_AND_ASSIGN(BiDiLineIteratorTest); |
| }; |
| |
| TEST_P(BiDiLineIteratorTest, OnlyLTR) { |
| iterator()->Open(UTF8ToUTF16("abc 馃榿 娴嬭瘯"), GetParam(), |
| BiDiLineIterator::CustomBehavior::NONE); |
| ASSERT_EQ(1, iterator()->CountRuns()); |
| |
| int start, length; |
| EXPECT_EQ(UBIDI_LTR, iterator()->GetVisualRun(0, &start, &length)); |
| EXPECT_EQ(0, start); |
| EXPECT_EQ(9, length); |
| |
| int end; |
| UBiDiLevel level; |
| iterator()->GetLogicalRun(0, &end, &level); |
| EXPECT_EQ(9, end); |
| if (GetParam() == TextDirection::RIGHT_TO_LEFT) |
| EXPECT_EQ(2, level); |
| else |
| EXPECT_EQ(0, level); |
| } |
| |
| TEST_P(BiDiLineIteratorTest, OnlyRTL) { |
| iterator()->Open(UTF8ToUTF16("诪讛 讛砖注讛"), GetParam(), |
| BiDiLineIterator::CustomBehavior::NONE); |
| ASSERT_EQ(1, iterator()->CountRuns()); |
| |
| int start, length; |
| EXPECT_EQ(UBIDI_RTL, iterator()->GetVisualRun(0, &start, &length)); |
| EXPECT_EQ(0, start); |
| EXPECT_EQ(7, length); |
| |
| int end; |
| UBiDiLevel level; |
| iterator()->GetLogicalRun(0, &end, &level); |
| EXPECT_EQ(7, end); |
| EXPECT_EQ(1, level); |
| } |
| |
| TEST_P(BiDiLineIteratorTest, Mixed) { |
| iterator()->Open(UTF8ToUTF16("讗谞讬 诪砖转诪砖 讘- Chrome 讻讚驻讚驻谉 讛讗讬谞讟专谞讟 砖诇讬"), |
| GetParam(), BiDiLineIterator::CustomBehavior::NONE); |
| ASSERT_EQ(3, iterator()->CountRuns()); |
| |
| // We'll get completely different results depending on the top-level paragraph |
| // direction. |
| if (GetParam() == TextDirection::RIGHT_TO_LEFT) { |
| // If para direction is RTL, expect the LTR substring "Chrome" to be nested |
| // within the surrounding RTL text. |
| int start, length; |
| EXPECT_EQ(UBIDI_RTL, iterator()->GetVisualRun(0, &start, &length)); |
| EXPECT_EQ(19, start); |
| EXPECT_EQ(20, length); |
| EXPECT_EQ(UBIDI_LTR, iterator()->GetVisualRun(1, &start, &length)); |
| EXPECT_EQ(13, start); |
| EXPECT_EQ(6, length); |
| EXPECT_EQ(UBIDI_RTL, iterator()->GetVisualRun(2, &start, &length)); |
| EXPECT_EQ(0, start); |
| EXPECT_EQ(13, length); |
| |
| int end; |
| UBiDiLevel level; |
| iterator()->GetLogicalRun(0, &end, &level); |
| EXPECT_EQ(13, end); |
| EXPECT_EQ(1, level); |
| iterator()->GetLogicalRun(13, &end, &level); |
| EXPECT_EQ(19, end); |
| EXPECT_EQ(2, level); |
| iterator()->GetLogicalRun(19, &end, &level); |
| EXPECT_EQ(39, end); |
| EXPECT_EQ(1, level); |
| } else { |
| // If the para direction is LTR, expect the LTR substring "- Chrome " to be |
| // at the top level, with two nested RTL runs on either side. |
| int start, length; |
| EXPECT_EQ(UBIDI_RTL, iterator()->GetVisualRun(0, &start, &length)); |
| EXPECT_EQ(0, start); |
| EXPECT_EQ(11, length); |
| EXPECT_EQ(UBIDI_LTR, iterator()->GetVisualRun(1, &start, &length)); |
| EXPECT_EQ(11, start); |
| EXPECT_EQ(9, length); |
| EXPECT_EQ(UBIDI_RTL, iterator()->GetVisualRun(2, &start, &length)); |
| EXPECT_EQ(20, start); |
| EXPECT_EQ(19, length); |
| |
| int end; |
| UBiDiLevel level; |
| iterator()->GetLogicalRun(0, &end, &level); |
| EXPECT_EQ(11, end); |
| EXPECT_EQ(1, level); |
| iterator()->GetLogicalRun(11, &end, &level); |
| EXPECT_EQ(20, end); |
| EXPECT_EQ(0, level); |
| iterator()->GetLogicalRun(20, &end, &level); |
| EXPECT_EQ(39, end); |
| EXPECT_EQ(1, level); |
| } |
| } |
| |
| TEST_P(BiDiLineIteratorTest, RTLPunctuationNoCustomBehavior) { |
| // This string features Hebrew characters interleaved with ASCII punctuation. |
| iterator()->Open(UTF8ToUTF16("讗!讘\"讙#讚$讛%讜&讝'讞(讟)讬*讱+讻,诇-诐.诪/" |
| "谉:谞;住<注=祝>驻?抓@爪[拽\\专]砖^转_讗`讘{讙|讚}讛~讜"), |
| GetParam(), BiDiLineIterator::CustomBehavior::NONE); |
| |
| // Expect a single RTL run. |
| ASSERT_EQ(1, iterator()->CountRuns()); |
| |
| int start, length; |
| EXPECT_EQ(UBIDI_RTL, iterator()->GetVisualRun(0, &start, &length)); |
| EXPECT_EQ(0, start); |
| EXPECT_EQ(65, length); |
| |
| int end; |
| UBiDiLevel level; |
| iterator()->GetLogicalRun(0, &end, &level); |
| EXPECT_EQ(65, end); |
| EXPECT_EQ(1, level); |
| } |
| |
| TEST_P(BiDiLineIteratorTest, RTLPunctuationAsURL) { |
| // This string features Hebrew characters interleaved with ASCII punctuation. |
| iterator()->Open(UTF8ToUTF16("讗!讘\"讙#讚$讛%讜&讝'讞(讟)讬*讱+讻,诇-诐.诪/" |
| "谉:谞;住<注=祝>驻?抓@爪[拽\\专]砖^转_讗`讘{讙|讚}讛~讜"), |
| GetParam(), BiDiLineIterator::CustomBehavior::AS_URL); |
| |
| const int kStringSize = 65; |
| |
| // Expect a primary RTL run, broken up by each of the 8 punctuation marks that |
| // are considered strong LTR (17 runs total). |
| struct { |
| int start; |
| UBiDiDirection dir; |
| } expected_runs[] = { |
| {0, UBIDI_RTL}, {5, UBIDI_LTR}, // '#' |
| {6, UBIDI_RTL}, {11, UBIDI_LTR}, // '&' |
| {12, UBIDI_RTL}, {27, UBIDI_LTR}, // '.' |
| {28, UBIDI_RTL}, {29, UBIDI_LTR}, // '/' |
| {30, UBIDI_RTL}, {31, UBIDI_LTR}, // ':' |
| {32, UBIDI_RTL}, {37, UBIDI_LTR}, // '=' |
| {38, UBIDI_RTL}, {41, UBIDI_LTR}, // '?' |
| {42, UBIDI_RTL}, {43, UBIDI_LTR}, // '@' |
| {44, UBIDI_RTL}, |
| }; |
| |
| ASSERT_EQ(arraysize(expected_runs), |
| static_cast<size_t>(iterator()->CountRuns())); |
| |
| for (size_t i = 0; i < arraysize(expected_runs); ++i) { |
| const auto& expected_run = expected_runs[i]; |
| int expected_run_end = i >= arraysize(expected_runs) - 1 |
| ? kStringSize |
| : expected_runs[i + 1].start; |
| |
| size_t visual_index = GetParam() == TextDirection::RIGHT_TO_LEFT |
| ? arraysize(expected_runs) - 1 - i |
| : i; |
| int start, length; |
| EXPECT_EQ(expected_run.dir, |
| iterator()->GetVisualRun(visual_index, &start, &length)) |
| << "(i = " << i << ")"; |
| EXPECT_EQ(expected_run.start, start) << "(i = " << i << ")"; |
| EXPECT_EQ(expected_run_end - expected_run.start, length) |
| << "(i = " << i << ")"; |
| |
| int expected_level = |
| expected_run.dir == UBIDI_RTL |
| ? 1 |
| : (GetParam() == TextDirection::RIGHT_TO_LEFT ? 2 : 0); |
| int end; |
| UBiDiLevel level; |
| iterator()->GetLogicalRun(expected_run.start, &end, &level); |
| EXPECT_EQ(expected_run_end, end) << "(i = " << i << ")"; |
| EXPECT_EQ(expected_level, level) << "(i = " << i << ")"; |
| } |
| } |
| |
| INSTANTIATE_TEST_CASE_P(, |
| BiDiLineIteratorTest, |
| ::testing::Values(TextDirection::LEFT_TO_RIGHT, |
| TextDirection::RIGHT_TO_LEFT)); |
| |
| } // namespace |
| } // namespace i18n |
| } // namespace base |