blob: 09d0af76c2f6151b06f2c8a4db4285b93191d237 [file] [log] [blame]
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Unit tests for |Feedback| object.
#include "chrome/browser/spellchecker/feedback.h"
#include "base/strings/utf_string_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::ASCIIToUTF16;
namespace spellcheck {
namespace {
// Identifier for a renderer process.
const int kRendererProcessId = 7;
// Hash identifier for a misspelling.
const uint32 kMisspellingHash = 42;
} // namespace
// A test fixture to help keep the tests simple.
class FeedbackTest : public testing::Test {
public:
FeedbackTest() {}
~FeedbackTest() override {}
protected:
void AddMisspelling(int renderer_process_id, uint32 hash) {
Misspelling misspelling;
misspelling.hash = hash;
feedback_.AddMisspelling(renderer_process_id, misspelling);
}
spellcheck::Feedback feedback_;
};
// Should be able to retrieve misspelling after it's added.
TEST_F(FeedbackTest, RetreiveMisspelling) {
EXPECT_EQ(NULL, feedback_.GetMisspelling(kMisspellingHash));
AddMisspelling(kRendererProcessId, kMisspellingHash);
Misspelling* result = feedback_.GetMisspelling(kMisspellingHash);
EXPECT_NE(static_cast<Misspelling*>(NULL), result);
EXPECT_EQ(kMisspellingHash, result->hash);
}
// Removed misspellings should be finalized.
TEST_F(FeedbackTest, FinalizeRemovedMisspellings) {
static const int kRemovedMisspellingHash = 1;
static const int kRemainingMisspellingHash = 2;
AddMisspelling(kRendererProcessId, kRemovedMisspellingHash);
AddMisspelling(kRendererProcessId, kRemainingMisspellingHash);
std::vector<uint32> remaining_markers(1, kRemainingMisspellingHash);
feedback_.FinalizeRemovedMisspellings(kRendererProcessId, remaining_markers);
Misspelling* removed_misspelling =
feedback_.GetMisspelling(kRemovedMisspellingHash);
EXPECT_NE(static_cast<Misspelling*>(NULL), removed_misspelling);
EXPECT_TRUE(removed_misspelling->action.IsFinal());
Misspelling* remaining_misspelling =
feedback_.GetMisspelling(kRemainingMisspellingHash);
EXPECT_NE(static_cast<Misspelling*>(NULL), remaining_misspelling);
EXPECT_FALSE(remaining_misspelling->action.IsFinal());
}
// Duplicate misspellings should not be finalized.
TEST_F(FeedbackTest, DuplicateMisspellingFinalization) {
AddMisspelling(kRendererProcessId, kMisspellingHash);
AddMisspelling(kRendererProcessId, kMisspellingHash);
std::vector<uint32> remaining_markers(1, kMisspellingHash);
feedback_.FinalizeRemovedMisspellings(kRendererProcessId, remaining_markers);
std::vector<Misspelling> misspellings = feedback_.GetAllMisspellings();
EXPECT_EQ(static_cast<size_t>(1), misspellings.size());
EXPECT_FALSE(misspellings[0].action.IsFinal());
}
// Misspellings should be associated with a renderer.
TEST_F(FeedbackTest, RendererHasMisspellings) {
EXPECT_FALSE(feedback_.RendererHasMisspellings(kRendererProcessId));
AddMisspelling(kRendererProcessId, kMisspellingHash);
EXPECT_TRUE(feedback_.RendererHasMisspellings(kRendererProcessId));
}
// Should be able to retrieve misspellings in renderer.
TEST_F(FeedbackTest, GetMisspellingsInRenderer) {
AddMisspelling(kRendererProcessId, kMisspellingHash);
const std::vector<Misspelling>& renderer_with_misspellings =
feedback_.GetMisspellingsInRenderer(kRendererProcessId);
EXPECT_EQ(static_cast<size_t>(1), renderer_with_misspellings.size());
EXPECT_EQ(kMisspellingHash, renderer_with_misspellings[0].hash);
const std::vector<Misspelling>& renderer_without_misspellings =
feedback_.GetMisspellingsInRenderer(kRendererProcessId + 1);
EXPECT_EQ(static_cast<size_t>(0), renderer_without_misspellings.size());
}
// Finalized misspellings should be erased.
TEST_F(FeedbackTest, EraseFinalizedMisspellings) {
AddMisspelling(kRendererProcessId, kMisspellingHash);
feedback_.FinalizeRemovedMisspellings(kRendererProcessId,
std::vector<uint32>());
EXPECT_TRUE(feedback_.RendererHasMisspellings(kRendererProcessId));
feedback_.EraseFinalizedMisspellings(kRendererProcessId);
EXPECT_FALSE(feedback_.RendererHasMisspellings(kRendererProcessId));
EXPECT_TRUE(feedback_.GetMisspellingsInRenderer(kRendererProcessId).empty());
}
// Should be able to check for misspelling existence.
TEST_F(FeedbackTest, HasMisspelling) {
EXPECT_FALSE(feedback_.HasMisspelling(kMisspellingHash));
AddMisspelling(kRendererProcessId, kMisspellingHash);
EXPECT_TRUE(feedback_.HasMisspelling(kMisspellingHash));
}
// Should be able to check for feedback data presence.
TEST_F(FeedbackTest, EmptyFeedback) {
EXPECT_TRUE(feedback_.Empty());
AddMisspelling(kRendererProcessId, kMisspellingHash);
EXPECT_FALSE(feedback_.Empty());
}
// Should be able to retrieve a list of all renderers with misspellings.
TEST_F(FeedbackTest, GetRendersWithMisspellings) {
EXPECT_TRUE(feedback_.GetRendersWithMisspellings().empty());
AddMisspelling(kRendererProcessId, kMisspellingHash);
AddMisspelling(kRendererProcessId + 1, kMisspellingHash + 1);
std::vector<int> result = feedback_.GetRendersWithMisspellings();
EXPECT_EQ(static_cast<size_t>(2), result.size());
EXPECT_NE(result[0], result[1]);
EXPECT_TRUE(result[0] == kRendererProcessId ||
result[0] == kRendererProcessId + 1);
EXPECT_TRUE(result[1] == kRendererProcessId ||
result[1] == kRendererProcessId + 1);
}
// Should be able to finalize all misspellings.
TEST_F(FeedbackTest, FinalizeAllMisspellings) {
AddMisspelling(kRendererProcessId, kMisspellingHash);
AddMisspelling(kRendererProcessId + 1, kMisspellingHash + 1);
{
std::vector<Misspelling> pending = feedback_.GetAllMisspellings();
for (std::vector<Misspelling>::const_iterator it = pending.begin();
it != pending.end();
++it) {
EXPECT_FALSE(it->action.IsFinal());
}
}
feedback_.FinalizeAllMisspellings();
{
std::vector<Misspelling> final = feedback_.GetAllMisspellings();
for (std::vector<Misspelling>::const_iterator it = final.begin();
it != final.end();
++it) {
EXPECT_TRUE(it->action.IsFinal());
}
}
}
// Should be able to retrieve a copy of all misspellings.
TEST_F(FeedbackTest, GetAllMisspellings) {
EXPECT_TRUE(feedback_.GetAllMisspellings().empty());
AddMisspelling(kRendererProcessId, kMisspellingHash);
AddMisspelling(kRendererProcessId + 1, kMisspellingHash + 1);
const std::vector<Misspelling>& result = feedback_.GetAllMisspellings();
EXPECT_EQ(static_cast<size_t>(2), result.size());
EXPECT_NE(result[0].hash, result[1].hash);
EXPECT_TRUE(result[0].hash == kMisspellingHash ||
result[0].hash == kMisspellingHash + 1);
EXPECT_TRUE(result[1].hash == kMisspellingHash ||
result[1].hash == kMisspellingHash + 1);
}
// Should be able to clear all misspellings.
TEST_F(FeedbackTest, ClearFeedback) {
AddMisspelling(kRendererProcessId, kMisspellingHash);
AddMisspelling(kRendererProcessId + 1, kMisspellingHash + 1);
EXPECT_FALSE(feedback_.Empty());
feedback_.Clear();
EXPECT_TRUE(feedback_.Empty());
}
// Should be able to find misspellings by misspelled word.
TEST_F(FeedbackTest, FindMisspellingsByText) {
static const base::string16 kMisspelledText =
ASCIIToUTF16("Helllo world. Helllo world");
static const base::string16 kSuggestion = ASCIIToUTF16("Hello");
static const int kMisspellingStart = 0;
static const int kMisspellingLength = 6;
static const int kSentenceLength = 14;
static const int kNumberOfSentences = 2;
static const int kNumberOfRenderers = 2;
uint32 hash = kMisspellingHash;
for (int renderer_process_id = kRendererProcessId;
renderer_process_id < kRendererProcessId + kNumberOfRenderers;
++renderer_process_id) {
for (int j = 0; j < kNumberOfSentences; ++j) {
feedback_.AddMisspelling(
renderer_process_id,
Misspelling(kMisspelledText,
kMisspellingStart + j * kSentenceLength,
kMisspellingLength,
std::vector<base::string16>(1, kSuggestion),
++hash));
}
}
static const base::string16 kOtherMisspelledText =
ASCIIToUTF16("Somethign else");
static const base::string16 kOtherSuggestion = ASCIIToUTF16("Something");
static const int kOtherMisspellingStart = 0;
static const int kOtherMisspellingLength = 9;
feedback_.AddMisspelling(
kRendererProcessId,
Misspelling(kOtherMisspelledText,
kOtherMisspellingStart,
kOtherMisspellingLength,
std::vector<base::string16>(1, kOtherSuggestion),
hash + 1));
static const base::string16 kMisspelledWord = ASCIIToUTF16("Helllo");
const std::set<uint32>& misspellings =
feedback_.FindMisspellings(kMisspelledWord);
EXPECT_EQ(static_cast<size_t>(kNumberOfSentences * kNumberOfRenderers),
misspellings.size());
for (std::set<uint32>::const_iterator it = misspellings.begin();
it != misspellings.end();
++it) {
Misspelling* misspelling = feedback_.GetMisspelling(*it);
EXPECT_NE(static_cast<Misspelling*>(NULL), misspelling);
EXPECT_TRUE(misspelling->hash >= kMisspellingHash &&
misspelling->hash <= hash);
EXPECT_EQ(kMisspelledWord, misspelling->GetMisspelledString());
}
}
// Should not be able to find misspellings by misspelled word after they have
// been removed.
TEST_F(FeedbackTest, CannotFindMisspellingsByTextAfterErased) {
static const base::string16 kMisspelledText = ASCIIToUTF16("Helllo world");
static const base::string16 kMisspelledWord = ASCIIToUTF16("Helllo");
static const base::string16 kSuggestion = ASCIIToUTF16("Hello");
static const int kMisspellingStart = 0;
static const int kMisspellingLength = 6;
feedback_.AddMisspelling(
kRendererProcessId,
Misspelling(kMisspelledText,
kMisspellingStart,
kMisspellingLength,
std::vector<base::string16>(1, kSuggestion),
kMisspellingHash));
feedback_.GetMisspelling(kMisspellingHash)->action.Finalize();
feedback_.EraseFinalizedMisspellings(kRendererProcessId);
EXPECT_TRUE(feedback_.FindMisspellings(kMisspelledWord).empty());
}
} // namespace spellcheck