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