12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <vector>
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/file_util.h"
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/metrics/histogram_samples.h"
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/metrics/statistics_recorder.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/spellchecker/spellcheck_custom_dictionary.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/spellchecker/spellcheck_factory.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/spellchecker/spellcheck_host_metrics.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/spellchecker/spellcheck_service.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/chrome_constants.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/spellcheck_common.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/base/testing_profile.h"
18a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "content/public/test/test_browser_thread_bundle.h"
19a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "net/url_request/test_url_fetcher_factory.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/api/sync_change.h"
21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "sync/api/sync_change_processor_wrapper_for_test.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/api/sync_data.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/api/sync_error_factory.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/api/sync_error_factory_mock.h"
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/protocol/sync.pb.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#if defined(OS_WIN)
303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// For version specific disabled tests below (http://crbug.com/230534).
313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/win/windows_version.h"
323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#endif
333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using base::HistogramBase;
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using base::HistogramSamples;
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using base::StatisticsRecorder;
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using chrome::spellcheck_common::WordList;
3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using chrome::spellcheck_common::WordSet;
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Get all sync data for the custom dictionary without limiting to maximum
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// number of syncable words.
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)syncer::SyncDataList GetAllSyncDataNoLimit(
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SpellcheckCustomDictionary* dictionary) {
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  syncer::SyncDataList data;
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string word;
4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const WordSet& words = dictionary->GetWords();
4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (WordSet::const_iterator it = words.begin(); it != words.end(); ++it) {
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    word = *it;
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_pb::EntitySpecifics specifics;
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    specifics.mutable_dictionary()->set_word(word);
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    data.push_back(syncer::SyncData::CreateLocalData(word, word, specifics));
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return data;
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)static KeyedService* BuildSpellcheckService(content::BrowserContext* profile) {
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return new SpellcheckService(static_cast<Profile*>(profile));
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class SpellcheckCustomDictionaryTest : public testing::Test {
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protected:
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void SetUp() OVERRIDE {
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Use SetTestingFactoryAndUse to force creation and initialization.
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
69a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch        &profile_, &BuildSpellcheckService);
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    StatisticsRecorder::Initialize();
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // A wrapper around SpellcheckCustomDictionary::LoadDictionaryFile private
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // function to avoid a large number of FRIEND_TEST declarations in
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // SpellcheckCustomDictionary.
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  chrome::spellcheck_common::WordList LoadDictionaryFile(
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const base::FilePath& path) {
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return SpellcheckCustomDictionary::LoadDictionaryFile(path);
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // A wrapper around SpellcheckCustomDictionary::UpdateDictionaryFile private
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // function to avoid a large number of FRIEND_TEST declarations in
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // SpellcheckCustomDictionary.
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void UpdateDictionaryFile(
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const SpellcheckCustomDictionary::Change& dictionary_change,
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const base::FilePath& path) {
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SpellcheckCustomDictionary::UpdateDictionaryFile(dictionary_change, path);
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // A wrapper around SpellcheckCustomDictionary::OnLoaded private method to
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // avoid a large number of FRIEND_TEST declarations in
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // SpellcheckCustomDictionary.
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void OnLoaded(
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SpellcheckCustomDictionary& dictionary,
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const chrome::spellcheck_common::WordList& custom_words) {
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dictionary.OnLoaded(custom_words);
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // A wrapper around SpellcheckCustomDictionary::Apply private method to avoid
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // a large number of FRIEND_TEST declarations in SpellcheckCustomDictionary.
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void Apply(
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SpellcheckCustomDictionary& dictionary,
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const SpellcheckCustomDictionary::Change& change) {
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return dictionary.Apply(change);
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
108a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  content::TestBrowserThreadBundle thread_bundle_;
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
110a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  TestingProfile profile_;
111a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  net::TestURLFetcherFactory fetcher_factory_;
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// An implementation of SyncErrorFactory that does not upload the error message
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// and updates an outside error counter. This lets us know the number of error
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// messages in an instance of this class after that instance is deleted.
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class SyncErrorFactoryStub : public syncer::SyncErrorFactory {
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  explicit SyncErrorFactoryStub(int* error_counter)
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : error_counter_(error_counter) {}
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~SyncErrorFactoryStub() {}
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Overridden from syncer::SyncErrorFactory:
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual syncer::SyncError CreateAndUploadError(
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const tracked_objects::Location& location,
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const std::string& message) OVERRIDE {
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    (*error_counter_)++;
128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return syncer::SyncError(location,
129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                             syncer::SyncError::DATATYPE_ERROR,
130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                             message,
131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                             syncer::DICTIONARY);
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int* error_counter_;
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SyncErrorFactoryStub);
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Counts the number of notifications for dictionary load and change.
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class DictionaryObserverCounter : public SpellcheckCustomDictionary::Observer {
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DictionaryObserverCounter() : loads_(0), changes_(0) {}
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~DictionaryObserverCounter() {}
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int loads() const { return loads_; }
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int changes() const { return changes_; }
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Overridden from SpellcheckCustomDictionary::Observer:
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnCustomDictionaryLoaded() OVERRIDE { loads_++; }
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnCustomDictionaryChanged(
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const SpellcheckCustomDictionary::Change& change) OVERRIDE { changes_++; }
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int loads_;
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int changes_;
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(DictionaryObserverCounter);
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, SaveAndLoad) {
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath path =
161a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      profile_.GetPath().Append(chrome::kCustomDictionaryFileName);
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WordList loaded_custom_words = LoadDictionaryFile(path);
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The custom word list should be empty now.
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WordList expected;
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(expected, loaded_custom_words);
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary::Change change;
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  change.AddWord("bar");
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  change.AddWord("foo");
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateDictionaryFile(change, path);
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected.push_back("bar");
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected.push_back("foo");
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The custom word list should include written words.
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  loaded_custom_words = LoadDictionaryFile(path);
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(expected, loaded_custom_words);
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  change = SpellcheckCustomDictionary::Change();
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  change.RemoveWord("bar");
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  change.RemoveWord("foo");
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateDictionaryFile(change, path);
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  loaded_custom_words = LoadDictionaryFile(path);
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected.clear();
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(expected, loaded_custom_words);
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, MultiProfile) {
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service =
191d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      SpellcheckServiceFactory::GetForContext(&profile_);
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary =
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service->GetCustomDictionary();
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestingProfile profile2;
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service2 =
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<SpellcheckService*>(
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              &profile2, &BuildSpellcheckService));
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary2 =
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service2->GetCustomDictionary();
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
20290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  WordSet expected1;
20390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  WordSet expected2;
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary->AddWord("foo");
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary->AddWord("bar");
20790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  expected1.insert("foo");
20890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  expected1.insert("bar");
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary2->AddWord("hoge");
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary2->AddWord("fuga");
21290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  expected2.insert("hoge");
21390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  expected2.insert("fuga");
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
21590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  WordSet actual1 = custom_dictionary->GetWords();
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(actual1, expected1);
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
21890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  WordSet actual2 = custom_dictionary2->GetWords();
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(actual2, expected2);
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Legacy empty dictionary should be converted to new format empty dictionary.
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, LegacyEmptyDictionaryShouldBeConverted) {
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath path =
225a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      profile_.GetPath().Append(chrome::kCustomDictionaryFileName);
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string content;
228a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::WriteFile(path, content.c_str(), content.length());
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WordList loaded_custom_words = LoadDictionaryFile(path);
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(loaded_custom_words.empty());
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Legacy dictionary with two words should be converted to new format dictionary
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// with two words.
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest,
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       LegacyDictionaryWithTwoWordsShouldBeConverted) {
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath path =
238a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      profile_.GetPath().Append(chrome::kCustomDictionaryFileName);
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string content = "foo\nbar\nfoo\n";
241a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::WriteFile(path, content.c_str(), content.length());
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WordList loaded_custom_words = LoadDictionaryFile(path);
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WordList expected;
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected.push_back("bar");
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected.push_back("foo");
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(expected, loaded_custom_words);
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Illegal words should be removed. Leading and trailing whitespace should be
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// trimmed.
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest,
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       IllegalWordsShouldBeRemovedFromDictionary) {
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath path =
254a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      profile_.GetPath().Append(chrome::kCustomDictionaryFileName);
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string content = "foo\n foo bar \n\n \nbar\n"
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "01234567890123456789012345678901234567890123456789"
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "01234567890123456789012345678901234567890123456789";
259a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::WriteFile(path, content.c_str(), content.length());
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WordList loaded_custom_words = LoadDictionaryFile(path);
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WordList expected;
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected.push_back("bar");
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected.push_back("foo");
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected.push_back("foo bar");
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(expected, loaded_custom_words);
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Write to dictionary should backup previous version and write the word to the
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// end of the dictionary. If the dictionary file is corrupted on disk, the
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// previous version should be reloaded.
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, CorruptedWriteShouldBeRecovered) {
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath path =
273a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      profile_.GetPath().Append(chrome::kCustomDictionaryFileName);
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string content = "foo\nbar";
276a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::WriteFile(path, content.c_str(), content.length());
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WordList loaded_custom_words = LoadDictionaryFile(path);
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WordList expected;
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected.push_back("bar");
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected.push_back("foo");
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(expected, loaded_custom_words);
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary::Change change;
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  change.AddWord("baz");
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateDictionaryFile(change, path);
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content.clear();
28758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  base::ReadFileToString(path, &content);
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content.append("corruption");
289a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::WriteFile(path, content.c_str(), content.length());
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  loaded_custom_words = LoadDictionaryFile(path);
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(expected, loaded_custom_words);
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest,
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       GetAllSyncDataAccuratelyReflectsDictionaryState) {
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* dictionary =
297d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      SpellcheckServiceFactory::GetForContext(
298a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch          &profile_)->GetCustomDictionary();
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  syncer::SyncDataList data = dictionary->GetAllSyncData(syncer::DICTIONARY);
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.empty());
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(dictionary->AddWord("bar"));
30490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(dictionary->AddWord("foo"));
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data = dictionary->GetAllSyncData(syncer::DICTIONARY);
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(2UL, data.size());
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::string> words;
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  words.push_back("bar");
31090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  words.push_back("foo");
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < data.size(); i++) {
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_TRUE(data[i].GetSpecifics().has_dictionary());
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(syncer::DICTIONARY, data[i].GetDataType());
314e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    EXPECT_EQ(words[i], syncer::SyncDataLocal(data[i]).GetTag());
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(words[i], data[i].GetSpecifics().dictionary().word());
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(dictionary->RemoveWord("bar"));
31990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(dictionary->RemoveWord("foo"));
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data = dictionary->GetAllSyncData(syncer::DICTIONARY);
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.empty());
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, GetAllSyncDataHasLimit) {
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* dictionary =
327d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      SpellcheckServiceFactory::GetForContext(
328a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch          &profile_)->GetCustomDictionary();
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary::Change change;
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0;
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS - 1;
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       i++) {
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    change.AddWord("foo" + base::Uint64ToString(i));
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Apply(*dictionary, change);
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS - 1,
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            dictionary->GetWords().size());
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS - 1,
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            dictionary->GetAllSyncData(syncer::DICTIONARY).size());
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dictionary->AddWord("baz");
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            dictionary->GetWords().size());
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            dictionary->GetAllSyncData(syncer::DICTIONARY).size());
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dictionary->AddWord("bar");
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1,
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            dictionary->GetWords().size());
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            dictionary->GetAllSyncData(syncer::DICTIONARY).size());
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dictionary->AddWord("snafoo");
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 2,
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            dictionary->GetWords().size());
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            dictionary->GetAllSyncData(syncer::DICTIONARY).size());
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, ProcessSyncChanges) {
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service =
363d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      SpellcheckServiceFactory::GetForContext(&profile_);
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* dictionary =
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service->GetCustomDictionary();
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dictionary->AddWord("foo");
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dictionary->AddWord("bar");
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  syncer::SyncChangeList changes;
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Add existing word.
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string word = "foo";
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_pb::EntitySpecifics specifics;
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    specifics.mutable_dictionary()->set_word(word);
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    changes.push_back(syncer::SyncChange(
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE,
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        syncer::SyncChange::ACTION_ADD,
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        syncer::SyncData::CreateLocalData(word, word, specifics)));
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Add invalid word. This word is too long.
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string word = "01234567890123456789012345678901234567890123456789"
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "01234567890123456789012345678901234567890123456789";
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_pb::EntitySpecifics specifics;
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    specifics.mutable_dictionary()->set_word(word);
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    changes.push_back(syncer::SyncChange(
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE,
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        syncer::SyncChange::ACTION_ADD,
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        syncer::SyncData::CreateLocalData(word, word, specifics)));
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Add valid word.
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string word = "baz";
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_pb::EntitySpecifics specifics;
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    specifics.mutable_dictionary()->set_word(word);
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    changes.push_back(syncer::SyncChange(
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE,
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        syncer::SyncChange::ACTION_ADD,
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        syncer::SyncData::CreateLocalData(word, word, specifics)));
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Remove missing word.
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string word = "snafoo";
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_pb::EntitySpecifics specifics;
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    specifics.mutable_dictionary()->set_word(word);
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    changes.push_back(syncer::SyncChange(
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE,
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        syncer::SyncChange::ACTION_DELETE,
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        syncer::SyncData::CreateLocalData(word, word, specifics)));
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Remove existing word.
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string word = "bar";
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_pb::EntitySpecifics specifics;
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    specifics.mutable_dictionary()->set_word(word);
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    changes.push_back(syncer::SyncChange(
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE,
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        syncer::SyncChange::ACTION_DELETE,
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        syncer::SyncData::CreateLocalData(word, word, specifics)));
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(dictionary->ProcessSyncChanges(FROM_HERE, changes).IsSet());
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
42590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const WordSet& words = dictionary->GetWords();
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(2UL, words.size());
42790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(0UL, words.count("bar"));
42890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(1UL, words.count("foo"));
42990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(1UL, words.count("baz"));
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, MergeDataAndStartSyncing) {
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service =
434d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      SpellcheckServiceFactory::GetForContext(&profile_);
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary =
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service->GetCustomDictionary();
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestingProfile profile2;
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service2 =
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<SpellcheckService*>(
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              &profile2, &BuildSpellcheckService));
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary2 =
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service2->GetCustomDictionary();
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary::Change change;
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0;
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS / 2;
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++i) {
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    change.AddWord("foo" + base::Uint64ToString(i));
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Apply(*custom_dictionary, change);
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary::Change change2;
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0;
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS / 2;
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++i) {
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    change2.AddWord("bar" + base::Uint64ToString(i));
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Apply(*custom_dictionary2, change2);
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int error_counter = 0;
462a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_FALSE(
463a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      custom_dictionary->MergeDataAndStartSyncing(
464a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             syncer::DICTIONARY,
465a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             custom_dictionary2->GetAllSyncData(
466a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 syncer::DICTIONARY),
467a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             scoped_ptr<syncer::SyncChangeProcessor>(
468a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 new syncer::SyncChangeProcessorWrapperForTest(
469a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     custom_dictionary2)),
470a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             scoped_ptr<syncer::SyncErrorFactory>(
471a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 new SyncErrorFactoryStub(&error_counter)))
472a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          .error()
473a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          .IsSet());
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, error_counter);
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(custom_dictionary->IsSyncing());
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
47790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  WordSet words = custom_dictionary->GetWords();
47890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  WordSet words2 = custom_dictionary2->GetWords();
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(words.size(), words2.size());
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(words, words2);
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, DictionaryTooBigBeforeSyncing) {
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service =
485d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      SpellcheckServiceFactory::GetForContext(&profile_);
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary =
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service->GetCustomDictionary();
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestingProfile profile2;
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service2 =
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<SpellcheckService*>(
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              &profile2, &BuildSpellcheckService));
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary2 =
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service2->GetCustomDictionary();
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary::Change change;
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0;
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1;
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++i) {
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    change.AddWord("foo" + base::Uint64ToString(i));
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Apply(*custom_dictionary, change);
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int error_counter = 0;
505a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_FALSE(
506a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      custom_dictionary->MergeDataAndStartSyncing(
507a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             syncer::DICTIONARY,
508a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             custom_dictionary2->GetAllSyncData(
509a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 syncer::DICTIONARY),
510a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             scoped_ptr<syncer::SyncChangeProcessor>(
511a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 new syncer::SyncChangeProcessorWrapperForTest(
512a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     custom_dictionary2)),
513a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             scoped_ptr<syncer::SyncErrorFactory>(
514a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 new SyncErrorFactoryStub(&error_counter)))
515a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          .error()
516a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          .IsSet());
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, error_counter);
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(custom_dictionary->IsSyncing());
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1,
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary->GetWords().size());
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary2->GetWords().size());
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary->GetAllSyncData(syncer::DICTIONARY).size());
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary2->GetAllSyncData(syncer::DICTIONARY).size());
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, DictionaryTooBigAndServerFull) {
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service =
533d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      SpellcheckServiceFactory::GetForContext(&profile_);
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary =
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service->GetCustomDictionary();
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestingProfile profile2;
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service2 =
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<SpellcheckService*>(
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              &profile2, &BuildSpellcheckService));
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary2 =
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service2->GetCustomDictionary();
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary::Change change;
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary::Change change2;
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0;
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS;
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++i) {
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    change.AddWord("foo" + base::Uint64ToString(i));
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    change2.AddWord("bar" + base::Uint64ToString(i));
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  change.AddWord("foo");
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Apply(*custom_dictionary, change);
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Apply(*custom_dictionary2, change2);
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1,
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary->GetWords().size());
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary2->GetWords().size());
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int error_counter = 0;
562a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_FALSE(
563a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      custom_dictionary->MergeDataAndStartSyncing(
564a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             syncer::DICTIONARY,
565a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             custom_dictionary2->GetAllSyncData(
566a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 syncer::DICTIONARY),
567a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             scoped_ptr<syncer::SyncChangeProcessor>(
568a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 new syncer::SyncChangeProcessorWrapperForTest(
569a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     custom_dictionary2)),
570a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             scoped_ptr<syncer::SyncErrorFactory>(
571a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 new SyncErrorFactoryStub(&error_counter)))
572a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          .error()
573a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          .IsSet());
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, error_counter);
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(custom_dictionary->IsSyncing());
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS * 2 + 1,
5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary->GetWords().size());
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary2->GetWords().size());
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary->GetAllSyncData(syncer::DICTIONARY).size());
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary2->GetAllSyncData(syncer::DICTIONARY).size());
5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, ServerTooBig) {
5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service =
590d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      SpellcheckServiceFactory::GetForContext(&profile_);
5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary =
5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service->GetCustomDictionary();
5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestingProfile profile2;
5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service2 =
5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<SpellcheckService*>(
5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              &profile2, &BuildSpellcheckService));
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary2 =
5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service2->GetCustomDictionary();
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary::Change change;
6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary::Change change2;
6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0;
6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1;
6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++i) {
6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    change.AddWord("foo" + base::Uint64ToString(i));
6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    change2.AddWord("bar" + base::Uint64ToString(i));
6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Apply(*custom_dictionary, change);
6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Apply(*custom_dictionary2, change2);
6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1,
6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary->GetWords().size());
6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1,
6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary2->GetWords().size());
6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int error_counter = 0;
618a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_FALSE(
619a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      custom_dictionary->MergeDataAndStartSyncing(
620a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             syncer::DICTIONARY,
621a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             GetAllSyncDataNoLimit(custom_dictionary2),
622a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             scoped_ptr<syncer::SyncChangeProcessor>(
623a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 new syncer::SyncChangeProcessorWrapperForTest(
624a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     custom_dictionary2)),
625a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             scoped_ptr<syncer::SyncErrorFactory>(
626a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 new SyncErrorFactoryStub(&error_counter)))
627a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          .error()
628a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          .IsSet());
6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, error_counter);
6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(custom_dictionary->IsSyncing());
6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS * 2 + 2,
6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary->GetWords().size());
6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1,
6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary2->GetWords().size());
6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary->GetAllSyncData(syncer::DICTIONARY).size());
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary2->GetAllSyncData(syncer::DICTIONARY).size());
6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, DictionaryTooBigToStartSyncing) {
6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service =
645d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      SpellcheckServiceFactory::GetForContext(&profile_);
6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary =
6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service->GetCustomDictionary();
6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestingProfile profile2;
6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service2 =
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<SpellcheckService*>(
6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              &profile2, &BuildSpellcheckService));
6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary2 =
6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service2->GetCustomDictionary();
6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary::Change change;
6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0;
6582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS - 1;
6592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++i) {
6602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    change.AddWord("foo" + base::Uint64ToString(i));
6612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Apply(*custom_dictionary, change);
6632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary2->AddWord("bar");
6652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary2->AddWord("baz");
6662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int error_counter = 0;
668a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_FALSE(
669a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      custom_dictionary->MergeDataAndStartSyncing(
670a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             syncer::DICTIONARY,
671a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             custom_dictionary2->GetAllSyncData(
672a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 syncer::DICTIONARY),
673a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             scoped_ptr<syncer::SyncChangeProcessor>(
674a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 new syncer::SyncChangeProcessorWrapperForTest(
675a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     custom_dictionary2)),
676a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             scoped_ptr<syncer::SyncErrorFactory>(
677a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 new SyncErrorFactoryStub(&error_counter)))
678a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          .error()
679a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          .IsSet());
6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, error_counter);
6812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(custom_dictionary->IsSyncing());
6822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1,
6842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary->GetWords().size());
6852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary2->GetWords().size());
6872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary->GetAllSyncData(syncer::DICTIONARY).size());
6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary2->GetAllSyncData(syncer::DICTIONARY).size());
6922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, DictionaryTooBigToContiueSyncing) {
6952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service =
696d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      SpellcheckServiceFactory::GetForContext(&profile_);
6972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary =
6982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service->GetCustomDictionary();
6992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestingProfile profile2;
7002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service2 =
7012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<SpellcheckService*>(
7022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
7032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              &profile2, &BuildSpellcheckService));
7042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary2 =
7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service2->GetCustomDictionary();
7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary::Change change;
7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0;
7092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS - 1;
7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++i) {
7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    change.AddWord("foo" + base::Uint64ToString(i));
7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Apply(*custom_dictionary, change);
7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int error_counter = 0;
716a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_FALSE(
717a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      custom_dictionary->MergeDataAndStartSyncing(
718a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             syncer::DICTIONARY,
719a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             custom_dictionary2->GetAllSyncData(
720a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 syncer::DICTIONARY),
721a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             scoped_ptr<syncer::SyncChangeProcessor>(
722a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 new syncer::SyncChangeProcessorWrapperForTest(
723a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     custom_dictionary2)),
724a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             scoped_ptr<syncer::SyncErrorFactory>(
725a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 new SyncErrorFactoryStub(&error_counter)))
726a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          .error()
727a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          .IsSet());
7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, error_counter);
7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(custom_dictionary->IsSyncing());
7302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary->AddWord("bar");
7322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, error_counter);
7332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(custom_dictionary->IsSyncing());
7342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary->AddWord("baz");
7362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, error_counter);
7372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(custom_dictionary->IsSyncing());
7382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1,
7402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary->GetWords().size());
7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
7422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary2->GetWords().size());
7432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
7452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary->GetAllSyncData(syncer::DICTIONARY).size());
7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
7472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary2->GetAllSyncData(syncer::DICTIONARY).size());
7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, LoadAfterSyncStart) {
7512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service =
752d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      SpellcheckServiceFactory::GetForContext(&profile_);
7532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary =
7542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service->GetCustomDictionary();
7552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestingProfile profile2;
7562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service2 =
7572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<SpellcheckService*>(
7582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
7592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              &profile2, &BuildSpellcheckService));
7602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary2 =
7612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service2->GetCustomDictionary();
7622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary->AddWord("foo");
7642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int error_counter = 0;
766a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_FALSE(
767a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      custom_dictionary->MergeDataAndStartSyncing(
768a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             syncer::DICTIONARY,
769a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             custom_dictionary2->GetAllSyncData(
770a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 syncer::DICTIONARY),
771a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             scoped_ptr<syncer::SyncChangeProcessor>(
772a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 new syncer::SyncChangeProcessorWrapperForTest(
773a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     custom_dictionary2)),
774a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             scoped_ptr<syncer::SyncErrorFactory>(
775a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 new SyncErrorFactoryStub(&error_counter)))
776a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          .error()
777a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          .IsSet());
7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, error_counter);
7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(custom_dictionary->IsSyncing());
7802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WordList custom_words;
7822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_words.push_back("bar");
7832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OnLoaded(*custom_dictionary, custom_words);
7842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(custom_dictionary->IsSyncing());
7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(2UL, custom_dictionary->GetWords().size());
7872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(2UL, custom_dictionary2->GetWords().size());
7882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(2UL, custom_dictionary->GetAllSyncData(syncer::DICTIONARY).size());
7902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(2UL, custom_dictionary2->GetAllSyncData(syncer::DICTIONARY).size());
7912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, LoadAfterSyncStartTooBigToSync) {
7942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service =
795d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      SpellcheckServiceFactory::GetForContext(&profile_);
7962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary =
7972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service->GetCustomDictionary();
7982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestingProfile profile2;
7992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service2 =
8002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<SpellcheckService*>(
8012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
8022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              &profile2, &BuildSpellcheckService));
8032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary2 =
8042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service2->GetCustomDictionary();
8052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary->AddWord("foo");
8072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int error_counter = 0;
809a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_FALSE(
810a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      custom_dictionary->MergeDataAndStartSyncing(
811a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             syncer::DICTIONARY,
812a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             custom_dictionary2->GetAllSyncData(
813a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 syncer::DICTIONARY),
814a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             scoped_ptr<syncer::SyncChangeProcessor>(
815a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 new syncer::SyncChangeProcessorWrapperForTest(
816a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     custom_dictionary2)),
817a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             scoped_ptr<syncer::SyncErrorFactory>(
818a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 new SyncErrorFactoryStub(&error_counter)))
819a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          .error()
820a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          .IsSet());
8212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, error_counter);
8222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(custom_dictionary->IsSyncing());
8232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WordList custom_words;
8252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0;
8262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS;
8272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++i) {
8282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    custom_words.push_back("foo" + base::Uint64ToString(i));
8292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OnLoaded(*custom_dictionary, custom_words);
8312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, error_counter);
8322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(custom_dictionary->IsSyncing());
8332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1,
8352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary->GetWords().size());
8362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
8372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary2->GetWords().size());
8382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
8402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary->GetAllSyncData(syncer::DICTIONARY).size());
8412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
8422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary2->GetAllSyncData(syncer::DICTIONARY).size());
8432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, LoadDuplicatesAfterSync) {
8462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service =
847d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      SpellcheckServiceFactory::GetForContext(&profile_);
8482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary =
8492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service->GetCustomDictionary();
8502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestingProfile profile2;
8512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service2 =
8522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<SpellcheckService*>(
8532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
8542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              &profile2, &BuildSpellcheckService));
8552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary2 =
8562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service2->GetCustomDictionary();
8572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WordList to_add;
8592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0;
8602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS / 2;
8612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++i) {
8622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    to_add.push_back("foo" + base::Uint64ToString(i));
8632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Apply(*custom_dictionary, SpellcheckCustomDictionary::Change(to_add));
8652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int error_counter = 0;
867a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_FALSE(
868a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      custom_dictionary->MergeDataAndStartSyncing(
869a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             syncer::DICTIONARY,
870a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             custom_dictionary2->GetAllSyncData(
871a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 syncer::DICTIONARY),
872a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             scoped_ptr<syncer::SyncChangeProcessor>(
873a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 new syncer::SyncChangeProcessorWrapperForTest(
874a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     custom_dictionary2)),
875a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             scoped_ptr<syncer::SyncErrorFactory>(
876a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 new SyncErrorFactoryStub(&error_counter)))
877a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          .error()
878a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          .IsSet());
8792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, error_counter);
8802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(custom_dictionary->IsSyncing());
8812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OnLoaded(*custom_dictionary, to_add);
8832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, error_counter);
8842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(custom_dictionary->IsSyncing());
8852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS / 2,
8872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary->GetWords().size());
8882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS / 2,
8892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary2->GetWords().size());
8902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS / 2,
8922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary->GetAllSyncData(syncer::DICTIONARY).size());
8932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS / 2,
8942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary2->GetAllSyncData(syncer::DICTIONARY).size());
8952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, DictionaryLoadNotification) {
8982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service =
899d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      SpellcheckServiceFactory::GetForContext(&profile_);
9002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary =
9012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service->GetCustomDictionary();
9022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DictionaryObserverCounter observer;
9042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary->AddObserver(&observer);
9052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WordList custom_words;
9072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_words.push_back("foo");
9082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_words.push_back("bar");
9092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OnLoaded(*custom_dictionary, custom_words);
9102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_GE(observer.loads(), 1);
9122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_LE(observer.loads(), 2);
9132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, observer.changes());
9142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary->RemoveObserver(&observer);
9162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, DictionaryAddWordNotification) {
9192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service =
920d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      SpellcheckServiceFactory::GetForContext(&profile_);
9212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary =
9222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service->GetCustomDictionary();
9232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OnLoaded(*custom_dictionary, WordList());
9252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DictionaryObserverCounter observer;
9272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary->AddObserver(&observer);
9282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(custom_dictionary->AddWord("foo"));
9302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(custom_dictionary->AddWord("bar"));
9312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(custom_dictionary->AddWord("bar"));
9322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(2, observer.changes());
9342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary->RemoveObserver(&observer);
9362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, DictionaryRemoveWordNotification) {
9392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service =
940d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      SpellcheckServiceFactory::GetForContext(&profile_);
9412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary =
9422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service->GetCustomDictionary();
9432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OnLoaded(*custom_dictionary, WordList());
9452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(custom_dictionary->AddWord("foo"));
9472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(custom_dictionary->AddWord("bar"));
9482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DictionaryObserverCounter observer;
9502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary->AddObserver(&observer);
9512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(custom_dictionary->RemoveWord("foo"));
9532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(custom_dictionary->RemoveWord("bar"));
9542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(custom_dictionary->RemoveWord("baz"));
9552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(2, observer.changes());
9572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary->RemoveObserver(&observer);
9592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, DictionarySyncNotification) {
9622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service =
963d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      SpellcheckServiceFactory::GetForContext(&profile_);
9642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary =
9652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service->GetCustomDictionary();
9662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestingProfile profile2;
9672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service2 =
9682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<SpellcheckService*>(
9692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
9702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              &profile2, &BuildSpellcheckService));
9712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary2 =
9722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service2->GetCustomDictionary();
9732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OnLoaded(*custom_dictionary, WordList());
9752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OnLoaded(*custom_dictionary2, WordList());
9762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary->AddWord("foo");
9782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary->AddWord("bar");
9792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary2->AddWord("foo");
9802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary2->AddWord("baz");
9812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DictionaryObserverCounter observer;
9832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary->AddObserver(&observer);
9842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DictionaryObserverCounter observer2;
9862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary2->AddObserver(&observer2);
9872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int error_counter = 0;
989a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_FALSE(
990a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      custom_dictionary->MergeDataAndStartSyncing(
991a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             syncer::DICTIONARY,
992a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             custom_dictionary2->GetAllSyncData(
993a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 syncer::DICTIONARY),
994a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             scoped_ptr<syncer::SyncChangeProcessor>(
995a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 new syncer::SyncChangeProcessorWrapperForTest(
996a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     custom_dictionary2)),
997a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             scoped_ptr<syncer::SyncErrorFactory>(
998a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 new SyncErrorFactoryStub(&error_counter)))
999a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          .error()
1000a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          .IsSet());
10012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, error_counter);
10022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(custom_dictionary->IsSyncing());
10032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(1, observer.changes());
10052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(1, observer2.changes());
10062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary->RemoveObserver(&observer);
10082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary2->RemoveObserver(&observer2);
10092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The server has maximum number of words and the client has maximum number of
10122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// different words before association time. No new words should be pushed to the
10132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// sync server upon association. The client should accept words from the sync
10142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// server, however.
10152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, DictionarySyncLimit) {
10162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestingProfile server_profile;
10172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* server_spellcheck_service =
10182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<SpellcheckService*>(
10192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
10202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              &server_profile, &BuildSpellcheckService));
10212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Here, |server_custom_dictionary| plays the role of the sync server.
10232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* server_custom_dictionary =
10242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      server_spellcheck_service->GetCustomDictionary();
10252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Upload the maximum number of words to the sync server.
10272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
10282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SpellcheckService* spellcheck_service =
1029d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        SpellcheckServiceFactory::GetForContext(&profile_);
10302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SpellcheckCustomDictionary* custom_dictionary =
10312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        spellcheck_service->GetCustomDictionary();
10322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SpellcheckCustomDictionary::Change change;
10342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (size_t i = 0;
10352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS;
10362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         ++i) {
10372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      change.AddWord("foo" + base::Uint64ToString(i));
10382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
10392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Apply(*custom_dictionary, change);
10402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int error_counter = 0;
1042a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    EXPECT_FALSE(
1043a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        custom_dictionary
1044a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            ->MergeDataAndStartSyncing(
1045a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                  syncer::DICTIONARY,
1046a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                  server_custom_dictionary->GetAllSyncData(syncer::DICTIONARY),
1047a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                  scoped_ptr<syncer::SyncChangeProcessor>(
1048a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                      new syncer::SyncChangeProcessorWrapperForTest(
1049a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                          server_custom_dictionary)),
1050a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                  scoped_ptr<syncer::SyncErrorFactory>(
1051a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                      new SyncErrorFactoryStub(&error_counter)))
1052a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            .error()
1053a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            .IsSet());
10542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(0, error_counter);
10552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_TRUE(custom_dictionary->IsSyncing());
10562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
10572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              custom_dictionary->GetWords().size());
10582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
10592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The sync server now has the maximum number of words.
10612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
10622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            server_custom_dictionary->GetWords().size());
10632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Associate the sync server with a client that also has the maximum number of
10652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // words, but all of these words are different from the ones on the sync
10662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // server.
10672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
10682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TestingProfile client_profile;
10692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SpellcheckService* client_spellcheck_service =
10702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        static_cast<SpellcheckService*>(
10712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
10722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                &client_profile, &BuildSpellcheckService));
10732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Here, |client_custom_dictionary| plays the role of the client.
10752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SpellcheckCustomDictionary* client_custom_dictionary =
10762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        client_spellcheck_service->GetCustomDictionary();
10772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Add the maximum number of words to the client. These words are all
10792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // different from those on the server.
10802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SpellcheckCustomDictionary::Change change;
10812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (size_t i = 0;
10822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS;
10832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         ++i) {
10842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      change.AddWord("bar" + base::Uint64ToString(i));
10852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
10862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Apply(*client_custom_dictionary, change);
10872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Associate the server and the client.
10892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int error_counter = 0;
1090a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    EXPECT_FALSE(
1091a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        client_custom_dictionary
1092a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            ->MergeDataAndStartSyncing(
1093a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                  syncer::DICTIONARY,
1094a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                  server_custom_dictionary->GetAllSyncData(syncer::DICTIONARY),
1095a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                  scoped_ptr<syncer::SyncChangeProcessor>(
1096a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                      new syncer::SyncChangeProcessorWrapperForTest(
1097a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                          server_custom_dictionary)),
1098a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                  scoped_ptr<syncer::SyncErrorFactory>(
1099a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                      new SyncErrorFactoryStub(&error_counter)))
1100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            .error()
1101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            .IsSet());
11022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(0, error_counter);
11032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_FALSE(client_custom_dictionary->IsSyncing());
11042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS * 2,
11052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              client_custom_dictionary->GetWords().size());
11062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
11072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The sync server should not receive more words, because it has the maximum
11092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // number of words already.
11102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
11112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            server_custom_dictionary->GetWords().size());
11122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, RecordSizeStatsCorrectly) {
11153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#if defined(OS_WIN)
11163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Failing consistently on Win7. See crbug.com/230534.
11173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (base::win::GetVersion() >= base::win::VERSION_VISTA)
11183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return;
11193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#endif
1120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Record a baseline.
1121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SpellCheckHostMetrics::RecordCustomWordCountStats(123);
1122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
11233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Determine if test failures are due the statistics recorder not being
11243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // available or because the histogram just isn't there: crbug.com/230534.
11253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_TRUE(StatisticsRecorder::IsActive());
11263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  HistogramBase* histogram =
1128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      StatisticsRecorder::FindHistogram("SpellCheck.CustomWords");
1129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(histogram != NULL);
1130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<HistogramSamples> baseline = histogram->SnapshotSamples();
1131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Load the dictionary which should be empty.
1133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::FilePath path =
1134a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      profile_.GetPath().Append(chrome::kCustomDictionaryFileName);
1135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  WordList loaded_custom_words = LoadDictionaryFile(path);
1136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(0u, loaded_custom_words.size());
1137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // We expect there to be an entry with 0.
1139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  histogram =
1140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      StatisticsRecorder::FindHistogram("SpellCheck.CustomWords");
1141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(histogram != NULL);
1142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<HistogramSamples> samples = histogram->SnapshotSamples();
1143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  samples->Subtract(*baseline);
1145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(0,samples->sum());
1146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SpellcheckCustomDictionary::Change change;
1148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  change.AddWord("bar");
1149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  change.AddWord("foo");
1150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  UpdateDictionaryFile(change, path);
1151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Load the dictionary again and it should have 2 entries.
1153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  loaded_custom_words = LoadDictionaryFile(path);
1154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(2u, loaded_custom_words.size());
1155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  histogram =
1157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      StatisticsRecorder::FindHistogram("SpellCheck.CustomWords");
1158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(histogram != NULL);
1159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<HistogramSamples> samples2 = histogram->SnapshotSamples();
1160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  samples2->Subtract(*baseline);
1162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(2,samples2->sum());
1163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
116490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
116590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, HasWord) {
116690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SpellcheckService* spellcheck_service =
1167d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      SpellcheckServiceFactory::GetForContext(&profile_);
116890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary =
116990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spellcheck_service->GetCustomDictionary();
117090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  OnLoaded(*custom_dictionary, WordList());
117190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_FALSE(custom_dictionary->HasWord("foo"));
117290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_FALSE(custom_dictionary->HasWord("bar"));
117390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  custom_dictionary->AddWord("foo");
117490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(custom_dictionary->HasWord("foo"));
117590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_FALSE(custom_dictionary->HasWord("bar"));
117690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
1177