1 // Copyright (c) 2013 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 "components/drive/chromeos/search_metadata.h"
6
7 #include <stddef.h>
8 #include <stdint.h>
9
10 #include <memory>
11 #include <vector>
12
13 #include "base/i18n/string_search.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16
17 namespace drive {
18 namespace internal {
19
20 namespace {
21
22 // A simple wrapper for testing FindAndHighlightWrapper(). It just converts the
23 // query text parameter to FixedPatternStringSearchIgnoringCaseAndAccents.
FindAndHighlightWrapper(const std::string & text,const std::string & query_text,std::string * highlighted_text)24 bool FindAndHighlightWrapper(
25 const std::string& text,
26 const std::string& query_text,
27 std::string* highlighted_text) {
28 std::vector<std::unique_ptr<
29 base::i18n::FixedPatternStringSearchIgnoringCaseAndAccents>>
30 queries;
31 queries.push_back(std::make_unique<
32 base::i18n::FixedPatternStringSearchIgnoringCaseAndAccents>(
33 base::UTF8ToUTF16(query_text)));
34 return FindAndHighlight(text, queries, highlighted_text);
35 }
36
37 } // namespace
38
TEST(SearchMetadataSimpleTest,FindAndHighlight_ZeroMatches)39 TEST(SearchMetadataSimpleTest, FindAndHighlight_ZeroMatches) {
40 std::string highlighted_text;
41 EXPECT_FALSE(FindAndHighlightWrapper("text", "query", &highlighted_text));
42 }
43
TEST(SearchMetadataSimpleTest,FindAndHighlight_EmptyText)44 TEST(SearchMetadataSimpleTest, FindAndHighlight_EmptyText) {
45 std::string highlighted_text;
46 EXPECT_FALSE(FindAndHighlightWrapper("", "query", &highlighted_text));
47 }
48
TEST(SearchMetadataSimpleTest,FindAndHighlight_EmptyQuery)49 TEST(SearchMetadataSimpleTest, FindAndHighlight_EmptyQuery) {
50 std::vector<std::unique_ptr<
51 base::i18n::FixedPatternStringSearchIgnoringCaseAndAccents>>
52 queries;
53
54 std::string highlighted_text;
55 EXPECT_TRUE(FindAndHighlight("hello", queries, &highlighted_text));
56 EXPECT_EQ("hello", highlighted_text);
57 }
58
TEST(SearchMetadataSimpleTest,FindAndHighlight_FullMatch)59 TEST(SearchMetadataSimpleTest, FindAndHighlight_FullMatch) {
60 std::string highlighted_text;
61 EXPECT_TRUE(FindAndHighlightWrapper("hello", "hello", &highlighted_text));
62 EXPECT_EQ("<b>hello</b>", highlighted_text);
63 }
64
TEST(SearchMetadataSimpleTest,FindAndHighlight_StartWith)65 TEST(SearchMetadataSimpleTest, FindAndHighlight_StartWith) {
66 std::string highlighted_text;
67 EXPECT_TRUE(FindAndHighlightWrapper("hello, world", "hello",
68 &highlighted_text));
69 EXPECT_EQ("<b>hello</b>, world", highlighted_text);
70 }
71
TEST(SearchMetadataSimpleTest,FindAndHighlight_EndWith)72 TEST(SearchMetadataSimpleTest, FindAndHighlight_EndWith) {
73 std::string highlighted_text;
74 EXPECT_TRUE(FindAndHighlightWrapper("hello, world", "world",
75 &highlighted_text));
76 EXPECT_EQ("hello, <b>world</b>", highlighted_text);
77 }
78
TEST(SearchMetadataSimpleTest,FindAndHighlight_InTheMiddle)79 TEST(SearchMetadataSimpleTest, FindAndHighlight_InTheMiddle) {
80 std::string highlighted_text;
81 EXPECT_TRUE(FindAndHighlightWrapper("yo hello, world", "hello",
82 &highlighted_text));
83 EXPECT_EQ("yo <b>hello</b>, world", highlighted_text);
84 }
85
TEST(SearchMetadataSimpleTest,FindAndHighlight_MultipeMatches)86 TEST(SearchMetadataSimpleTest, FindAndHighlight_MultipeMatches) {
87 std::string highlighted_text;
88 EXPECT_TRUE(FindAndHighlightWrapper("yoyoyoyoy", "yoy", &highlighted_text));
89 // Only the first match is highlighted.
90 EXPECT_EQ("<b>yoy</b>oyoyoy", highlighted_text);
91 }
92
TEST(SearchMetadataSimpleTest,FindAndHighlight_IgnoreCase)93 TEST(SearchMetadataSimpleTest, FindAndHighlight_IgnoreCase) {
94 std::string highlighted_text;
95 EXPECT_TRUE(FindAndHighlightWrapper("HeLLo", "hello", &highlighted_text));
96 EXPECT_EQ("<b>HeLLo</b>", highlighted_text);
97 }
98
TEST(SearchMetadataSimpleTest,FindAndHighlight_IgnoreCaseNonASCII)99 TEST(SearchMetadataSimpleTest, FindAndHighlight_IgnoreCaseNonASCII) {
100 std::string highlighted_text;
101
102 // Case and accent ignorance in Greek. Find "socra" in "Socra'tes".
103 EXPECT_TRUE(FindAndHighlightWrapper(
104 "\xCE\xA3\xCF\x89\xCE\xBA\xCF\x81\xCE\xAC\xCF\x84\xCE\xB7\xCF\x82",
105 "\xCF\x83\xCF\x89\xCE\xBA\xCF\x81\xCE\xB1", &highlighted_text));
106 EXPECT_EQ(
107 "<b>\xCE\xA3\xCF\x89\xCE\xBA\xCF\x81\xCE\xAC</b>\xCF\x84\xCE\xB7\xCF\x82",
108 highlighted_text);
109
110 // In Japanese characters.
111 // Find Hiragana "pi" + "(small)ya" in Katakana "hi" + semi-voiced-mark + "ya"
112 EXPECT_TRUE(FindAndHighlightWrapper(
113 "\xE3\x81\xB2\xE3\x82\x9A\xE3\x82\x83\xE3\x83\xBC",
114 "\xE3\x83\x94\xE3\x83\xA4",
115 &highlighted_text));
116 EXPECT_EQ(
117 "<b>\xE3\x81\xB2\xE3\x82\x9A\xE3\x82\x83</b>\xE3\x83\xBC",
118 highlighted_text);
119 }
120
TEST(SearchMetadataSimpleTest,MultiTextBySingleQuery)121 TEST(SearchMetadataSimpleTest, MultiTextBySingleQuery) {
122 std::vector<std::unique_ptr<
123 base::i18n::FixedPatternStringSearchIgnoringCaseAndAccents>>
124 queries;
125 queries.push_back(std::make_unique<
126 base::i18n::FixedPatternStringSearchIgnoringCaseAndAccents>(
127 base::UTF8ToUTF16("hello")));
128
129 std::string highlighted_text;
130 EXPECT_TRUE(FindAndHighlight("hello", queries, &highlighted_text));
131 EXPECT_EQ("<b>hello</b>", highlighted_text);
132 EXPECT_FALSE(FindAndHighlight("goodbye", queries, &highlighted_text));
133 EXPECT_TRUE(FindAndHighlight("1hello2", queries, &highlighted_text));
134 EXPECT_EQ("1<b>hello</b>2", highlighted_text);
135 }
136
TEST(SearchMetadataSimpleTest,FindAndHighlight_MetaChars)137 TEST(SearchMetadataSimpleTest, FindAndHighlight_MetaChars) {
138 std::string highlighted_text;
139 EXPECT_TRUE(FindAndHighlightWrapper("<hello>", "hello", &highlighted_text));
140 EXPECT_EQ("<<b>hello</b>>", highlighted_text);
141 }
142
TEST(SearchMetadataSimpleTest,FindAndHighlight_MoreMetaChars)143 TEST(SearchMetadataSimpleTest, FindAndHighlight_MoreMetaChars) {
144 std::string highlighted_text;
145 EXPECT_TRUE(FindAndHighlightWrapper("a&b&c&d", "b&c", &highlighted_text));
146 EXPECT_EQ("a&<b>b&c</b>&d", highlighted_text);
147 }
148
TEST(SearchMetadataSimpleTest,FindAndHighlight_SurrogatePair)149 TEST(SearchMetadataSimpleTest, FindAndHighlight_SurrogatePair) {
150 std::string highlighted_text;
151 // \xF0\x9F\x98\x81 (U+1F601) is a surrogate pair for smile icon of emoji.
152 EXPECT_TRUE(FindAndHighlightWrapper("hi\xF0\x9F\x98\x81hello",
153 "i\xF0\x9F\x98\x81", &highlighted_text));
154 EXPECT_EQ("h<b>i\xF0\x9F\x98\x81</b>hello", highlighted_text);
155 }
156
TEST(SearchMetadataSimpleTest,FindAndHighlight_MultipleQueries)157 TEST(SearchMetadataSimpleTest, FindAndHighlight_MultipleQueries) {
158 std::vector<std::unique_ptr<
159 base::i18n::FixedPatternStringSearchIgnoringCaseAndAccents>>
160 queries;
161 queries.push_back(std::make_unique<
162 base::i18n::FixedPatternStringSearchIgnoringCaseAndAccents>(
163 base::UTF8ToUTF16("hello")));
164 queries.push_back(std::make_unique<
165 base::i18n::FixedPatternStringSearchIgnoringCaseAndAccents>(
166 base::UTF8ToUTF16("good")));
167
168 std::string highlighted_text;
169 EXPECT_TRUE(
170 FindAndHighlight("good morning, hello", queries, &highlighted_text));
171 EXPECT_EQ("<b>good</b> morning, <b>hello</b>", highlighted_text);
172 }
173
TEST(SearchMetadataSimpleTest,FindAndHighlight_OverlappingHighlights)174 TEST(SearchMetadataSimpleTest, FindAndHighlight_OverlappingHighlights) {
175 std::vector<std::unique_ptr<
176 base::i18n::FixedPatternStringSearchIgnoringCaseAndAccents>>
177 queries;
178 queries.push_back(std::make_unique<
179 base::i18n::FixedPatternStringSearchIgnoringCaseAndAccents>(
180 base::UTF8ToUTF16("morning")));
181 queries.push_back(std::make_unique<
182 base::i18n::FixedPatternStringSearchIgnoringCaseAndAccents>(
183 base::UTF8ToUTF16("ing,")));
184
185 std::string highlighted_text;
186 EXPECT_TRUE(
187 FindAndHighlight("good morning, hello", queries, &highlighted_text));
188 EXPECT_EQ("good <b>morning,</b> hello", highlighted_text);
189 }
190
191 } // namespace internal
192 } // namespace drive
193