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: 27 FeedbackTest() {} 28 virtual ~FeedbackTest() {} 29 30 protected: 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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