Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / spellchecker / spellcheck_custom_dictionary_unittest.cc
blobdbd4da5a77cc333d3aaa61ab4b4b888f387024c5
1 // Copyright (c) 2012 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.
5 #include "chrome/browser/spellchecker/spellcheck_custom_dictionary.h"
7 #include <vector>
9 #include "base/files/file_util.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/metrics/histogram_samples.h"
12 #include "base/metrics/statistics_recorder.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "chrome/browser/spellchecker/spellcheck_factory.h"
15 #include "chrome/browser/spellchecker/spellcheck_host_metrics.h"
16 #include "chrome/browser/spellchecker/spellcheck_service.h"
17 #include "chrome/common/chrome_constants.h"
18 #include "chrome/common/spellcheck_common.h"
19 #include "chrome/test/base/testing_profile.h"
20 #include "content/public/test/test_browser_thread_bundle.h"
21 #include "net/url_request/test_url_fetcher_factory.h"
22 #include "sync/api/sync_change.h"
23 #include "sync/api/sync_change_processor_wrapper_for_test.h"
24 #include "sync/api/sync_data.h"
25 #include "sync/api/sync_error_factory.h"
26 #include "sync/api/sync_error_factory_mock.h"
27 #include "sync/protocol/sync.pb.h"
28 #include "testing/gmock/include/gmock/gmock.h"
29 #include "testing/gtest/include/gtest/gtest.h"
31 #if defined(OS_WIN)
32 // For version specific disabled tests below (http://crbug.com/230534).
33 #include "base/win/windows_version.h"
34 #endif
36 using base::HistogramBase;
37 using base::HistogramSamples;
38 using base::StatisticsRecorder;
40 namespace {
42 // Get all sync data for the custom dictionary without limiting to maximum
43 // number of syncable words.
44 syncer::SyncDataList GetAllSyncDataNoLimit(
45 const SpellcheckCustomDictionary* dictionary) {
46 syncer::SyncDataList data;
47 for (const std::string& word : dictionary->GetWords()) {
48 sync_pb::EntitySpecifics specifics;
49 specifics.mutable_dictionary()->set_word(word);
50 data.push_back(syncer::SyncData::CreateLocalData(word, word, specifics));
52 return data;
55 } // namespace
57 static scoped_ptr<KeyedService> BuildSpellcheckService(
58 content::BrowserContext* profile) {
59 return make_scoped_ptr(new SpellcheckService(static_cast<Profile*>(profile)));
62 class SpellcheckCustomDictionaryTest : public testing::Test {
63 protected:
64 void SetUp() override {
65 // Use SetTestingFactoryAndUse to force creation and initialization.
66 SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
67 &profile_, &BuildSpellcheckService);
69 StatisticsRecorder::Initialize();
72 // A wrapper around SpellcheckCustomDictionary::LoadDictionaryFile private
73 // function to avoid a large number of FRIEND_TEST declarations in
74 // SpellcheckCustomDictionary.
75 scoped_ptr<std::set<std::string>> LoadDictionaryFile(
76 const base::FilePath& path) {
77 return SpellcheckCustomDictionary::LoadDictionaryFile(path);
80 // A wrapper around SpellcheckCustomDictionary::UpdateDictionaryFile private
81 // function to avoid a large number of FRIEND_TEST declarations in
82 // SpellcheckCustomDictionary.
83 void UpdateDictionaryFile(
84 scoped_ptr<SpellcheckCustomDictionary::Change> dictionary_change,
85 const base::FilePath& path) {
86 SpellcheckCustomDictionary::UpdateDictionaryFile(dictionary_change.Pass(),
87 path);
90 // A wrapper around SpellcheckCustomDictionary::OnLoaded private method to
91 // avoid a large number of FRIEND_TEST declarations in
92 // SpellcheckCustomDictionary.
93 void OnLoaded(SpellcheckCustomDictionary& dictionary,
94 scoped_ptr<std::set<std::string>> custom_words) {
95 dictionary.OnLoaded(custom_words.Pass());
98 // A wrapper around SpellcheckCustomDictionary::Apply private method to avoid
99 // a large number of FRIEND_TEST declarations in SpellcheckCustomDictionary.
100 void Apply(
101 SpellcheckCustomDictionary& dictionary,
102 const SpellcheckCustomDictionary::Change& change) {
103 return dictionary.Apply(change);
106 content::TestBrowserThreadBundle thread_bundle_;
108 TestingProfile profile_;
109 net::TestURLFetcherFactory fetcher_factory_;
112 // An implementation of SyncErrorFactory that does not upload the error message
113 // and updates an outside error counter. This lets us know the number of error
114 // messages in an instance of this class after that instance is deleted.
115 class SyncErrorFactoryStub : public syncer::SyncErrorFactory {
116 public:
117 explicit SyncErrorFactoryStub(int* error_counter)
118 : error_counter_(error_counter) {}
119 ~SyncErrorFactoryStub() override {}
121 // Overridden from syncer::SyncErrorFactory:
122 syncer::SyncError CreateAndUploadError(
123 const tracked_objects::Location& location,
124 const std::string& message) override {
125 (*error_counter_)++;
126 return syncer::SyncError(location,
127 syncer::SyncError::DATATYPE_ERROR,
128 message,
129 syncer::DICTIONARY);
132 private:
133 int* error_counter_;
134 DISALLOW_COPY_AND_ASSIGN(SyncErrorFactoryStub);
137 // Counts the number of notifications for dictionary load and change.
138 class DictionaryObserverCounter : public SpellcheckCustomDictionary::Observer {
139 public:
140 DictionaryObserverCounter() : loads_(0), changes_(0) {}
141 virtual ~DictionaryObserverCounter() {}
143 int loads() const { return loads_; }
144 int changes() const { return changes_; }
146 // Overridden from SpellcheckCustomDictionary::Observer:
147 void OnCustomDictionaryLoaded() override { loads_++; }
148 void OnCustomDictionaryChanged(
149 const SpellcheckCustomDictionary::Change& change) override {
150 changes_++;
153 private:
154 int loads_;
155 int changes_;
156 DISALLOW_COPY_AND_ASSIGN(DictionaryObserverCounter);
159 TEST_F(SpellcheckCustomDictionaryTest, SaveAndLoad) {
160 base::FilePath path =
161 profile_.GetPath().Append(chrome::kCustomDictionaryFileName);
163 // The custom word list should be empty now.
164 EXPECT_TRUE(LoadDictionaryFile(path)->empty());
166 scoped_ptr<SpellcheckCustomDictionary::Change> change(
167 new SpellcheckCustomDictionary::Change);
168 change->AddWord("bar");
169 change->AddWord("foo");
171 UpdateDictionaryFile(change.Pass(), path);
172 std::set<std::string> expected;
173 expected.insert("bar");
174 expected.insert("foo");
176 // The custom word list should include written words.
177 EXPECT_EQ(expected, *LoadDictionaryFile(path));
179 scoped_ptr<SpellcheckCustomDictionary::Change> change2(
180 new SpellcheckCustomDictionary::Change);
181 change2->RemoveWord("bar");
182 change2->RemoveWord("foo");
183 UpdateDictionaryFile(change2.Pass(), path);
184 EXPECT_TRUE(LoadDictionaryFile(path)->empty());
187 TEST_F(SpellcheckCustomDictionaryTest, MultiProfile) {
188 SpellcheckService* spellcheck_service =
189 SpellcheckServiceFactory::GetForContext(&profile_);
190 SpellcheckCustomDictionary* custom_dictionary =
191 spellcheck_service->GetCustomDictionary();
192 TestingProfile profile2;
193 SpellcheckService* spellcheck_service2 =
194 static_cast<SpellcheckService*>(
195 SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
196 &profile2, &BuildSpellcheckService));
197 SpellcheckCustomDictionary* custom_dictionary2 =
198 spellcheck_service2->GetCustomDictionary();
200 std::set<std::string> expected1;
201 std::set<std::string> expected2;
203 custom_dictionary->AddWord("foo");
204 custom_dictionary->AddWord("bar");
205 expected1.insert("foo");
206 expected1.insert("bar");
208 custom_dictionary2->AddWord("hoge");
209 custom_dictionary2->AddWord("fuga");
210 expected2.insert("hoge");
211 expected2.insert("fuga");
213 std::set<std::string> actual1 = custom_dictionary->GetWords();
214 EXPECT_EQ(actual1, expected1);
216 std::set<std::string> actual2 = custom_dictionary2->GetWords();
217 EXPECT_EQ(actual2, expected2);
220 // Legacy empty dictionary should be converted to new format empty dictionary.
221 TEST_F(SpellcheckCustomDictionaryTest, LegacyEmptyDictionaryShouldBeConverted) {
222 base::FilePath path =
223 profile_.GetPath().Append(chrome::kCustomDictionaryFileName);
225 std::string content;
226 base::WriteFile(path, content.c_str(), content.length());
227 EXPECT_TRUE(LoadDictionaryFile(path)->empty());
230 // Legacy dictionary with two words should be converted to new format dictionary
231 // with two words.
232 TEST_F(SpellcheckCustomDictionaryTest,
233 LegacyDictionaryWithTwoWordsShouldBeConverted) {
234 base::FilePath path =
235 profile_.GetPath().Append(chrome::kCustomDictionaryFileName);
237 std::string content = "foo\nbar\nfoo\n";
238 base::WriteFile(path, content.c_str(), content.length());
239 std::set<std::string> expected;
240 expected.insert("bar");
241 expected.insert("foo");
242 EXPECT_EQ(expected, *LoadDictionaryFile(path));
245 // Illegal words should be removed. Leading and trailing whitespace should be
246 // trimmed.
247 TEST_F(SpellcheckCustomDictionaryTest,
248 IllegalWordsShouldBeRemovedFromDictionary) {
249 base::FilePath path =
250 profile_.GetPath().Append(chrome::kCustomDictionaryFileName);
252 std::string content = "foo\n foo bar \n\n \nbar\n"
253 "01234567890123456789012345678901234567890123456789"
254 "01234567890123456789012345678901234567890123456789";
255 base::WriteFile(path, content.c_str(), content.length());
256 std::set<std::string> expected;
257 expected.insert("bar");
258 expected.insert("foo");
259 expected.insert("foo bar");
260 EXPECT_EQ(expected, *LoadDictionaryFile(path));
263 // Write to dictionary should backup previous version and write the word to the
264 // end of the dictionary. If the dictionary file is corrupted on disk, the
265 // previous version should be reloaded.
266 TEST_F(SpellcheckCustomDictionaryTest, CorruptedWriteShouldBeRecovered) {
267 base::FilePath path =
268 profile_.GetPath().Append(chrome::kCustomDictionaryFileName);
270 std::string content = "foo\nbar";
271 base::WriteFile(path, content.c_str(), content.length());
272 std::set<std::string> expected;
273 expected.insert("bar");
274 expected.insert("foo");
275 EXPECT_EQ(expected, *LoadDictionaryFile(path));
277 scoped_ptr<SpellcheckCustomDictionary::Change> change(
278 new SpellcheckCustomDictionary::Change);
279 change->AddWord("baz");
280 UpdateDictionaryFile(change.Pass(), path);
281 content.clear();
282 base::ReadFileToString(path, &content);
283 content.append("corruption");
284 base::WriteFile(path, content.c_str(), content.length());
285 EXPECT_EQ(expected, *LoadDictionaryFile(path));
288 TEST_F(SpellcheckCustomDictionaryTest,
289 GetAllSyncDataAccuratelyReflectsDictionaryState) {
290 SpellcheckCustomDictionary* dictionary =
291 SpellcheckServiceFactory::GetForContext(
292 &profile_)->GetCustomDictionary();
294 syncer::SyncDataList data = dictionary->GetAllSyncData(syncer::DICTIONARY);
295 EXPECT_TRUE(data.empty());
297 EXPECT_TRUE(dictionary->AddWord("bar"));
298 EXPECT_TRUE(dictionary->AddWord("foo"));
300 data = dictionary->GetAllSyncData(syncer::DICTIONARY);
301 EXPECT_EQ(2UL, data.size());
302 std::vector<std::string> words;
303 words.push_back("bar");
304 words.push_back("foo");
305 for (size_t i = 0; i < data.size(); i++) {
306 EXPECT_TRUE(data[i].GetSpecifics().has_dictionary());
307 EXPECT_EQ(syncer::DICTIONARY, data[i].GetDataType());
308 EXPECT_EQ(words[i], syncer::SyncDataLocal(data[i]).GetTag());
309 EXPECT_EQ(words[i], data[i].GetSpecifics().dictionary().word());
312 EXPECT_TRUE(dictionary->RemoveWord("bar"));
313 EXPECT_TRUE(dictionary->RemoveWord("foo"));
315 data = dictionary->GetAllSyncData(syncer::DICTIONARY);
316 EXPECT_TRUE(data.empty());
319 TEST_F(SpellcheckCustomDictionaryTest, GetAllSyncDataHasLimit) {
320 SpellcheckCustomDictionary* dictionary =
321 SpellcheckServiceFactory::GetForContext(
322 &profile_)->GetCustomDictionary();
324 SpellcheckCustomDictionary::Change change;
325 for (size_t i = 0;
326 i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS - 1;
327 i++) {
328 change.AddWord("foo" + base::Uint64ToString(i));
330 Apply(*dictionary, change);
331 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS - 1,
332 dictionary->GetWords().size());
333 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS - 1,
334 dictionary->GetAllSyncData(syncer::DICTIONARY).size());
336 dictionary->AddWord("baz");
337 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
338 dictionary->GetWords().size());
339 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
340 dictionary->GetAllSyncData(syncer::DICTIONARY).size());
342 dictionary->AddWord("bar");
343 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1,
344 dictionary->GetWords().size());
345 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
346 dictionary->GetAllSyncData(syncer::DICTIONARY).size());
348 dictionary->AddWord("snafoo");
349 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 2,
350 dictionary->GetWords().size());
351 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
352 dictionary->GetAllSyncData(syncer::DICTIONARY).size());
355 TEST_F(SpellcheckCustomDictionaryTest, ProcessSyncChanges) {
356 SpellcheckService* spellcheck_service =
357 SpellcheckServiceFactory::GetForContext(&profile_);
358 SpellcheckCustomDictionary* dictionary =
359 spellcheck_service->GetCustomDictionary();
361 dictionary->AddWord("foo");
362 dictionary->AddWord("bar");
364 syncer::SyncChangeList changes;
366 // Add existing word.
367 std::string word = "foo";
368 sync_pb::EntitySpecifics specifics;
369 specifics.mutable_dictionary()->set_word(word);
370 changes.push_back(syncer::SyncChange(
371 FROM_HERE,
372 syncer::SyncChange::ACTION_ADD,
373 syncer::SyncData::CreateLocalData(word, word, specifics)));
376 // Add invalid word. This word is too long.
377 std::string word = "01234567890123456789012345678901234567890123456789"
378 "01234567890123456789012345678901234567890123456789";
379 sync_pb::EntitySpecifics specifics;
380 specifics.mutable_dictionary()->set_word(word);
381 changes.push_back(syncer::SyncChange(
382 FROM_HERE,
383 syncer::SyncChange::ACTION_ADD,
384 syncer::SyncData::CreateLocalData(word, word, specifics)));
387 // Add valid word.
388 std::string word = "baz";
389 sync_pb::EntitySpecifics specifics;
390 specifics.mutable_dictionary()->set_word(word);
391 changes.push_back(syncer::SyncChange(
392 FROM_HERE,
393 syncer::SyncChange::ACTION_ADD,
394 syncer::SyncData::CreateLocalData(word, word, specifics)));
397 // Remove missing word.
398 std::string word = "snafoo";
399 sync_pb::EntitySpecifics specifics;
400 specifics.mutable_dictionary()->set_word(word);
401 changes.push_back(syncer::SyncChange(
402 FROM_HERE,
403 syncer::SyncChange::ACTION_DELETE,
404 syncer::SyncData::CreateLocalData(word, word, specifics)));
407 // Remove existing word.
408 std::string word = "bar";
409 sync_pb::EntitySpecifics specifics;
410 specifics.mutable_dictionary()->set_word(word);
411 changes.push_back(syncer::SyncChange(
412 FROM_HERE,
413 syncer::SyncChange::ACTION_DELETE,
414 syncer::SyncData::CreateLocalData(word, word, specifics)));
417 EXPECT_FALSE(dictionary->ProcessSyncChanges(FROM_HERE, changes).IsSet());
419 const std::set<std::string>& words = dictionary->GetWords();
420 EXPECT_EQ(2UL, words.size());
421 EXPECT_EQ(0UL, words.count("bar"));
422 EXPECT_EQ(1UL, words.count("foo"));
423 EXPECT_EQ(1UL, words.count("baz"));
426 TEST_F(SpellcheckCustomDictionaryTest, MergeDataAndStartSyncing) {
427 SpellcheckService* spellcheck_service =
428 SpellcheckServiceFactory::GetForContext(&profile_);
429 SpellcheckCustomDictionary* custom_dictionary =
430 spellcheck_service->GetCustomDictionary();
431 TestingProfile profile2;
432 SpellcheckService* spellcheck_service2 =
433 static_cast<SpellcheckService*>(
434 SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
435 &profile2, &BuildSpellcheckService));
436 SpellcheckCustomDictionary* custom_dictionary2 =
437 spellcheck_service2->GetCustomDictionary();
439 SpellcheckCustomDictionary::Change change;
440 for (size_t i = 0;
441 i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS / 2;
442 ++i) {
443 change.AddWord("foo" + base::Uint64ToString(i));
445 Apply(*custom_dictionary, change);
447 SpellcheckCustomDictionary::Change change2;
448 for (size_t i = 0;
449 i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS / 2;
450 ++i) {
451 change2.AddWord("bar" + base::Uint64ToString(i));
453 Apply(*custom_dictionary2, change2);
455 int error_counter = 0;
456 EXPECT_FALSE(
457 custom_dictionary->MergeDataAndStartSyncing(
458 syncer::DICTIONARY,
459 custom_dictionary2->GetAllSyncData(
460 syncer::DICTIONARY),
461 scoped_ptr<syncer::SyncChangeProcessor>(
462 new syncer::SyncChangeProcessorWrapperForTest(
463 custom_dictionary2)),
464 scoped_ptr<syncer::SyncErrorFactory>(
465 new SyncErrorFactoryStub(&error_counter)))
466 .error()
467 .IsSet());
468 EXPECT_EQ(0, error_counter);
469 EXPECT_TRUE(custom_dictionary->IsSyncing());
471 std::set<std::string> words = custom_dictionary->GetWords();
472 std::set<std::string> words2 = custom_dictionary2->GetWords();
473 EXPECT_EQ(words.size(), words2.size());
474 EXPECT_EQ(words, words2);
477 TEST_F(SpellcheckCustomDictionaryTest, SyncBeforeLoadDoesNotDuplicateWords) {
478 SpellcheckCustomDictionary* custom_dictionary =
479 SpellcheckServiceFactory::GetForContext(&profile_)->GetCustomDictionary();
481 TestingProfile profile2;
482 SpellcheckCustomDictionary* custom_dictionary2 =
483 static_cast<SpellcheckService*>(
484 SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
485 &profile2, &BuildSpellcheckService))
486 ->GetCustomDictionary();
488 scoped_ptr<SpellcheckCustomDictionary::Change> change(
489 new SpellcheckCustomDictionary::Change);
490 change->AddWord("foo");
491 Apply(*custom_dictionary2, *change);
493 base::FilePath path =
494 profile_.GetPath().Append(chrome::kCustomDictionaryFileName);
495 UpdateDictionaryFile(change.Pass(), path);
496 EXPECT_TRUE(custom_dictionary->GetWords().empty());
498 int error_counter = 0;
499 EXPECT_FALSE(
500 custom_dictionary->MergeDataAndStartSyncing(
501 syncer::DICTIONARY,
502 custom_dictionary2->GetAllSyncData(
503 syncer::DICTIONARY),
504 scoped_ptr<syncer::SyncChangeProcessor>(
505 new syncer::SyncChangeProcessorWrapperForTest(
506 custom_dictionary2)),
507 scoped_ptr<syncer::SyncErrorFactory>(
508 new SyncErrorFactoryStub(&error_counter)))
509 .error()
510 .IsSet());
511 EXPECT_EQ(0, error_counter);
512 EXPECT_TRUE(custom_dictionary->IsSyncing());
514 std::set<std::string> expected_words_in_memory;
515 expected_words_in_memory.insert("foo");
516 EXPECT_EQ(expected_words_in_memory, custom_dictionary->GetWords());
518 // Finish all writes to disk.
519 base::MessageLoop::current()->RunUntilIdle();
521 std::string actual_contents_on_disk;
522 base::ReadFileToString(path, &actual_contents_on_disk);
523 static const char kExpectedContentsPrefix[] = "foo\nchecksum_v1 = ";
524 EXPECT_EQ(
525 kExpectedContentsPrefix,
526 actual_contents_on_disk.substr(0, sizeof kExpectedContentsPrefix - 1));
529 TEST_F(SpellcheckCustomDictionaryTest, DictionaryTooBigBeforeSyncing) {
530 SpellcheckService* spellcheck_service =
531 SpellcheckServiceFactory::GetForContext(&profile_);
532 SpellcheckCustomDictionary* custom_dictionary =
533 spellcheck_service->GetCustomDictionary();
534 TestingProfile profile2;
535 SpellcheckService* spellcheck_service2 =
536 static_cast<SpellcheckService*>(
537 SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
538 &profile2, &BuildSpellcheckService));
539 SpellcheckCustomDictionary* custom_dictionary2 =
540 spellcheck_service2->GetCustomDictionary();
542 SpellcheckCustomDictionary::Change change;
543 for (size_t i = 0;
544 i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1;
545 ++i) {
546 change.AddWord("foo" + base::Uint64ToString(i));
548 Apply(*custom_dictionary, change);
550 int error_counter = 0;
551 EXPECT_FALSE(
552 custom_dictionary->MergeDataAndStartSyncing(
553 syncer::DICTIONARY,
554 custom_dictionary2->GetAllSyncData(
555 syncer::DICTIONARY),
556 scoped_ptr<syncer::SyncChangeProcessor>(
557 new syncer::SyncChangeProcessorWrapperForTest(
558 custom_dictionary2)),
559 scoped_ptr<syncer::SyncErrorFactory>(
560 new SyncErrorFactoryStub(&error_counter)))
561 .error()
562 .IsSet());
563 EXPECT_EQ(0, error_counter);
564 EXPECT_FALSE(custom_dictionary->IsSyncing());
566 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1,
567 custom_dictionary->GetWords().size());
568 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
569 custom_dictionary2->GetWords().size());
571 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
572 custom_dictionary->GetAllSyncData(syncer::DICTIONARY).size());
573 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
574 custom_dictionary2->GetAllSyncData(syncer::DICTIONARY).size());
577 TEST_F(SpellcheckCustomDictionaryTest, DictionaryTooBigAndServerFull) {
578 SpellcheckService* spellcheck_service =
579 SpellcheckServiceFactory::GetForContext(&profile_);
580 SpellcheckCustomDictionary* custom_dictionary =
581 spellcheck_service->GetCustomDictionary();
582 TestingProfile profile2;
583 SpellcheckService* spellcheck_service2 =
584 static_cast<SpellcheckService*>(
585 SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
586 &profile2, &BuildSpellcheckService));
587 SpellcheckCustomDictionary* custom_dictionary2 =
588 spellcheck_service2->GetCustomDictionary();
590 SpellcheckCustomDictionary::Change change;
591 SpellcheckCustomDictionary::Change change2;
592 for (size_t i = 0;
593 i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS;
594 ++i) {
595 change.AddWord("foo" + base::Uint64ToString(i));
596 change2.AddWord("bar" + base::Uint64ToString(i));
598 change.AddWord("foo");
599 Apply(*custom_dictionary, change);
600 Apply(*custom_dictionary2, change2);
602 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1,
603 custom_dictionary->GetWords().size());
604 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
605 custom_dictionary2->GetWords().size());
607 int error_counter = 0;
608 EXPECT_FALSE(
609 custom_dictionary->MergeDataAndStartSyncing(
610 syncer::DICTIONARY,
611 custom_dictionary2->GetAllSyncData(
612 syncer::DICTIONARY),
613 scoped_ptr<syncer::SyncChangeProcessor>(
614 new syncer::SyncChangeProcessorWrapperForTest(
615 custom_dictionary2)),
616 scoped_ptr<syncer::SyncErrorFactory>(
617 new SyncErrorFactoryStub(&error_counter)))
618 .error()
619 .IsSet());
620 EXPECT_EQ(0, error_counter);
621 EXPECT_FALSE(custom_dictionary->IsSyncing());
623 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS * 2 + 1,
624 custom_dictionary->GetWords().size());
625 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
626 custom_dictionary2->GetWords().size());
628 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
629 custom_dictionary->GetAllSyncData(syncer::DICTIONARY).size());
630 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
631 custom_dictionary2->GetAllSyncData(syncer::DICTIONARY).size());
634 TEST_F(SpellcheckCustomDictionaryTest, ServerTooBig) {
635 SpellcheckService* spellcheck_service =
636 SpellcheckServiceFactory::GetForContext(&profile_);
637 SpellcheckCustomDictionary* custom_dictionary =
638 spellcheck_service->GetCustomDictionary();
639 TestingProfile profile2;
640 SpellcheckService* spellcheck_service2 =
641 static_cast<SpellcheckService*>(
642 SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
643 &profile2, &BuildSpellcheckService));
644 SpellcheckCustomDictionary* custom_dictionary2 =
645 spellcheck_service2->GetCustomDictionary();
647 SpellcheckCustomDictionary::Change change;
648 SpellcheckCustomDictionary::Change change2;
649 for (size_t i = 0;
650 i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1;
651 ++i) {
652 change.AddWord("foo" + base::Uint64ToString(i));
653 change2.AddWord("bar" + base::Uint64ToString(i));
655 Apply(*custom_dictionary, change);
656 Apply(*custom_dictionary2, change2);
658 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1,
659 custom_dictionary->GetWords().size());
660 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1,
661 custom_dictionary2->GetWords().size());
663 int error_counter = 0;
664 EXPECT_FALSE(
665 custom_dictionary->MergeDataAndStartSyncing(
666 syncer::DICTIONARY,
667 GetAllSyncDataNoLimit(custom_dictionary2),
668 scoped_ptr<syncer::SyncChangeProcessor>(
669 new syncer::SyncChangeProcessorWrapperForTest(
670 custom_dictionary2)),
671 scoped_ptr<syncer::SyncErrorFactory>(
672 new SyncErrorFactoryStub(&error_counter)))
673 .error()
674 .IsSet());
675 EXPECT_EQ(0, error_counter);
676 EXPECT_FALSE(custom_dictionary->IsSyncing());
678 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS * 2 + 2,
679 custom_dictionary->GetWords().size());
680 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1,
681 custom_dictionary2->GetWords().size());
683 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
684 custom_dictionary->GetAllSyncData(syncer::DICTIONARY).size());
685 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
686 custom_dictionary2->GetAllSyncData(syncer::DICTIONARY).size());
689 TEST_F(SpellcheckCustomDictionaryTest, DictionaryTooBigToStartSyncing) {
690 SpellcheckService* spellcheck_service =
691 SpellcheckServiceFactory::GetForContext(&profile_);
692 SpellcheckCustomDictionary* custom_dictionary =
693 spellcheck_service->GetCustomDictionary();
694 TestingProfile profile2;
695 SpellcheckService* spellcheck_service2 =
696 static_cast<SpellcheckService*>(
697 SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
698 &profile2, &BuildSpellcheckService));
699 SpellcheckCustomDictionary* custom_dictionary2 =
700 spellcheck_service2->GetCustomDictionary();
702 SpellcheckCustomDictionary::Change change;
703 for (size_t i = 0;
704 i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS - 1;
705 ++i) {
706 change.AddWord("foo" + base::Uint64ToString(i));
708 Apply(*custom_dictionary, change);
710 custom_dictionary2->AddWord("bar");
711 custom_dictionary2->AddWord("baz");
713 int error_counter = 0;
714 EXPECT_FALSE(
715 custom_dictionary->MergeDataAndStartSyncing(
716 syncer::DICTIONARY,
717 custom_dictionary2->GetAllSyncData(
718 syncer::DICTIONARY),
719 scoped_ptr<syncer::SyncChangeProcessor>(
720 new syncer::SyncChangeProcessorWrapperForTest(
721 custom_dictionary2)),
722 scoped_ptr<syncer::SyncErrorFactory>(
723 new SyncErrorFactoryStub(&error_counter)))
724 .error()
725 .IsSet());
726 EXPECT_EQ(0, error_counter);
727 EXPECT_FALSE(custom_dictionary->IsSyncing());
729 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1,
730 custom_dictionary->GetWords().size());
731 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
732 custom_dictionary2->GetWords().size());
734 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
735 custom_dictionary->GetAllSyncData(syncer::DICTIONARY).size());
736 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
737 custom_dictionary2->GetAllSyncData(syncer::DICTIONARY).size());
740 TEST_F(SpellcheckCustomDictionaryTest, DictionaryTooBigToContiueSyncing) {
741 SpellcheckService* spellcheck_service =
742 SpellcheckServiceFactory::GetForContext(&profile_);
743 SpellcheckCustomDictionary* custom_dictionary =
744 spellcheck_service->GetCustomDictionary();
745 TestingProfile profile2;
746 SpellcheckService* spellcheck_service2 =
747 static_cast<SpellcheckService*>(
748 SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
749 &profile2, &BuildSpellcheckService));
750 SpellcheckCustomDictionary* custom_dictionary2 =
751 spellcheck_service2->GetCustomDictionary();
753 SpellcheckCustomDictionary::Change change;
754 for (size_t i = 0;
755 i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS - 1;
756 ++i) {
757 change.AddWord("foo" + base::Uint64ToString(i));
759 Apply(*custom_dictionary, change);
761 int error_counter = 0;
762 EXPECT_FALSE(
763 custom_dictionary->MergeDataAndStartSyncing(
764 syncer::DICTIONARY,
765 custom_dictionary2->GetAllSyncData(
766 syncer::DICTIONARY),
767 scoped_ptr<syncer::SyncChangeProcessor>(
768 new syncer::SyncChangeProcessorWrapperForTest(
769 custom_dictionary2)),
770 scoped_ptr<syncer::SyncErrorFactory>(
771 new SyncErrorFactoryStub(&error_counter)))
772 .error()
773 .IsSet());
774 EXPECT_EQ(0, error_counter);
775 EXPECT_TRUE(custom_dictionary->IsSyncing());
777 custom_dictionary->AddWord("bar");
778 EXPECT_EQ(0, error_counter);
779 EXPECT_TRUE(custom_dictionary->IsSyncing());
781 custom_dictionary->AddWord("baz");
782 EXPECT_EQ(0, error_counter);
783 EXPECT_FALSE(custom_dictionary->IsSyncing());
785 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1,
786 custom_dictionary->GetWords().size());
787 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
788 custom_dictionary2->GetWords().size());
790 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
791 custom_dictionary->GetAllSyncData(syncer::DICTIONARY).size());
792 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
793 custom_dictionary2->GetAllSyncData(syncer::DICTIONARY).size());
796 TEST_F(SpellcheckCustomDictionaryTest, LoadAfterSyncStart) {
797 SpellcheckService* spellcheck_service =
798 SpellcheckServiceFactory::GetForContext(&profile_);
799 SpellcheckCustomDictionary* custom_dictionary =
800 spellcheck_service->GetCustomDictionary();
801 TestingProfile profile2;
802 SpellcheckService* spellcheck_service2 =
803 static_cast<SpellcheckService*>(
804 SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
805 &profile2, &BuildSpellcheckService));
806 SpellcheckCustomDictionary* custom_dictionary2 =
807 spellcheck_service2->GetCustomDictionary();
809 custom_dictionary->AddWord("foo");
811 int error_counter = 0;
812 EXPECT_FALSE(
813 custom_dictionary->MergeDataAndStartSyncing(
814 syncer::DICTIONARY,
815 custom_dictionary2->GetAllSyncData(
816 syncer::DICTIONARY),
817 scoped_ptr<syncer::SyncChangeProcessor>(
818 new syncer::SyncChangeProcessorWrapperForTest(
819 custom_dictionary2)),
820 scoped_ptr<syncer::SyncErrorFactory>(
821 new SyncErrorFactoryStub(&error_counter)))
822 .error()
823 .IsSet());
824 EXPECT_EQ(0, error_counter);
825 EXPECT_TRUE(custom_dictionary->IsSyncing());
827 scoped_ptr<std::set<std::string>> custom_words(new std::set<std::string>);
828 custom_words->insert("bar");
829 OnLoaded(*custom_dictionary, custom_words.Pass());
830 EXPECT_TRUE(custom_dictionary->IsSyncing());
832 EXPECT_EQ(2UL, custom_dictionary->GetWords().size());
833 EXPECT_EQ(2UL, custom_dictionary2->GetWords().size());
835 EXPECT_EQ(2UL, custom_dictionary->GetAllSyncData(syncer::DICTIONARY).size());
836 EXPECT_EQ(2UL, custom_dictionary2->GetAllSyncData(syncer::DICTIONARY).size());
839 TEST_F(SpellcheckCustomDictionaryTest, LoadAfterSyncStartTooBigToSync) {
840 SpellcheckService* spellcheck_service =
841 SpellcheckServiceFactory::GetForContext(&profile_);
842 SpellcheckCustomDictionary* custom_dictionary =
843 spellcheck_service->GetCustomDictionary();
844 TestingProfile profile2;
845 SpellcheckService* spellcheck_service2 =
846 static_cast<SpellcheckService*>(
847 SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
848 &profile2, &BuildSpellcheckService));
849 SpellcheckCustomDictionary* custom_dictionary2 =
850 spellcheck_service2->GetCustomDictionary();
852 custom_dictionary->AddWord("foo");
854 int error_counter = 0;
855 EXPECT_FALSE(
856 custom_dictionary->MergeDataAndStartSyncing(
857 syncer::DICTIONARY,
858 custom_dictionary2->GetAllSyncData(
859 syncer::DICTIONARY),
860 scoped_ptr<syncer::SyncChangeProcessor>(
861 new syncer::SyncChangeProcessorWrapperForTest(
862 custom_dictionary2)),
863 scoped_ptr<syncer::SyncErrorFactory>(
864 new SyncErrorFactoryStub(&error_counter)))
865 .error()
866 .IsSet());
867 EXPECT_EQ(0, error_counter);
868 EXPECT_TRUE(custom_dictionary->IsSyncing());
870 scoped_ptr<std::set<std::string>> custom_words(new std::set<std::string>);
871 for (size_t i = 0;
872 i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS;
873 ++i) {
874 custom_words->insert(custom_words->end(), "foo" + base::Uint64ToString(i));
876 OnLoaded(*custom_dictionary, custom_words.Pass());
877 EXPECT_EQ(0, error_counter);
878 EXPECT_FALSE(custom_dictionary->IsSyncing());
880 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1,
881 custom_dictionary->GetWords().size());
882 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
883 custom_dictionary2->GetWords().size());
885 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
886 custom_dictionary->GetAllSyncData(syncer::DICTIONARY).size());
887 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
888 custom_dictionary2->GetAllSyncData(syncer::DICTIONARY).size());
891 TEST_F(SpellcheckCustomDictionaryTest, LoadDuplicatesAfterSync) {
892 SpellcheckService* spellcheck_service =
893 SpellcheckServiceFactory::GetForContext(&profile_);
894 SpellcheckCustomDictionary* custom_dictionary =
895 spellcheck_service->GetCustomDictionary();
896 TestingProfile profile2;
897 SpellcheckService* spellcheck_service2 =
898 static_cast<SpellcheckService*>(
899 SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
900 &profile2, &BuildSpellcheckService));
901 SpellcheckCustomDictionary* custom_dictionary2 =
902 spellcheck_service2->GetCustomDictionary();
904 SpellcheckCustomDictionary::Change change;
905 for (size_t i = 0;
906 i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS / 2;
907 ++i) {
908 change.AddWord("foo" + base::Uint64ToString(i));
910 Apply(*custom_dictionary, change);
912 int error_counter = 0;
913 EXPECT_FALSE(
914 custom_dictionary->MergeDataAndStartSyncing(
915 syncer::DICTIONARY,
916 custom_dictionary2->GetAllSyncData(
917 syncer::DICTIONARY),
918 scoped_ptr<syncer::SyncChangeProcessor>(
919 new syncer::SyncChangeProcessorWrapperForTest(
920 custom_dictionary2)),
921 scoped_ptr<syncer::SyncErrorFactory>(
922 new SyncErrorFactoryStub(&error_counter)))
923 .error()
924 .IsSet());
925 EXPECT_EQ(0, error_counter);
926 EXPECT_TRUE(custom_dictionary->IsSyncing());
928 OnLoaded(*custom_dictionary,
929 make_scoped_ptr(new std::set<std::string>(change.to_add())));
930 EXPECT_EQ(0, error_counter);
931 EXPECT_TRUE(custom_dictionary->IsSyncing());
933 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS / 2,
934 custom_dictionary->GetWords().size());
935 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS / 2,
936 custom_dictionary2->GetWords().size());
938 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS / 2,
939 custom_dictionary->GetAllSyncData(syncer::DICTIONARY).size());
940 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS / 2,
941 custom_dictionary2->GetAllSyncData(syncer::DICTIONARY).size());
944 TEST_F(SpellcheckCustomDictionaryTest, DictionaryLoadNotification) {
945 SpellcheckService* spellcheck_service =
946 SpellcheckServiceFactory::GetForContext(&profile_);
947 SpellcheckCustomDictionary* custom_dictionary =
948 spellcheck_service->GetCustomDictionary();
950 DictionaryObserverCounter observer;
951 custom_dictionary->AddObserver(&observer);
953 scoped_ptr<std::set<std::string>> custom_words(new std::set<std::string>);
954 custom_words->insert("foo");
955 custom_words->insert("bar");
956 OnLoaded(*custom_dictionary, custom_words.Pass());
958 EXPECT_GE(observer.loads(), 1);
959 EXPECT_LE(observer.loads(), 2);
960 EXPECT_EQ(0, observer.changes());
962 custom_dictionary->RemoveObserver(&observer);
965 TEST_F(SpellcheckCustomDictionaryTest, DictionaryAddWordNotification) {
966 SpellcheckService* spellcheck_service =
967 SpellcheckServiceFactory::GetForContext(&profile_);
968 SpellcheckCustomDictionary* custom_dictionary =
969 spellcheck_service->GetCustomDictionary();
971 OnLoaded(*custom_dictionary, make_scoped_ptr(new std::set<std::string>));
973 DictionaryObserverCounter observer;
974 custom_dictionary->AddObserver(&observer);
976 EXPECT_TRUE(custom_dictionary->AddWord("foo"));
977 EXPECT_TRUE(custom_dictionary->AddWord("bar"));
978 EXPECT_FALSE(custom_dictionary->AddWord("bar"));
980 EXPECT_EQ(2, observer.changes());
982 custom_dictionary->RemoveObserver(&observer);
985 TEST_F(SpellcheckCustomDictionaryTest, DictionaryRemoveWordNotification) {
986 SpellcheckService* spellcheck_service =
987 SpellcheckServiceFactory::GetForContext(&profile_);
988 SpellcheckCustomDictionary* custom_dictionary =
989 spellcheck_service->GetCustomDictionary();
991 OnLoaded(*custom_dictionary, make_scoped_ptr(new std::set<std::string>));
993 EXPECT_TRUE(custom_dictionary->AddWord("foo"));
994 EXPECT_TRUE(custom_dictionary->AddWord("bar"));
996 DictionaryObserverCounter observer;
997 custom_dictionary->AddObserver(&observer);
999 EXPECT_TRUE(custom_dictionary->RemoveWord("foo"));
1000 EXPECT_TRUE(custom_dictionary->RemoveWord("bar"));
1001 EXPECT_FALSE(custom_dictionary->RemoveWord("baz"));
1003 EXPECT_EQ(2, observer.changes());
1005 custom_dictionary->RemoveObserver(&observer);
1008 TEST_F(SpellcheckCustomDictionaryTest, DictionarySyncNotification) {
1009 SpellcheckService* spellcheck_service =
1010 SpellcheckServiceFactory::GetForContext(&profile_);
1011 SpellcheckCustomDictionary* custom_dictionary =
1012 spellcheck_service->GetCustomDictionary();
1013 TestingProfile profile2;
1014 SpellcheckService* spellcheck_service2 =
1015 static_cast<SpellcheckService*>(
1016 SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
1017 &profile2, &BuildSpellcheckService));
1018 SpellcheckCustomDictionary* custom_dictionary2 =
1019 spellcheck_service2->GetCustomDictionary();
1021 OnLoaded(*custom_dictionary, make_scoped_ptr(new std::set<std::string>));
1022 OnLoaded(*custom_dictionary2, make_scoped_ptr(new std::set<std::string>));
1024 custom_dictionary->AddWord("foo");
1025 custom_dictionary->AddWord("bar");
1026 custom_dictionary2->AddWord("foo");
1027 custom_dictionary2->AddWord("baz");
1029 DictionaryObserverCounter observer;
1030 custom_dictionary->AddObserver(&observer);
1032 DictionaryObserverCounter observer2;
1033 custom_dictionary2->AddObserver(&observer2);
1035 int error_counter = 0;
1036 EXPECT_FALSE(
1037 custom_dictionary->MergeDataAndStartSyncing(
1038 syncer::DICTIONARY,
1039 custom_dictionary2->GetAllSyncData(
1040 syncer::DICTIONARY),
1041 scoped_ptr<syncer::SyncChangeProcessor>(
1042 new syncer::SyncChangeProcessorWrapperForTest(
1043 custom_dictionary2)),
1044 scoped_ptr<syncer::SyncErrorFactory>(
1045 new SyncErrorFactoryStub(&error_counter)))
1046 .error()
1047 .IsSet());
1048 EXPECT_EQ(0, error_counter);
1049 EXPECT_TRUE(custom_dictionary->IsSyncing());
1051 EXPECT_EQ(1, observer.changes());
1052 EXPECT_EQ(1, observer2.changes());
1054 custom_dictionary->RemoveObserver(&observer);
1055 custom_dictionary2->RemoveObserver(&observer2);
1058 // The server has maximum number of words and the client has maximum number of
1059 // different words before association time. No new words should be pushed to the
1060 // sync server upon association. The client should accept words from the sync
1061 // server, however.
1062 TEST_F(SpellcheckCustomDictionaryTest, DictionarySyncLimit) {
1063 TestingProfile server_profile;
1064 SpellcheckService* server_spellcheck_service =
1065 static_cast<SpellcheckService*>(
1066 SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
1067 &server_profile, &BuildSpellcheckService));
1069 // Here, |server_custom_dictionary| plays the role of the sync server.
1070 SpellcheckCustomDictionary* server_custom_dictionary =
1071 server_spellcheck_service->GetCustomDictionary();
1073 // Upload the maximum number of words to the sync server.
1075 SpellcheckService* spellcheck_service =
1076 SpellcheckServiceFactory::GetForContext(&profile_);
1077 SpellcheckCustomDictionary* custom_dictionary =
1078 spellcheck_service->GetCustomDictionary();
1080 SpellcheckCustomDictionary::Change change;
1081 for (size_t i = 0;
1082 i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS;
1083 ++i) {
1084 change.AddWord("foo" + base::Uint64ToString(i));
1086 Apply(*custom_dictionary, change);
1088 int error_counter = 0;
1089 EXPECT_FALSE(
1090 custom_dictionary
1091 ->MergeDataAndStartSyncing(
1092 syncer::DICTIONARY,
1093 server_custom_dictionary->GetAllSyncData(syncer::DICTIONARY),
1094 scoped_ptr<syncer::SyncChangeProcessor>(
1095 new syncer::SyncChangeProcessorWrapperForTest(
1096 server_custom_dictionary)),
1097 scoped_ptr<syncer::SyncErrorFactory>(
1098 new SyncErrorFactoryStub(&error_counter)))
1099 .error()
1100 .IsSet());
1101 EXPECT_EQ(0, error_counter);
1102 EXPECT_TRUE(custom_dictionary->IsSyncing());
1103 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
1104 custom_dictionary->GetWords().size());
1107 // The sync server now has the maximum number of words.
1108 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
1109 server_custom_dictionary->GetWords().size());
1111 // Associate the sync server with a client that also has the maximum number of
1112 // words, but all of these words are different from the ones on the sync
1113 // server.
1115 TestingProfile client_profile;
1116 SpellcheckService* client_spellcheck_service =
1117 static_cast<SpellcheckService*>(
1118 SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
1119 &client_profile, &BuildSpellcheckService));
1121 // Here, |client_custom_dictionary| plays the role of the client.
1122 SpellcheckCustomDictionary* client_custom_dictionary =
1123 client_spellcheck_service->GetCustomDictionary();
1125 // Add the maximum number of words to the client. These words are all
1126 // different from those on the server.
1127 SpellcheckCustomDictionary::Change change;
1128 for (size_t i = 0;
1129 i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS;
1130 ++i) {
1131 change.AddWord("bar" + base::Uint64ToString(i));
1133 Apply(*client_custom_dictionary, change);
1135 // Associate the server and the client.
1136 int error_counter = 0;
1137 EXPECT_FALSE(
1138 client_custom_dictionary
1139 ->MergeDataAndStartSyncing(
1140 syncer::DICTIONARY,
1141 server_custom_dictionary->GetAllSyncData(syncer::DICTIONARY),
1142 scoped_ptr<syncer::SyncChangeProcessor>(
1143 new syncer::SyncChangeProcessorWrapperForTest(
1144 server_custom_dictionary)),
1145 scoped_ptr<syncer::SyncErrorFactory>(
1146 new SyncErrorFactoryStub(&error_counter)))
1147 .error()
1148 .IsSet());
1149 EXPECT_EQ(0, error_counter);
1150 EXPECT_FALSE(client_custom_dictionary->IsSyncing());
1151 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS * 2,
1152 client_custom_dictionary->GetWords().size());
1155 // The sync server should not receive more words, because it has the maximum
1156 // number of words already.
1157 EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
1158 server_custom_dictionary->GetWords().size());
1161 TEST_F(SpellcheckCustomDictionaryTest, RecordSizeStatsCorrectly) {
1162 #if defined(OS_WIN)
1163 // Failing consistently on Win7. See crbug.com/230534.
1164 if (base::win::GetVersion() >= base::win::VERSION_VISTA)
1165 return;
1166 #endif
1167 // Record a baseline.
1168 SpellCheckHostMetrics::RecordCustomWordCountStats(123);
1170 // Determine if test failures are due the statistics recorder not being
1171 // available or because the histogram just isn't there: crbug.com/230534.
1172 EXPECT_TRUE(StatisticsRecorder::IsActive());
1174 HistogramBase* histogram =
1175 StatisticsRecorder::FindHistogram("SpellCheck.CustomWords");
1176 ASSERT_TRUE(histogram != NULL);
1177 scoped_ptr<HistogramSamples> baseline = histogram->SnapshotSamples();
1179 // Load the dictionary which should be empty.
1180 base::FilePath path =
1181 profile_.GetPath().Append(chrome::kCustomDictionaryFileName);
1182 EXPECT_TRUE(LoadDictionaryFile(path)->empty());
1184 // We expect there to be an entry with 0.
1185 histogram =
1186 StatisticsRecorder::FindHistogram("SpellCheck.CustomWords");
1187 ASSERT_TRUE(histogram != NULL);
1188 scoped_ptr<HistogramSamples> samples = histogram->SnapshotSamples();
1190 samples->Subtract(*baseline);
1191 EXPECT_EQ(0,samples->sum());
1193 scoped_ptr<SpellcheckCustomDictionary::Change> change(
1194 new SpellcheckCustomDictionary::Change);
1195 change->AddWord("bar");
1196 change->AddWord("foo");
1197 UpdateDictionaryFile(change.Pass(), path);
1199 // Load the dictionary again and it should have 2 entries.
1200 EXPECT_EQ(2u, LoadDictionaryFile(path)->size());
1202 histogram =
1203 StatisticsRecorder::FindHistogram("SpellCheck.CustomWords");
1204 ASSERT_TRUE(histogram != NULL);
1205 scoped_ptr<HistogramSamples> samples2 = histogram->SnapshotSamples();
1207 samples2->Subtract(*baseline);
1208 EXPECT_EQ(2,samples2->sum());
1211 TEST_F(SpellcheckCustomDictionaryTest, HasWord) {
1212 SpellcheckService* spellcheck_service =
1213 SpellcheckServiceFactory::GetForContext(&profile_);
1214 SpellcheckCustomDictionary* custom_dictionary =
1215 spellcheck_service->GetCustomDictionary();
1216 OnLoaded(*custom_dictionary, make_scoped_ptr(new std::set<std::string>));
1217 EXPECT_FALSE(custom_dictionary->HasWord("foo"));
1218 EXPECT_FALSE(custom_dictionary->HasWord("bar"));
1219 custom_dictionary->AddWord("foo");
1220 EXPECT_TRUE(custom_dictionary->HasWord("foo"));
1221 EXPECT_FALSE(custom_dictionary->HasWord("bar"));