1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "config.h"
6#include "core/editing/CompositionUnderlineRangeFilter.h"
7
8#include "core/editing/CompositionUnderline.h"
9#include "platform/graphics/Color.h"
10#include "wtf/Vector.h"
11#include "wtf/text/IntegerToStringConversion.h"
12#include "wtf/text/WTFString.h"
13#include <gtest/gtest.h>
14
15using namespace blink;
16
17namespace {
18
19// Parses test case string and populate |underlines|.
20void initUnderlines(const String& testCase, Vector<CompositionUnderline>* underlines)
21{
22    ASSERT(underlines && underlines->size() == 0U);
23    Vector<String> rangeList;
24    testCase.split('|', rangeList);
25    // Intervals are named 'A', 'B', ..., 'Z', so ensure there aren't too many.
26    ASSERT_LE(rangeList.size(), static_cast<size_t>('Z' - 'A'));
27    for (unsigned i = 0; i < rangeList.size(); ++i) {
28        String range = rangeList[i];
29        Vector<String> toks;
30        rangeList[i].split(',', toks);
31        ASSERT_EQ(2U, toks.size());
32        int startOffset = toks[0].toInt();
33        int endOffset = toks[1].toInt();
34        ASSERT_LE(startOffset, endOffset);
35        // For testing: Store i in red component of |color|, so the intervals
36        // can be distinguished.
37        underlines->append(CompositionUnderline(startOffset, endOffset, Color(i, 0, 0), false, 0));
38    }
39}
40
41// Runs the filter and encodes the result into a string, with 'A' as first
42// elemnt, 'B' as second, etc.
43String filterUnderlines(const Vector<CompositionUnderline>& underlines, int indexLo, int indexHi)
44{
45    CompositionUnderlineRangeFilter filter(underlines, indexLo, indexHi);
46    String ret = "";
47    for (CompositionUnderlineRangeFilter::ConstIterator it = filter.begin(); it != filter.end(); ++it) {
48        int code = (*it).color.red();
49        ret.append(static_cast<char>('A' + code));
50    }
51    return ret;
52}
53
54TEST(CompositionUnderlineRangeFilterTest, Empty)
55{
56    Vector<CompositionUnderline> underlines;
57    EXPECT_EQ("", filterUnderlines(underlines, 0, 10));
58    EXPECT_EQ("", filterUnderlines(underlines, 5, 5));
59}
60
61TEST(CompositionUnderlineRangeFilterTest, Single)
62{
63    String testCase = "10,20"; // Semi-closed interval: {10, 11, ..., 19}.
64    Vector<CompositionUnderline> underlines;
65    initUnderlines(testCase, &underlines);
66    // The query intervals are all closed, e.g., [0, 9] = {0, ..., 9}.
67    EXPECT_EQ("", filterUnderlines(underlines, 0, 9));
68    EXPECT_EQ("A", filterUnderlines(underlines, 5, 10));
69    EXPECT_EQ("A", filterUnderlines(underlines, 10, 20));
70    EXPECT_EQ("A", filterUnderlines(underlines, 15, 25));
71    EXPECT_EQ("A", filterUnderlines(underlines, 19, 30));
72    EXPECT_EQ("", filterUnderlines(underlines, 20, 25));
73    EXPECT_EQ("A", filterUnderlines(underlines, 5, 25));
74}
75
76TEST(CompositionUnderlineRangeFilterTest, Multi)
77{
78    String testCase = "0,2|0,5|1,3|1,10|3,5|5,8|7,8|8,10";
79    Vector<CompositionUnderline> underlines;
80    initUnderlines(testCase, &underlines);
81    EXPECT_EQ("", filterUnderlines(underlines, 11, 11));
82    EXPECT_EQ("ABCDEFGH", filterUnderlines(underlines, 0, 9));
83    EXPECT_EQ("BDEF", filterUnderlines(underlines, 4, 5));
84    EXPECT_EQ("AB", filterUnderlines(underlines, 0, 0));
85    EXPECT_EQ("BDE", filterUnderlines(underlines, 3, 3));
86    EXPECT_EQ("DF", filterUnderlines(underlines, 5, 5));
87    EXPECT_EQ("DFG", filterUnderlines(underlines, 7, 7));
88}
89
90} // namespace
91