This source file includes following definitions.
- GetAllSyncDataNoLimit
- BuildSpellcheckService
- SetUp
- LoadDictionaryFile
- UpdateDictionaryFile
- OnLoaded
- Apply
- CreateAndUploadError
- changes_
- loads
- changes
- OnCustomDictionaryLoaded
- OnCustomDictionaryChanged
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
#include <vector>
#include "base/file_util.h"
#include "base/metrics/histogram_samples.h"
#include "base/metrics/statistics_recorder.h"
#include "base/strings/string_number_conversions.h"
#include "chrome/browser/spellchecker/spellcheck_custom_dictionary.h"
#include "chrome/browser/spellchecker/spellcheck_factory.h"
#include "chrome/browser/spellchecker/spellcheck_host_metrics.h"
#include "chrome/browser/spellchecker/spellcheck_service.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/spellcheck_common.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "net/url_request/test_url_fetcher_factory.h"
#include "sync/api/sync_change.h"
#include "sync/api/sync_change_processor_wrapper_for_test.h"
#include "sync/api/sync_data.h"
#include "sync/api/sync_error_factory.h"
#include "sync/api/sync_error_factory_mock.h"
#include "sync/protocol/sync.pb.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#if defined(OS_WIN)
#include "base/win/windows_version.h"
#endif
using base::HistogramBase;
using base::HistogramSamples;
using base::StatisticsRecorder;
using chrome::spellcheck_common::WordList;
using chrome::spellcheck_common::WordSet;
namespace {
syncer::SyncDataList GetAllSyncDataNoLimit(
const SpellcheckCustomDictionary* dictionary) {
syncer::SyncDataList data;
std::string word;
const WordSet& words = dictionary->GetWords();
for (WordSet::const_iterator it = words.begin(); it != words.end(); ++it) {
word = *it;
sync_pb::EntitySpecifics specifics;
specifics.mutable_dictionary()->set_word(word);
data.push_back(syncer::SyncData::CreateLocalData(word, word, specifics));
}
return data;
}
}
static KeyedService* BuildSpellcheckService(content::BrowserContext* profile) {
return new SpellcheckService(static_cast<Profile*>(profile));
}
class SpellcheckCustomDictionaryTest : public testing::Test {
protected:
virtual void SetUp() OVERRIDE {
SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
&profile_, &BuildSpellcheckService);
StatisticsRecorder::Initialize();
}
chrome::spellcheck_common::WordList LoadDictionaryFile(
const base::FilePath& path) {
return SpellcheckCustomDictionary::LoadDictionaryFile(path);
}
void UpdateDictionaryFile(
const SpellcheckCustomDictionary::Change& dictionary_change,
const base::FilePath& path) {
SpellcheckCustomDictionary::UpdateDictionaryFile(dictionary_change, path);
}
void OnLoaded(
SpellcheckCustomDictionary& dictionary,
const chrome::spellcheck_common::WordList& custom_words) {
dictionary.OnLoaded(custom_words);
}
void Apply(
SpellcheckCustomDictionary& dictionary,
const SpellcheckCustomDictionary::Change& change) {
return dictionary.Apply(change);
}
content::TestBrowserThreadBundle thread_bundle_;
TestingProfile profile_;
net::TestURLFetcherFactory fetcher_factory_;
};
class SyncErrorFactoryStub : public syncer::SyncErrorFactory {
public:
explicit SyncErrorFactoryStub(int* error_counter)
: error_counter_(error_counter) {}
virtual ~SyncErrorFactoryStub() {}
virtual syncer::SyncError CreateAndUploadError(
const tracked_objects::Location& location,
const std::string& message) OVERRIDE {
(*error_counter_)++;
return syncer::SyncError(location,
syncer::SyncError::DATATYPE_ERROR,
message,
syncer::DICTIONARY);
}
private:
int* error_counter_;
DISALLOW_COPY_AND_ASSIGN(SyncErrorFactoryStub);
};
class DictionaryObserverCounter : public SpellcheckCustomDictionary::Observer {
public:
DictionaryObserverCounter() : loads_(0), changes_(0) {}
virtual ~DictionaryObserverCounter() {}
int loads() const { return loads_; }
int changes() const { return changes_; }
virtual void OnCustomDictionaryLoaded() OVERRIDE { loads_++; }
virtual void OnCustomDictionaryChanged(
const SpellcheckCustomDictionary::Change& change) OVERRIDE { changes_++; }
private:
int loads_;
int changes_;
DISALLOW_COPY_AND_ASSIGN(DictionaryObserverCounter);
};
TEST_F(SpellcheckCustomDictionaryTest, SaveAndLoad) {
base::FilePath path =
profile_.GetPath().Append(chrome::kCustomDictionaryFileName);
WordList loaded_custom_words = LoadDictionaryFile(path);
WordList expected;
EXPECT_EQ(expected, loaded_custom_words);
SpellcheckCustomDictionary::Change change;
change.AddWord("bar");
change.AddWord("foo");
UpdateDictionaryFile(change, path);
expected.push_back("bar");
expected.push_back("foo");
loaded_custom_words = LoadDictionaryFile(path);
EXPECT_EQ(expected, loaded_custom_words);
change = SpellcheckCustomDictionary::Change();
change.RemoveWord("bar");
change.RemoveWord("foo");
UpdateDictionaryFile(change, path);
loaded_custom_words = LoadDictionaryFile(path);
expected.clear();
EXPECT_EQ(expected, loaded_custom_words);
}
TEST_F(SpellcheckCustomDictionaryTest, MultiProfile) {
SpellcheckService* spellcheck_service =
SpellcheckServiceFactory::GetForContext(&profile_);
SpellcheckCustomDictionary* custom_dictionary =
spellcheck_service->GetCustomDictionary();
TestingProfile profile2;
SpellcheckService* spellcheck_service2 =
static_cast<SpellcheckService*>(
SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
&profile2, &BuildSpellcheckService));
SpellcheckCustomDictionary* custom_dictionary2 =
spellcheck_service2->GetCustomDictionary();
WordSet expected1;
WordSet expected2;
custom_dictionary->AddWord("foo");
custom_dictionary->AddWord("bar");
expected1.insert("foo");
expected1.insert("bar");
custom_dictionary2->AddWord("hoge");
custom_dictionary2->AddWord("fuga");
expected2.insert("hoge");
expected2.insert("fuga");
WordSet actual1 = custom_dictionary->GetWords();
EXPECT_EQ(actual1, expected1);
WordSet actual2 = custom_dictionary2->GetWords();
EXPECT_EQ(actual2, expected2);
}
TEST_F(SpellcheckCustomDictionaryTest, LegacyEmptyDictionaryShouldBeConverted) {
base::FilePath path =
profile_.GetPath().Append(chrome::kCustomDictionaryFileName);
std::string content;
base::WriteFile(path, content.c_str(), content.length());
WordList loaded_custom_words = LoadDictionaryFile(path);
EXPECT_TRUE(loaded_custom_words.empty());
}
TEST_F(SpellcheckCustomDictionaryTest,
LegacyDictionaryWithTwoWordsShouldBeConverted) {
base::FilePath path =
profile_.GetPath().Append(chrome::kCustomDictionaryFileName);
std::string content = "foo\nbar\nfoo\n";
base::WriteFile(path, content.c_str(), content.length());
WordList loaded_custom_words = LoadDictionaryFile(path);
WordList expected;
expected.push_back("bar");
expected.push_back("foo");
EXPECT_EQ(expected, loaded_custom_words);
}
TEST_F(SpellcheckCustomDictionaryTest,
IllegalWordsShouldBeRemovedFromDictionary) {
base::FilePath path =
profile_.GetPath().Append(chrome::kCustomDictionaryFileName);
std::string content = "foo\n foo bar \n\n \nbar\n"
"01234567890123456789012345678901234567890123456789"
"01234567890123456789012345678901234567890123456789";
base::WriteFile(path, content.c_str(), content.length());
WordList loaded_custom_words = LoadDictionaryFile(path);
WordList expected;
expected.push_back("bar");
expected.push_back("foo");
expected.push_back("foo bar");
EXPECT_EQ(expected, loaded_custom_words);
}
TEST_F(SpellcheckCustomDictionaryTest, CorruptedWriteShouldBeRecovered) {
base::FilePath path =
profile_.GetPath().Append(chrome::kCustomDictionaryFileName);
std::string content = "foo\nbar";
base::WriteFile(path, content.c_str(), content.length());
WordList loaded_custom_words = LoadDictionaryFile(path);
WordList expected;
expected.push_back("bar");
expected.push_back("foo");
EXPECT_EQ(expected, loaded_custom_words);
SpellcheckCustomDictionary::Change change;
change.AddWord("baz");
UpdateDictionaryFile(change, path);
content.clear();
base::ReadFileToString(path, &content);
content.append("corruption");
base::WriteFile(path, content.c_str(), content.length());
loaded_custom_words = LoadDictionaryFile(path);
EXPECT_EQ(expected, loaded_custom_words);
}
TEST_F(SpellcheckCustomDictionaryTest,
GetAllSyncDataAccuratelyReflectsDictionaryState) {
SpellcheckCustomDictionary* dictionary =
SpellcheckServiceFactory::GetForContext(
&profile_)->GetCustomDictionary();
syncer::SyncDataList data = dictionary->GetAllSyncData(syncer::DICTIONARY);
EXPECT_TRUE(data.empty());
EXPECT_TRUE(dictionary->AddWord("bar"));
EXPECT_TRUE(dictionary->AddWord("foo"));
data = dictionary->GetAllSyncData(syncer::DICTIONARY);
EXPECT_EQ(2UL, data.size());
std::vector<std::string> words;
words.push_back("bar");
words.push_back("foo");
for (size_t i = 0; i < data.size(); i++) {
EXPECT_TRUE(data[i].GetSpecifics().has_dictionary());
EXPECT_EQ(syncer::DICTIONARY, data[i].GetDataType());
EXPECT_EQ(words[i], syncer::SyncDataLocal(data[i]).GetTag());
EXPECT_EQ(words[i], data[i].GetSpecifics().dictionary().word());
}
EXPECT_TRUE(dictionary->RemoveWord("bar"));
EXPECT_TRUE(dictionary->RemoveWord("foo"));
data = dictionary->GetAllSyncData(syncer::DICTIONARY);
EXPECT_TRUE(data.empty());
}
TEST_F(SpellcheckCustomDictionaryTest, GetAllSyncDataHasLimit) {
SpellcheckCustomDictionary* dictionary =
SpellcheckServiceFactory::GetForContext(
&profile_)->GetCustomDictionary();
SpellcheckCustomDictionary::Change change;
for (size_t i = 0;
i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS - 1;
i++) {
change.AddWord("foo" + base::Uint64ToString(i));
}
Apply(*dictionary, change);
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS - 1,
dictionary->GetWords().size());
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS - 1,
dictionary->GetAllSyncData(syncer::DICTIONARY).size());
dictionary->AddWord("baz");
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
dictionary->GetWords().size());
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
dictionary->GetAllSyncData(syncer::DICTIONARY).size());
dictionary->AddWord("bar");
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1,
dictionary->GetWords().size());
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
dictionary->GetAllSyncData(syncer::DICTIONARY).size());
dictionary->AddWord("snafoo");
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 2,
dictionary->GetWords().size());
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
dictionary->GetAllSyncData(syncer::DICTIONARY).size());
}
TEST_F(SpellcheckCustomDictionaryTest, ProcessSyncChanges) {
SpellcheckService* spellcheck_service =
SpellcheckServiceFactory::GetForContext(&profile_);
SpellcheckCustomDictionary* dictionary =
spellcheck_service->GetCustomDictionary();
dictionary->AddWord("foo");
dictionary->AddWord("bar");
syncer::SyncChangeList changes;
{
std::string word = "foo";
sync_pb::EntitySpecifics specifics;
specifics.mutable_dictionary()->set_word(word);
changes.push_back(syncer::SyncChange(
FROM_HERE,
syncer::SyncChange::ACTION_ADD,
syncer::SyncData::CreateLocalData(word, word, specifics)));
}
{
std::string word = "01234567890123456789012345678901234567890123456789"
"01234567890123456789012345678901234567890123456789";
sync_pb::EntitySpecifics specifics;
specifics.mutable_dictionary()->set_word(word);
changes.push_back(syncer::SyncChange(
FROM_HERE,
syncer::SyncChange::ACTION_ADD,
syncer::SyncData::CreateLocalData(word, word, specifics)));
}
{
std::string word = "baz";
sync_pb::EntitySpecifics specifics;
specifics.mutable_dictionary()->set_word(word);
changes.push_back(syncer::SyncChange(
FROM_HERE,
syncer::SyncChange::ACTION_ADD,
syncer::SyncData::CreateLocalData(word, word, specifics)));
}
{
std::string word = "snafoo";
sync_pb::EntitySpecifics specifics;
specifics.mutable_dictionary()->set_word(word);
changes.push_back(syncer::SyncChange(
FROM_HERE,
syncer::SyncChange::ACTION_DELETE,
syncer::SyncData::CreateLocalData(word, word, specifics)));
}
{
std::string word = "bar";
sync_pb::EntitySpecifics specifics;
specifics.mutable_dictionary()->set_word(word);
changes.push_back(syncer::SyncChange(
FROM_HERE,
syncer::SyncChange::ACTION_DELETE,
syncer::SyncData::CreateLocalData(word, word, specifics)));
}
EXPECT_FALSE(dictionary->ProcessSyncChanges(FROM_HERE, changes).IsSet());
const WordSet& words = dictionary->GetWords();
EXPECT_EQ(2UL, words.size());
EXPECT_EQ(0UL, words.count("bar"));
EXPECT_EQ(1UL, words.count("foo"));
EXPECT_EQ(1UL, words.count("baz"));
}
TEST_F(SpellcheckCustomDictionaryTest, MergeDataAndStartSyncing) {
SpellcheckService* spellcheck_service =
SpellcheckServiceFactory::GetForContext(&profile_);
SpellcheckCustomDictionary* custom_dictionary =
spellcheck_service->GetCustomDictionary();
TestingProfile profile2;
SpellcheckService* spellcheck_service2 =
static_cast<SpellcheckService*>(
SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
&profile2, &BuildSpellcheckService));
SpellcheckCustomDictionary* custom_dictionary2 =
spellcheck_service2->GetCustomDictionary();
SpellcheckCustomDictionary::Change change;
for (size_t i = 0;
i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS / 2;
++i) {
change.AddWord("foo" + base::Uint64ToString(i));
}
Apply(*custom_dictionary, change);
SpellcheckCustomDictionary::Change change2;
for (size_t i = 0;
i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS / 2;
++i) {
change2.AddWord("bar" + base::Uint64ToString(i));
}
Apply(*custom_dictionary2, change2);
int error_counter = 0;
EXPECT_FALSE(
custom_dictionary->MergeDataAndStartSyncing(
syncer::DICTIONARY,
custom_dictionary2->GetAllSyncData(
syncer::DICTIONARY),
scoped_ptr<syncer::SyncChangeProcessor>(
new syncer::SyncChangeProcessorWrapperForTest(
custom_dictionary2)),
scoped_ptr<syncer::SyncErrorFactory>(
new SyncErrorFactoryStub(&error_counter)))
.error()
.IsSet());
EXPECT_EQ(0, error_counter);
EXPECT_TRUE(custom_dictionary->IsSyncing());
WordSet words = custom_dictionary->GetWords();
WordSet words2 = custom_dictionary2->GetWords();
EXPECT_EQ(words.size(), words2.size());
EXPECT_EQ(words, words2);
}
TEST_F(SpellcheckCustomDictionaryTest, DictionaryTooBigBeforeSyncing) {
SpellcheckService* spellcheck_service =
SpellcheckServiceFactory::GetForContext(&profile_);
SpellcheckCustomDictionary* custom_dictionary =
spellcheck_service->GetCustomDictionary();
TestingProfile profile2;
SpellcheckService* spellcheck_service2 =
static_cast<SpellcheckService*>(
SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
&profile2, &BuildSpellcheckService));
SpellcheckCustomDictionary* custom_dictionary2 =
spellcheck_service2->GetCustomDictionary();
SpellcheckCustomDictionary::Change change;
for (size_t i = 0;
i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1;
++i) {
change.AddWord("foo" + base::Uint64ToString(i));
}
Apply(*custom_dictionary, change);
int error_counter = 0;
EXPECT_FALSE(
custom_dictionary->MergeDataAndStartSyncing(
syncer::DICTIONARY,
custom_dictionary2->GetAllSyncData(
syncer::DICTIONARY),
scoped_ptr<syncer::SyncChangeProcessor>(
new syncer::SyncChangeProcessorWrapperForTest(
custom_dictionary2)),
scoped_ptr<syncer::SyncErrorFactory>(
new SyncErrorFactoryStub(&error_counter)))
.error()
.IsSet());
EXPECT_EQ(0, error_counter);
EXPECT_FALSE(custom_dictionary->IsSyncing());
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1,
custom_dictionary->GetWords().size());
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
custom_dictionary2->GetWords().size());
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
custom_dictionary->GetAllSyncData(syncer::DICTIONARY).size());
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
custom_dictionary2->GetAllSyncData(syncer::DICTIONARY).size());
}
TEST_F(SpellcheckCustomDictionaryTest, DictionaryTooBigAndServerFull) {
SpellcheckService* spellcheck_service =
SpellcheckServiceFactory::GetForContext(&profile_);
SpellcheckCustomDictionary* custom_dictionary =
spellcheck_service->GetCustomDictionary();
TestingProfile profile2;
SpellcheckService* spellcheck_service2 =
static_cast<SpellcheckService*>(
SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
&profile2, &BuildSpellcheckService));
SpellcheckCustomDictionary* custom_dictionary2 =
spellcheck_service2->GetCustomDictionary();
SpellcheckCustomDictionary::Change change;
SpellcheckCustomDictionary::Change change2;
for (size_t i = 0;
i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS;
++i) {
change.AddWord("foo" + base::Uint64ToString(i));
change2.AddWord("bar" + base::Uint64ToString(i));
}
change.AddWord("foo");
Apply(*custom_dictionary, change);
Apply(*custom_dictionary2, change2);
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1,
custom_dictionary->GetWords().size());
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
custom_dictionary2->GetWords().size());
int error_counter = 0;
EXPECT_FALSE(
custom_dictionary->MergeDataAndStartSyncing(
syncer::DICTIONARY,
custom_dictionary2->GetAllSyncData(
syncer::DICTIONARY),
scoped_ptr<syncer::SyncChangeProcessor>(
new syncer::SyncChangeProcessorWrapperForTest(
custom_dictionary2)),
scoped_ptr<syncer::SyncErrorFactory>(
new SyncErrorFactoryStub(&error_counter)))
.error()
.IsSet());
EXPECT_EQ(0, error_counter);
EXPECT_FALSE(custom_dictionary->IsSyncing());
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS * 2 + 1,
custom_dictionary->GetWords().size());
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
custom_dictionary2->GetWords().size());
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
custom_dictionary->GetAllSyncData(syncer::DICTIONARY).size());
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
custom_dictionary2->GetAllSyncData(syncer::DICTIONARY).size());
}
TEST_F(SpellcheckCustomDictionaryTest, ServerTooBig) {
SpellcheckService* spellcheck_service =
SpellcheckServiceFactory::GetForContext(&profile_);
SpellcheckCustomDictionary* custom_dictionary =
spellcheck_service->GetCustomDictionary();
TestingProfile profile2;
SpellcheckService* spellcheck_service2 =
static_cast<SpellcheckService*>(
SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
&profile2, &BuildSpellcheckService));
SpellcheckCustomDictionary* custom_dictionary2 =
spellcheck_service2->GetCustomDictionary();
SpellcheckCustomDictionary::Change change;
SpellcheckCustomDictionary::Change change2;
for (size_t i = 0;
i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1;
++i) {
change.AddWord("foo" + base::Uint64ToString(i));
change2.AddWord("bar" + base::Uint64ToString(i));
}
Apply(*custom_dictionary, change);
Apply(*custom_dictionary2, change2);
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1,
custom_dictionary->GetWords().size());
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1,
custom_dictionary2->GetWords().size());
int error_counter = 0;
EXPECT_FALSE(
custom_dictionary->MergeDataAndStartSyncing(
syncer::DICTIONARY,
GetAllSyncDataNoLimit(custom_dictionary2),
scoped_ptr<syncer::SyncChangeProcessor>(
new syncer::SyncChangeProcessorWrapperForTest(
custom_dictionary2)),
scoped_ptr<syncer::SyncErrorFactory>(
new SyncErrorFactoryStub(&error_counter)))
.error()
.IsSet());
EXPECT_EQ(0, error_counter);
EXPECT_FALSE(custom_dictionary->IsSyncing());
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS * 2 + 2,
custom_dictionary->GetWords().size());
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1,
custom_dictionary2->GetWords().size());
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
custom_dictionary->GetAllSyncData(syncer::DICTIONARY).size());
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
custom_dictionary2->GetAllSyncData(syncer::DICTIONARY).size());
}
TEST_F(SpellcheckCustomDictionaryTest, DictionaryTooBigToStartSyncing) {
SpellcheckService* spellcheck_service =
SpellcheckServiceFactory::GetForContext(&profile_);
SpellcheckCustomDictionary* custom_dictionary =
spellcheck_service->GetCustomDictionary();
TestingProfile profile2;
SpellcheckService* spellcheck_service2 =
static_cast<SpellcheckService*>(
SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
&profile2, &BuildSpellcheckService));
SpellcheckCustomDictionary* custom_dictionary2 =
spellcheck_service2->GetCustomDictionary();
SpellcheckCustomDictionary::Change change;
for (size_t i = 0;
i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS - 1;
++i) {
change.AddWord("foo" + base::Uint64ToString(i));
}
Apply(*custom_dictionary, change);
custom_dictionary2->AddWord("bar");
custom_dictionary2->AddWord("baz");
int error_counter = 0;
EXPECT_FALSE(
custom_dictionary->MergeDataAndStartSyncing(
syncer::DICTIONARY,
custom_dictionary2->GetAllSyncData(
syncer::DICTIONARY),
scoped_ptr<syncer::SyncChangeProcessor>(
new syncer::SyncChangeProcessorWrapperForTest(
custom_dictionary2)),
scoped_ptr<syncer::SyncErrorFactory>(
new SyncErrorFactoryStub(&error_counter)))
.error()
.IsSet());
EXPECT_EQ(0, error_counter);
EXPECT_FALSE(custom_dictionary->IsSyncing());
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1,
custom_dictionary->GetWords().size());
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
custom_dictionary2->GetWords().size());
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
custom_dictionary->GetAllSyncData(syncer::DICTIONARY).size());
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
custom_dictionary2->GetAllSyncData(syncer::DICTIONARY).size());
}
TEST_F(SpellcheckCustomDictionaryTest, DictionaryTooBigToContiueSyncing) {
SpellcheckService* spellcheck_service =
SpellcheckServiceFactory::GetForContext(&profile_);
SpellcheckCustomDictionary* custom_dictionary =
spellcheck_service->GetCustomDictionary();
TestingProfile profile2;
SpellcheckService* spellcheck_service2 =
static_cast<SpellcheckService*>(
SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
&profile2, &BuildSpellcheckService));
SpellcheckCustomDictionary* custom_dictionary2 =
spellcheck_service2->GetCustomDictionary();
SpellcheckCustomDictionary::Change change;
for (size_t i = 0;
i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS - 1;
++i) {
change.AddWord("foo" + base::Uint64ToString(i));
}
Apply(*custom_dictionary, change);
int error_counter = 0;
EXPECT_FALSE(
custom_dictionary->MergeDataAndStartSyncing(
syncer::DICTIONARY,
custom_dictionary2->GetAllSyncData(
syncer::DICTIONARY),
scoped_ptr<syncer::SyncChangeProcessor>(
new syncer::SyncChangeProcessorWrapperForTest(
custom_dictionary2)),
scoped_ptr<syncer::SyncErrorFactory>(
new SyncErrorFactoryStub(&error_counter)))
.error()
.IsSet());
EXPECT_EQ(0, error_counter);
EXPECT_TRUE(custom_dictionary->IsSyncing());
custom_dictionary->AddWord("bar");
EXPECT_EQ(0, error_counter);
EXPECT_TRUE(custom_dictionary->IsSyncing());
custom_dictionary->AddWord("baz");
EXPECT_EQ(0, error_counter);
EXPECT_FALSE(custom_dictionary->IsSyncing());
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1,
custom_dictionary->GetWords().size());
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
custom_dictionary2->GetWords().size());
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
custom_dictionary->GetAllSyncData(syncer::DICTIONARY).size());
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
custom_dictionary2->GetAllSyncData(syncer::DICTIONARY).size());
}
TEST_F(SpellcheckCustomDictionaryTest, LoadAfterSyncStart) {
SpellcheckService* spellcheck_service =
SpellcheckServiceFactory::GetForContext(&profile_);
SpellcheckCustomDictionary* custom_dictionary =
spellcheck_service->GetCustomDictionary();
TestingProfile profile2;
SpellcheckService* spellcheck_service2 =
static_cast<SpellcheckService*>(
SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
&profile2, &BuildSpellcheckService));
SpellcheckCustomDictionary* custom_dictionary2 =
spellcheck_service2->GetCustomDictionary();
custom_dictionary->AddWord("foo");
int error_counter = 0;
EXPECT_FALSE(
custom_dictionary->MergeDataAndStartSyncing(
syncer::DICTIONARY,
custom_dictionary2->GetAllSyncData(
syncer::DICTIONARY),
scoped_ptr<syncer::SyncChangeProcessor>(
new syncer::SyncChangeProcessorWrapperForTest(
custom_dictionary2)),
scoped_ptr<syncer::SyncErrorFactory>(
new SyncErrorFactoryStub(&error_counter)))
.error()
.IsSet());
EXPECT_EQ(0, error_counter);
EXPECT_TRUE(custom_dictionary->IsSyncing());
WordList custom_words;
custom_words.push_back("bar");
OnLoaded(*custom_dictionary, custom_words);
EXPECT_TRUE(custom_dictionary->IsSyncing());
EXPECT_EQ(2UL, custom_dictionary->GetWords().size());
EXPECT_EQ(2UL, custom_dictionary2->GetWords().size());
EXPECT_EQ(2UL, custom_dictionary->GetAllSyncData(syncer::DICTIONARY).size());
EXPECT_EQ(2UL, custom_dictionary2->GetAllSyncData(syncer::DICTIONARY).size());
}
TEST_F(SpellcheckCustomDictionaryTest, LoadAfterSyncStartTooBigToSync) {
SpellcheckService* spellcheck_service =
SpellcheckServiceFactory::GetForContext(&profile_);
SpellcheckCustomDictionary* custom_dictionary =
spellcheck_service->GetCustomDictionary();
TestingProfile profile2;
SpellcheckService* spellcheck_service2 =
static_cast<SpellcheckService*>(
SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
&profile2, &BuildSpellcheckService));
SpellcheckCustomDictionary* custom_dictionary2 =
spellcheck_service2->GetCustomDictionary();
custom_dictionary->AddWord("foo");
int error_counter = 0;
EXPECT_FALSE(
custom_dictionary->MergeDataAndStartSyncing(
syncer::DICTIONARY,
custom_dictionary2->GetAllSyncData(
syncer::DICTIONARY),
scoped_ptr<syncer::SyncChangeProcessor>(
new syncer::SyncChangeProcessorWrapperForTest(
custom_dictionary2)),
scoped_ptr<syncer::SyncErrorFactory>(
new SyncErrorFactoryStub(&error_counter)))
.error()
.IsSet());
EXPECT_EQ(0, error_counter);
EXPECT_TRUE(custom_dictionary->IsSyncing());
WordList custom_words;
for (size_t i = 0;
i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS;
++i) {
custom_words.push_back("foo" + base::Uint64ToString(i));
}
OnLoaded(*custom_dictionary, custom_words);
EXPECT_EQ(0, error_counter);
EXPECT_FALSE(custom_dictionary->IsSyncing());
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1,
custom_dictionary->GetWords().size());
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
custom_dictionary2->GetWords().size());
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
custom_dictionary->GetAllSyncData(syncer::DICTIONARY).size());
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
custom_dictionary2->GetAllSyncData(syncer::DICTIONARY).size());
}
TEST_F(SpellcheckCustomDictionaryTest, LoadDuplicatesAfterSync) {
SpellcheckService* spellcheck_service =
SpellcheckServiceFactory::GetForContext(&profile_);
SpellcheckCustomDictionary* custom_dictionary =
spellcheck_service->GetCustomDictionary();
TestingProfile profile2;
SpellcheckService* spellcheck_service2 =
static_cast<SpellcheckService*>(
SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
&profile2, &BuildSpellcheckService));
SpellcheckCustomDictionary* custom_dictionary2 =
spellcheck_service2->GetCustomDictionary();
WordList to_add;
for (size_t i = 0;
i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS / 2;
++i) {
to_add.push_back("foo" + base::Uint64ToString(i));
}
Apply(*custom_dictionary, SpellcheckCustomDictionary::Change(to_add));
int error_counter = 0;
EXPECT_FALSE(
custom_dictionary->MergeDataAndStartSyncing(
syncer::DICTIONARY,
custom_dictionary2->GetAllSyncData(
syncer::DICTIONARY),
scoped_ptr<syncer::SyncChangeProcessor>(
new syncer::SyncChangeProcessorWrapperForTest(
custom_dictionary2)),
scoped_ptr<syncer::SyncErrorFactory>(
new SyncErrorFactoryStub(&error_counter)))
.error()
.IsSet());
EXPECT_EQ(0, error_counter);
EXPECT_TRUE(custom_dictionary->IsSyncing());
OnLoaded(*custom_dictionary, to_add);
EXPECT_EQ(0, error_counter);
EXPECT_TRUE(custom_dictionary->IsSyncing());
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS / 2,
custom_dictionary->GetWords().size());
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS / 2,
custom_dictionary2->GetWords().size());
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS / 2,
custom_dictionary->GetAllSyncData(syncer::DICTIONARY).size());
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS / 2,
custom_dictionary2->GetAllSyncData(syncer::DICTIONARY).size());
}
TEST_F(SpellcheckCustomDictionaryTest, DictionaryLoadNotification) {
SpellcheckService* spellcheck_service =
SpellcheckServiceFactory::GetForContext(&profile_);
SpellcheckCustomDictionary* custom_dictionary =
spellcheck_service->GetCustomDictionary();
DictionaryObserverCounter observer;
custom_dictionary->AddObserver(&observer);
WordList custom_words;
custom_words.push_back("foo");
custom_words.push_back("bar");
OnLoaded(*custom_dictionary, custom_words);
EXPECT_GE(observer.loads(), 1);
EXPECT_LE(observer.loads(), 2);
EXPECT_EQ(0, observer.changes());
custom_dictionary->RemoveObserver(&observer);
}
TEST_F(SpellcheckCustomDictionaryTest, DictionaryAddWordNotification) {
SpellcheckService* spellcheck_service =
SpellcheckServiceFactory::GetForContext(&profile_);
SpellcheckCustomDictionary* custom_dictionary =
spellcheck_service->GetCustomDictionary();
OnLoaded(*custom_dictionary, WordList());
DictionaryObserverCounter observer;
custom_dictionary->AddObserver(&observer);
EXPECT_TRUE(custom_dictionary->AddWord("foo"));
EXPECT_TRUE(custom_dictionary->AddWord("bar"));
EXPECT_FALSE(custom_dictionary->AddWord("bar"));
EXPECT_EQ(2, observer.changes());
custom_dictionary->RemoveObserver(&observer);
}
TEST_F(SpellcheckCustomDictionaryTest, DictionaryRemoveWordNotification) {
SpellcheckService* spellcheck_service =
SpellcheckServiceFactory::GetForContext(&profile_);
SpellcheckCustomDictionary* custom_dictionary =
spellcheck_service->GetCustomDictionary();
OnLoaded(*custom_dictionary, WordList());
EXPECT_TRUE(custom_dictionary->AddWord("foo"));
EXPECT_TRUE(custom_dictionary->AddWord("bar"));
DictionaryObserverCounter observer;
custom_dictionary->AddObserver(&observer);
EXPECT_TRUE(custom_dictionary->RemoveWord("foo"));
EXPECT_TRUE(custom_dictionary->RemoveWord("bar"));
EXPECT_FALSE(custom_dictionary->RemoveWord("baz"));
EXPECT_EQ(2, observer.changes());
custom_dictionary->RemoveObserver(&observer);
}
TEST_F(SpellcheckCustomDictionaryTest, DictionarySyncNotification) {
SpellcheckService* spellcheck_service =
SpellcheckServiceFactory::GetForContext(&profile_);
SpellcheckCustomDictionary* custom_dictionary =
spellcheck_service->GetCustomDictionary();
TestingProfile profile2;
SpellcheckService* spellcheck_service2 =
static_cast<SpellcheckService*>(
SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
&profile2, &BuildSpellcheckService));
SpellcheckCustomDictionary* custom_dictionary2 =
spellcheck_service2->GetCustomDictionary();
OnLoaded(*custom_dictionary, WordList());
OnLoaded(*custom_dictionary2, WordList());
custom_dictionary->AddWord("foo");
custom_dictionary->AddWord("bar");
custom_dictionary2->AddWord("foo");
custom_dictionary2->AddWord("baz");
DictionaryObserverCounter observer;
custom_dictionary->AddObserver(&observer);
DictionaryObserverCounter observer2;
custom_dictionary2->AddObserver(&observer2);
int error_counter = 0;
EXPECT_FALSE(
custom_dictionary->MergeDataAndStartSyncing(
syncer::DICTIONARY,
custom_dictionary2->GetAllSyncData(
syncer::DICTIONARY),
scoped_ptr<syncer::SyncChangeProcessor>(
new syncer::SyncChangeProcessorWrapperForTest(
custom_dictionary2)),
scoped_ptr<syncer::SyncErrorFactory>(
new SyncErrorFactoryStub(&error_counter)))
.error()
.IsSet());
EXPECT_EQ(0, error_counter);
EXPECT_TRUE(custom_dictionary->IsSyncing());
EXPECT_EQ(1, observer.changes());
EXPECT_EQ(1, observer2.changes());
custom_dictionary->RemoveObserver(&observer);
custom_dictionary2->RemoveObserver(&observer2);
}
TEST_F(SpellcheckCustomDictionaryTest, DictionarySyncLimit) {
TestingProfile server_profile;
SpellcheckService* server_spellcheck_service =
static_cast<SpellcheckService*>(
SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
&server_profile, &BuildSpellcheckService));
SpellcheckCustomDictionary* server_custom_dictionary =
server_spellcheck_service->GetCustomDictionary();
{
SpellcheckService* spellcheck_service =
SpellcheckServiceFactory::GetForContext(&profile_);
SpellcheckCustomDictionary* custom_dictionary =
spellcheck_service->GetCustomDictionary();
SpellcheckCustomDictionary::Change change;
for (size_t i = 0;
i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS;
++i) {
change.AddWord("foo" + base::Uint64ToString(i));
}
Apply(*custom_dictionary, change);
int error_counter = 0;
EXPECT_FALSE(
custom_dictionary
->MergeDataAndStartSyncing(
syncer::DICTIONARY,
server_custom_dictionary->GetAllSyncData(syncer::DICTIONARY),
scoped_ptr<syncer::SyncChangeProcessor>(
new syncer::SyncChangeProcessorWrapperForTest(
server_custom_dictionary)),
scoped_ptr<syncer::SyncErrorFactory>(
new SyncErrorFactoryStub(&error_counter)))
.error()
.IsSet());
EXPECT_EQ(0, error_counter);
EXPECT_TRUE(custom_dictionary->IsSyncing());
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
custom_dictionary->GetWords().size());
}
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
server_custom_dictionary->GetWords().size());
{
TestingProfile client_profile;
SpellcheckService* client_spellcheck_service =
static_cast<SpellcheckService*>(
SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
&client_profile, &BuildSpellcheckService));
SpellcheckCustomDictionary* client_custom_dictionary =
client_spellcheck_service->GetCustomDictionary();
SpellcheckCustomDictionary::Change change;
for (size_t i = 0;
i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS;
++i) {
change.AddWord("bar" + base::Uint64ToString(i));
}
Apply(*client_custom_dictionary, change);
int error_counter = 0;
EXPECT_FALSE(
client_custom_dictionary
->MergeDataAndStartSyncing(
syncer::DICTIONARY,
server_custom_dictionary->GetAllSyncData(syncer::DICTIONARY),
scoped_ptr<syncer::SyncChangeProcessor>(
new syncer::SyncChangeProcessorWrapperForTest(
server_custom_dictionary)),
scoped_ptr<syncer::SyncErrorFactory>(
new SyncErrorFactoryStub(&error_counter)))
.error()
.IsSet());
EXPECT_EQ(0, error_counter);
EXPECT_FALSE(client_custom_dictionary->IsSyncing());
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS * 2,
client_custom_dictionary->GetWords().size());
}
EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
server_custom_dictionary->GetWords().size());
}
TEST_F(SpellcheckCustomDictionaryTest, RecordSizeStatsCorrectly) {
#if defined(OS_WIN)
if (base::win::GetVersion() >= base::win::VERSION_VISTA)
return;
#endif
SpellCheckHostMetrics::RecordCustomWordCountStats(123);
EXPECT_TRUE(StatisticsRecorder::IsActive());
HistogramBase* histogram =
StatisticsRecorder::FindHistogram("SpellCheck.CustomWords");
ASSERT_TRUE(histogram != NULL);
scoped_ptr<HistogramSamples> baseline = histogram->SnapshotSamples();
base::FilePath path =
profile_.GetPath().Append(chrome::kCustomDictionaryFileName);
WordList loaded_custom_words = LoadDictionaryFile(path);
EXPECT_EQ(0u, loaded_custom_words.size());
histogram =
StatisticsRecorder::FindHistogram("SpellCheck.CustomWords");
ASSERT_TRUE(histogram != NULL);
scoped_ptr<HistogramSamples> samples = histogram->SnapshotSamples();
samples->Subtract(*baseline);
EXPECT_EQ(0,samples->sum());
SpellcheckCustomDictionary::Change change;
change.AddWord("bar");
change.AddWord("foo");
UpdateDictionaryFile(change, path);
loaded_custom_words = LoadDictionaryFile(path);
EXPECT_EQ(2u, loaded_custom_words.size());
histogram =
StatisticsRecorder::FindHistogram("SpellCheck.CustomWords");
ASSERT_TRUE(histogram != NULL);
scoped_ptr<HistogramSamples> samples2 = histogram->SnapshotSamples();
samples2->Subtract(*baseline);
EXPECT_EQ(2,samples2->sum());
}
TEST_F(SpellcheckCustomDictionaryTest, HasWord) {
SpellcheckService* spellcheck_service =
SpellcheckServiceFactory::GetForContext(&profile_);
SpellcheckCustomDictionary* custom_dictionary =
spellcheck_service->GetCustomDictionary();
OnLoaded(*custom_dictionary, WordList());
EXPECT_FALSE(custom_dictionary->HasWord("foo"));
EXPECT_FALSE(custom_dictionary->HasWord("bar"));
custom_dictionary->AddWord("foo");
EXPECT_TRUE(custom_dictionary->HasWord("foo"));
EXPECT_FALSE(custom_dictionary->HasWord("bar"));
}