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 // Unit tests for |Feedback| object.
6
7 #include "chrome/browser/spellchecker/feedback.h"
8
9 #include "base/strings/utf_string_conversions.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11
12 namespace spellcheck {
13
14 namespace {
15
16 // Identifier for a renderer process.
17 const int kRendererProcessId = 7;
18
19 // Hash identifier for a misspelling.
20 const uint32 kMisspellingHash = 42;
21
22 } // namespace
23
24 // A test fixture to help keep the tests simple.
25 class FeedbackTest : public testing::Test {
26 public:
FeedbackTest()27 FeedbackTest() {}
~FeedbackTest()28 virtual ~FeedbackTest() {}
29
30 protected:
AddMisspelling(int renderer_process_id,uint32 hash)31 void AddMisspelling(int renderer_process_id, uint32 hash) {
32 Misspelling misspelling;
33 misspelling.hash = hash;
34 feedback_.AddMisspelling(renderer_process_id, misspelling);
35 }
36
37 spellcheck::Feedback feedback_;
38 };
39
40 // Should be able to retrieve misspelling after it's added.
TEST_F(FeedbackTest,RetreiveMisspelling)41 TEST_F(FeedbackTest, RetreiveMisspelling) {
42 EXPECT_EQ(NULL, feedback_.GetMisspelling(kMisspellingHash));
43 AddMisspelling(kRendererProcessId, kMisspellingHash);
44 Misspelling* result = feedback_.GetMisspelling(kMisspellingHash);
45 EXPECT_NE(static_cast<Misspelling*>(NULL), result);
46 EXPECT_EQ(kMisspellingHash, result->hash);
47 }
48
49 // Removed misspellings should be finalized.
TEST_F(FeedbackTest,FinalizeRemovedMisspellings)50 TEST_F(FeedbackTest, FinalizeRemovedMisspellings) {
51 static const int kRemovedMisspellingHash = 1;
52 static const int kRemainingMisspellingHash = 2;
53 AddMisspelling(kRendererProcessId, kRemovedMisspellingHash);
54 AddMisspelling(kRendererProcessId, kRemainingMisspellingHash);
55 std::vector<uint32> remaining_markers(1, kRemainingMisspellingHash);
56 feedback_.FinalizeRemovedMisspellings(kRendererProcessId, remaining_markers);
57 Misspelling* removed_misspelling =
58 feedback_.GetMisspelling(kRemovedMisspellingHash);
59 EXPECT_NE(static_cast<Misspelling*>(NULL), removed_misspelling);
60 EXPECT_TRUE(removed_misspelling->action.IsFinal());
61 Misspelling* remaining_misspelling =
62 feedback_.GetMisspelling(kRemainingMisspellingHash);
63 EXPECT_NE(static_cast<Misspelling*>(NULL), remaining_misspelling);
64 EXPECT_FALSE(remaining_misspelling->action.IsFinal());
65 }
66
67 // Duplicate misspellings should not be finalized.
TEST_F(FeedbackTest,DuplicateMisspellingFinalization)68 TEST_F(FeedbackTest, DuplicateMisspellingFinalization) {
69 AddMisspelling(kRendererProcessId, kMisspellingHash);
70 AddMisspelling(kRendererProcessId, kMisspellingHash);
71 std::vector<uint32> remaining_markers(1, kMisspellingHash);
72 feedback_.FinalizeRemovedMisspellings(kRendererProcessId, remaining_markers);
73 std::vector<Misspelling> misspellings = feedback_.GetAllMisspellings();
74 EXPECT_EQ(static_cast<size_t>(1), misspellings.size());
75 EXPECT_FALSE(misspellings[0].action.IsFinal());
76 }
77
78 // Misspellings should be associated with a renderer.
TEST_F(FeedbackTest,RendererHasMisspellings)79 TEST_F(FeedbackTest, RendererHasMisspellings) {
80 EXPECT_FALSE(feedback_.RendererHasMisspellings(kRendererProcessId));
81 AddMisspelling(kRendererProcessId, kMisspellingHash);
82 EXPECT_TRUE(feedback_.RendererHasMisspellings(kRendererProcessId));
83 }
84
85 // Should be able to retrieve misspellings in renderer.
TEST_F(FeedbackTest,GetMisspellingsInRenderer)86 TEST_F(FeedbackTest, GetMisspellingsInRenderer) {
87 AddMisspelling(kRendererProcessId, kMisspellingHash);
88 const std::vector<Misspelling>& renderer_with_misspellings =
89 feedback_.GetMisspellingsInRenderer(kRendererProcessId);
90 EXPECT_EQ(static_cast<size_t>(1), renderer_with_misspellings.size());
91 EXPECT_EQ(kMisspellingHash, renderer_with_misspellings[0].hash);
92 const std::vector<Misspelling>& renderer_without_misspellings =
93 feedback_.GetMisspellingsInRenderer(kRendererProcessId + 1);
94 EXPECT_EQ(static_cast<size_t>(0), renderer_without_misspellings.size());
95 }
96
97 // Finalized misspellings should be erased.
TEST_F(FeedbackTest,EraseFinalizedMisspellings)98 TEST_F(FeedbackTest, EraseFinalizedMisspellings) {
99 AddMisspelling(kRendererProcessId, kMisspellingHash);
100 feedback_.FinalizeRemovedMisspellings(kRendererProcessId,
101 std::vector<uint32>());
102 EXPECT_TRUE(feedback_.RendererHasMisspellings(kRendererProcessId));
103 feedback_.EraseFinalizedMisspellings(kRendererProcessId);
104 EXPECT_FALSE(feedback_.RendererHasMisspellings(kRendererProcessId));
105 EXPECT_TRUE(feedback_.GetMisspellingsInRenderer(kRendererProcessId).empty());
106 }
107
108 // Should be able to check for misspelling existence.
TEST_F(FeedbackTest,HasMisspelling)109 TEST_F(FeedbackTest, HasMisspelling) {
110 EXPECT_FALSE(feedback_.HasMisspelling(kMisspellingHash));
111 AddMisspelling(kRendererProcessId, kMisspellingHash);
112 EXPECT_TRUE(feedback_.HasMisspelling(kMisspellingHash));
113 }
114
115 // Should be able to check for feedback data presence.
TEST_F(FeedbackTest,EmptyFeedback)116 TEST_F(FeedbackTest, EmptyFeedback) {
117 EXPECT_TRUE(feedback_.Empty());
118 AddMisspelling(kRendererProcessId, kMisspellingHash);
119 EXPECT_FALSE(feedback_.Empty());
120 }
121
122 // Should be able to retrieve a list of all renderers with misspellings.
TEST_F(FeedbackTest,GetRendersWithMisspellings)123 TEST_F(FeedbackTest, GetRendersWithMisspellings) {
124 EXPECT_TRUE(feedback_.GetRendersWithMisspellings().empty());
125 AddMisspelling(kRendererProcessId, kMisspellingHash);
126 AddMisspelling(kRendererProcessId + 1, kMisspellingHash + 1);
127 std::vector<int> result = feedback_.GetRendersWithMisspellings();
128 EXPECT_EQ(static_cast<size_t>(2), result.size());
129 EXPECT_NE(result[0], result[1]);
130 EXPECT_TRUE(result[0] == kRendererProcessId ||
131 result[0] == kRendererProcessId + 1);
132 EXPECT_TRUE(result[1] == kRendererProcessId ||
133 result[1] == kRendererProcessId + 1);
134 }
135
136 // Should be able to finalize all misspellings.
TEST_F(FeedbackTest,FinalizeAllMisspellings)137 TEST_F(FeedbackTest, FinalizeAllMisspellings) {
138 AddMisspelling(kRendererProcessId, kMisspellingHash);
139 AddMisspelling(kRendererProcessId + 1, kMisspellingHash + 1);
140 {
141 std::vector<Misspelling> pending = feedback_.GetAllMisspellings();
142 for (std::vector<Misspelling>::const_iterator it = pending.begin();
143 it != pending.end();
144 ++it) {
145 EXPECT_FALSE(it->action.IsFinal());
146 }
147 }
148 feedback_.FinalizeAllMisspellings();
149 {
150 std::vector<Misspelling> final = feedback_.GetAllMisspellings();
151 for (std::vector<Misspelling>::const_iterator it = final.begin();
152 it != final.end();
153 ++it) {
154 EXPECT_TRUE(it->action.IsFinal());
155 }
156 }
157 }
158
159 // Should be able to retrieve a copy of all misspellings.
TEST_F(FeedbackTest,GetAllMisspellings)160 TEST_F(FeedbackTest, GetAllMisspellings) {
161 EXPECT_TRUE(feedback_.GetAllMisspellings().empty());
162 AddMisspelling(kRendererProcessId, kMisspellingHash);
163 AddMisspelling(kRendererProcessId + 1, kMisspellingHash + 1);
164 const std::vector<Misspelling>& result = feedback_.GetAllMisspellings();
165 EXPECT_EQ(static_cast<size_t>(2), result.size());
166 EXPECT_NE(result[0].hash, result[1].hash);
167 EXPECT_TRUE(result[0].hash == kMisspellingHash ||
168 result[0].hash == kMisspellingHash + 1);
169 EXPECT_TRUE(result[1].hash == kMisspellingHash ||
170 result[1].hash == kMisspellingHash + 1);
171 }
172
173 // Should be able to clear all misspellings.
TEST_F(FeedbackTest,ClearFeedback)174 TEST_F(FeedbackTest, ClearFeedback) {
175 AddMisspelling(kRendererProcessId, kMisspellingHash);
176 AddMisspelling(kRendererProcessId + 1, kMisspellingHash + 1);
177 EXPECT_FALSE(feedback_.Empty());
178 feedback_.Clear();
179 EXPECT_TRUE(feedback_.Empty());
180 }
181
182 // Should be able to find misspellings by misspelled word.
TEST_F(FeedbackTest,FindMisspellingsByText)183 TEST_F(FeedbackTest, FindMisspellingsByText) {
184 static const base::string16 kMisspelledText =
185 ASCIIToUTF16("Helllo world. Helllo world");
186 static const base::string16 kSuggestion = ASCIIToUTF16("Hello");
187 static const int kMisspellingStart = 0;
188 static const int kMisspellingLength = 6;
189 static const int kSentenceLength = 14;
190 static const int kNumberOfSentences = 2;
191 static const int kNumberOfRenderers = 2;
192 uint32 hash = kMisspellingHash;
193 for (int renderer_process_id = kRendererProcessId;
194 renderer_process_id < kRendererProcessId + kNumberOfRenderers;
195 ++renderer_process_id) {
196 for (int j = 0; j < kNumberOfSentences; ++j) {
197 feedback_.AddMisspelling(
198 renderer_process_id,
199 Misspelling(kMisspelledText,
200 kMisspellingStart + j * kSentenceLength,
201 kMisspellingLength,
202 std::vector<base::string16>(1, kSuggestion),
203 ++hash));
204 }
205 }
206
207 static const base::string16 kOtherMisspelledText =
208 ASCIIToUTF16("Somethign else");
209 static const base::string16 kOtherSuggestion = ASCIIToUTF16("Something");
210 static const int kOtherMisspellingStart = 0;
211 static const int kOtherMisspellingLength = 9;
212 feedback_.AddMisspelling(
213 kRendererProcessId,
214 Misspelling(kOtherMisspelledText,
215 kOtherMisspellingStart,
216 kOtherMisspellingLength,
217 std::vector<base::string16>(1, kOtherSuggestion),
218 hash + 1));
219
220 static const base::string16 kMisspelledWord = ASCIIToUTF16("Helllo");
221 const std::set<uint32>& misspellings =
222 feedback_.FindMisspellings(kMisspelledWord);
223 EXPECT_EQ(static_cast<size_t>(kNumberOfSentences * kNumberOfRenderers),
224 misspellings.size());
225
226 for (std::set<uint32>::const_iterator it = misspellings.begin();
227 it != misspellings.end();
228 ++it) {
229 Misspelling* misspelling = feedback_.GetMisspelling(*it);
230 EXPECT_NE(static_cast<Misspelling*>(NULL), misspelling);
231 EXPECT_TRUE(misspelling->hash >= kMisspellingHash &&
232 misspelling->hash <= hash);
233 EXPECT_EQ(kMisspelledWord, misspelling->GetMisspelledString());
234 }
235 }
236
237 // Should not be able to find misspellings by misspelled word after they have
238 // been removed.
TEST_F(FeedbackTest,CannotFindMisspellingsByTextAfterErased)239 TEST_F(FeedbackTest, CannotFindMisspellingsByTextAfterErased) {
240 static const base::string16 kMisspelledText = ASCIIToUTF16("Helllo world");
241 static const base::string16 kMisspelledWord = ASCIIToUTF16("Helllo");
242 static const base::string16 kSuggestion = ASCIIToUTF16("Hello");
243 static const int kMisspellingStart = 0;
244 static const int kMisspellingLength = 6;
245 feedback_.AddMisspelling(
246 kRendererProcessId,
247 Misspelling(kMisspelledText,
248 kMisspellingStart,
249 kMisspellingLength,
250 std::vector<base::string16>(1, kSuggestion),
251 kMisspellingHash));
252 feedback_.GetMisspelling(kMisspellingHash)->action.Finalize();
253 feedback_.EraseFinalizedMisspellings(kRendererProcessId);
254 EXPECT_TRUE(feedback_.FindMisspellings(kMisspelledWord).empty());
255 }
256
257 } // namespace spellcheck
258