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.
4
5#include "ui/app_list/search/tokenized_string_char_iterator.h"
6
7#include <string>
8#include <vector>
9
10#include "base/strings/string_util.h"
11#include "base/strings/stringprintf.h"
12#include "base/strings/utf_string_conversions.h"
13#include "testing/gtest/include/gtest/gtest.h"
14
15namespace app_list {
16namespace test {
17
18namespace {
19
20// Returns a string represents the current state of |iter|. The state string
21// has three fields. The first is the current char. The second is the offset of
22// the current char in terms of the original text of the TokenizedString. The
23// last one is optional and only shows up when IsFirstCharOfToken returns true.
24std::string GetIterateState(const TokenizedStringCharIterator& iter) {
25  return base::StringPrintf("%s%d%s",
26                            base::UTF16ToUTF8(
27                                base::string16(1, iter.Get())).c_str(),
28                            iter.GetArrayPos(),
29                            iter.IsFirstCharOfToken() ? "!" : "");
30}
31
32void TestBeyondTheEnd(TokenizedStringCharIterator* iter) {
33  ASSERT_TRUE(iter->end());
34  ASSERT_FALSE(iter->NextChar());
35  ASSERT_FALSE(iter->NextToken());
36
37  // Don't care what it returns, but this shouldn't crash.
38  iter->Get();
39}
40
41void TestEveryChar(const std::string& text, const std::string& expects) {
42  TokenizedString tokens(base::UTF8ToUTF16(text));
43  TokenizedStringCharIterator iter(tokens);
44
45  std::vector<std::string> results;
46  while (!iter.end()) {
47    results.push_back(GetIterateState(iter));
48    iter.NextChar();
49  }
50
51  EXPECT_EQ(expects, JoinString(results, ' '));
52  TestBeyondTheEnd(&iter);
53}
54
55void TestNextToken(const std::string& text, const std::string& expects) {
56  TokenizedString tokens(base::UTF8ToUTF16(text));
57  TokenizedStringCharIterator iter(tokens);
58
59  std::vector<std::string> results;
60  while (!iter.end()) {
61    results.push_back(GetIterateState(iter));
62    iter.NextToken();
63  }
64
65  EXPECT_EQ(expects, JoinString(results, ' '));
66  TestBeyondTheEnd(&iter);
67}
68
69void TestFirstTwoCharInEveryToken(const std::string& text,
70                                  const std::string& expects) {
71  TokenizedString tokens(base::UTF8ToUTF16(text));
72  TokenizedStringCharIterator iter(tokens);
73
74  std::vector<std::string> results;
75  while (!iter.end()) {
76    results.push_back(GetIterateState(iter));
77    if (iter.NextChar())
78      results.push_back(GetIterateState(iter));
79
80    iter.NextToken();
81  }
82
83  EXPECT_EQ(expects, JoinString(results, ' '));
84  TestBeyondTheEnd(&iter);
85}
86
87}  // namespace
88
89TEST(TokenizedStringCharIteratorTest, NoTerms) {
90  const char* text;
91
92  text = "";
93  TestEveryChar(text, "");
94  TestNextToken(text, "");
95  TestFirstTwoCharInEveryToken(text, "");
96
97  text = "!@#$%^&*()<<<**>>>";
98  TestEveryChar(text, "");
99  TestNextToken(text, "");
100  TestFirstTwoCharInEveryToken(text, "");
101}
102
103TEST(TokenizedStringCharIteratorTest, Basic) {
104  const char* text;
105
106  text = "c";
107  TestEveryChar(text, "c0!");
108  TestNextToken(text, "c0!");
109  TestFirstTwoCharInEveryToken(text, "c0!");
110
111  text = "Simple";
112  TestEveryChar(text, "s0! i1 m2 p3 l4 e5");
113  TestNextToken(text, "s0!");
114  TestFirstTwoCharInEveryToken(text, "s0! i1");
115
116  text = "ScratchPad";
117  TestEveryChar(text, "s0! c1 r2 a3 t4 c5 h6 p7! a8 d9");
118  TestNextToken(text, "s0! p7!");
119  TestFirstTwoCharInEveryToken(text, "s0! c1 p7! a8");
120
121  text = "Chess2.0";
122  TestEveryChar(text, "c0! h1 e2 s3 s4 25! .6 07");
123  TestNextToken(text, "c0! 25!");
124  TestFirstTwoCharInEveryToken(text, "c0! h1 25! .6");
125
126  text = "Cut the rope";
127  TestEveryChar(text, "c0! u1 t2 t4! h5 e6 r8! o9 p10 e11");
128  TestNextToken(text, "c0! t4! r8!");
129  TestFirstTwoCharInEveryToken(text, "c0! u1 t4! h5 r8! o9");
130
131  text = "AutoCAD WS";
132  TestEveryChar(text, "a0! u1 t2 o3 c4! a5 d6 w8! s9");
133  TestNextToken(text, "a0! c4! w8!");
134  TestFirstTwoCharInEveryToken(text, "a0! u1 c4! a5 w8! s9");
135
136  text = "Great TweetDeck";
137  TestEveryChar(text, "g0! r1 e2 a3 t4 t6! w7 e8 e9 t10 d11! e12 c13 k14");
138  TestNextToken(text, "g0! t6! d11!");
139  TestFirstTwoCharInEveryToken(text, "g0! r1 t6! w7 d11! e12");
140
141  text = "Draw-It!";
142  TestEveryChar(text, "d0! r1 a2 w3 i5! t6");
143  TestNextToken(text, "d0! i5!");
144  TestFirstTwoCharInEveryToken(text, "d0! r1 i5! t6");
145
146  text = "Faxing & Signing";
147  TestEveryChar(text, "f0! a1 x2 i3 n4 g5 s9! i10 g11 n12 i13 n14 g15");
148  TestNextToken(text, "f0! s9!");
149  TestFirstTwoCharInEveryToken(text, "f0! a1 s9! i10");
150}
151
152}  // namespace test
153}  // namespace app_list
154