1 // Copyright 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.
5 #include "ui/app_list/search/tokenized_string_match.h"
9 #include "base/basictypes.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "testing/gtest/include/gtest/gtest.h"
16 // Returns a string of |text| marked the hits in |match| using block bracket.
17 // e.g. text= "Text", hits = [{0,1}], returns "[T]ext".
18 std::string
MatchHit(const base::string16
& text
,
19 const TokenizedStringMatch
& match
) {
20 base::string16 marked
= text
;
22 const TokenizedStringMatch::Hits
& hits
= match
.hits();
23 for (TokenizedStringMatch::Hits::const_reverse_iterator it
= hits
.rbegin();
24 it
!= hits
.rend(); ++it
) {
25 const gfx::Range
& hit
= *it
;
26 marked
.insert(hit
.end(), 1, ']');
27 marked
.insert(hit
.start(), 1, '[');
30 return base::UTF16ToUTF8(marked
);
33 TEST(TokenizedStringMatchTest
, NotMatch
) {
41 { "!", "!@#$%^&*()<<<**>>>" },
46 TokenizedStringMatch match
;
47 for (size_t i
= 0; i
< arraysize(kTestCases
); ++i
) {
48 const base::string16
text(base::UTF8ToUTF16(kTestCases
[i
].text
));
49 EXPECT_FALSE(match
.Calculate(base::UTF8ToUTF16(kTestCases
[i
].query
), text
))
51 << " : text=" << kTestCases
[i
].text
52 << ", query=" << kTestCases
[i
].query
;
56 TEST(TokenizedStringMatchTest
, Match
) {
62 { "ScratchPad", "pad", "Scratch[Pad]" },
63 { "ScratchPad", "sp", "[S]cratch[P]ad" },
64 { "Chess2", "che", "[Che]ss2" },
65 { "Chess2", "c2", "[C]hess[2]" },
66 { "Cut the rope", "cut ro", "[Cut] the [ro]pe" },
67 { "Cut the rope", "cr", "[C]ut the [r]ope" },
68 { "John Doe", "jdoe", "[J]ohn [Doe]" },
69 { "John Doe", "johnd", "[John D]oe" },
70 { "Secure Shell", "she", "Secure [She]ll" },
71 { "Simple Secure Shell", "sish", "[Si]mple Secure [Sh]ell" },
72 { "Netflix", "flix", "Net[flix]" },
75 TokenizedStringMatch match
;
76 for (size_t i
= 0; i
< arraysize(kTestCases
); ++i
) {
77 const base::string16
text(base::UTF8ToUTF16(kTestCases
[i
].text
));
78 EXPECT_TRUE(match
.Calculate(base::UTF8ToUTF16(kTestCases
[i
].query
), text
));
79 EXPECT_EQ(kTestCases
[i
].expect
, MatchHit(text
, match
));
83 TEST(TokenizedStringMatchTest
, Relevance
) {
86 const char* query_low
;
87 const char* query_high
;
89 // More matched chars are better.
90 { "Google Chrome", "g", "go" },
91 { "Google Chrome", "go", "goo" },
92 { "Google Chrome", "goo", "goog" },
93 { "Google Chrome", "c", "ch" },
94 { "Google Chrome", "ch", "chr" },
95 // Acronym match is better than something in the middle.
96 { "Google Chrome", "ch", "gc" },
97 // Prefix match is better than middle match and acronym match.
98 { "Google Chrome", "ch", "go" },
99 { "Google Chrome", "gc", "go" },
100 // Substring match has the lowest score.
101 { "Google Chrome", "oo", "gc" },
102 { "Google Chrome", "oo", "go" },
103 { "Google Chrome", "oo", "ch" },
106 TokenizedStringMatch match_low
;
107 TokenizedStringMatch match_high
;
108 for (size_t i
= 0; i
< arraysize(kTestCases
); ++i
) {
109 const base::string16
text(base::UTF8ToUTF16(kTestCases
[i
].text
));
111 match_low
.Calculate(base::UTF8ToUTF16(kTestCases
[i
].query_low
), text
));
112 EXPECT_TRUE(match_high
.Calculate(
113 base::UTF8ToUTF16(kTestCases
[i
].query_high
), text
));
114 EXPECT_LT(match_low
.relevance(), match_high
.relevance())
116 << " : text=" << kTestCases
[i
].text
117 << ", query_low=" << kTestCases
[i
].query_low
118 << ", query_high=" << kTestCases
[i
].query_high
;
123 } // namespace app_list