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"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/api/sync_data.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/api/sync_error_factory.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/api/sync_error_factory_mock.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/protocol/sync.pb.h"
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#if defined(OS_WIN)
293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// For version specific disabled tests below (http://crbug.com/230534).
303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/win/windows_version.h"
313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#endif
323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using base::HistogramBase;
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using base::HistogramSamples;
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using base::StatisticsRecorder;
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using chrome::spellcheck_common::WordList;
3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using chrome::spellcheck_common::WordSet;
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Get all sync data for the custom dictionary without limiting to maximum
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// number of syncable words.
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)syncer::SyncDataList GetAllSyncDataNoLimit(
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SpellcheckCustomDictionary* dictionary) {
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  syncer::SyncDataList data;
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string word;
4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const WordSet& words = dictionary->GetWords();
4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (WordSet::const_iterator it = words.begin(); it != words.end(); ++it) {
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    word = *it;
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_pb::EntitySpecifics specifics;
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    specifics.mutable_dictionary()->set_word(word);
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    data.push_back(syncer::SyncData::CreateLocalData(word, word, specifics));
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return data;
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static BrowserContextKeyedService* BuildSpellcheckService(
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    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)// A wrapper around SpellcheckCustomDictionary that does not own the wrapped
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// object. An instance of this class can be inside of a scoped pointer safely
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// while the dictionary is managed by another scoped pointer.
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class SyncChangeProcessorDelegate : public syncer::SyncChangeProcessor {
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  explicit SyncChangeProcessorDelegate(SpellcheckCustomDictionary* dictionary)
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : dictionary_(dictionary) {}
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~SyncChangeProcessorDelegate() {}
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Overridden from syncer::SyncChangeProcessor:
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual syncer::SyncError ProcessSyncChanges(
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const tracked_objects::Location& from_here,
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const syncer::SyncChangeList& change_list) OVERRIDE {
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return dictionary_->ProcessSyncChanges(from_here, change_list);
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  virtual syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const
13158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      OVERRIDE {
13258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return syncer::SyncDataList();
13358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
13458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* dictionary_;
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SyncChangeProcessorDelegate);
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// An implementation of SyncErrorFactory that does not upload the error message
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// and updates an outside error counter. This lets us know the number of error
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// messages in an instance of this class after that instance is deleted.
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class SyncErrorFactoryStub : public syncer::SyncErrorFactory {
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  explicit SyncErrorFactoryStub(int* error_counter)
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : error_counter_(error_counter) {}
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~SyncErrorFactoryStub() {}
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Overridden from syncer::SyncErrorFactory:
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual syncer::SyncError CreateAndUploadError(
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const tracked_objects::Location& location,
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const std::string& message) OVERRIDE {
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    (*error_counter_)++;
154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return syncer::SyncError(location,
155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                             syncer::SyncError::DATATYPE_ERROR,
156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                             message,
157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                             syncer::DICTIONARY);
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int* error_counter_;
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SyncErrorFactoryStub);
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Counts the number of notifications for dictionary load and change.
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class DictionaryObserverCounter : public SpellcheckCustomDictionary::Observer {
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DictionaryObserverCounter() : loads_(0), changes_(0) {}
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~DictionaryObserverCounter() {}
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int loads() const { return loads_; }
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int changes() const { return changes_; }
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Overridden from SpellcheckCustomDictionary::Observer:
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnCustomDictionaryLoaded() OVERRIDE { loads_++; }
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnCustomDictionaryChanged(
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const SpellcheckCustomDictionary::Change& change) OVERRIDE { changes_++; }
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int loads_;
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int changes_;
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(DictionaryObserverCounter);
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, SaveAndLoad) {
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath path =
187a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      profile_.GetPath().Append(chrome::kCustomDictionaryFileName);
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WordList loaded_custom_words = LoadDictionaryFile(path);
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The custom word list should be empty now.
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WordList expected;
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(expected, loaded_custom_words);
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary::Change change;
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  change.AddWord("bar");
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  change.AddWord("foo");
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateDictionaryFile(change, path);
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected.push_back("bar");
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected.push_back("foo");
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The custom word list should include written words.
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  loaded_custom_words = LoadDictionaryFile(path);
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(expected, loaded_custom_words);
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  change = SpellcheckCustomDictionary::Change();
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  change.RemoveWord("bar");
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  change.RemoveWord("foo");
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateDictionaryFile(change, path);
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  loaded_custom_words = LoadDictionaryFile(path);
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected.clear();
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(expected, loaded_custom_words);
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, MultiProfile) {
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service =
217d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      SpellcheckServiceFactory::GetForContext(&profile_);
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary =
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service->GetCustomDictionary();
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestingProfile profile2;
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service2 =
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<SpellcheckService*>(
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              &profile2, &BuildSpellcheckService));
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary2 =
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service2->GetCustomDictionary();
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
22890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  WordSet expected1;
22990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  WordSet expected2;
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary->AddWord("foo");
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary->AddWord("bar");
23390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  expected1.insert("foo");
23490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  expected1.insert("bar");
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary2->AddWord("hoge");
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary2->AddWord("fuga");
23890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  expected2.insert("hoge");
23990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  expected2.insert("fuga");
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
24190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  WordSet actual1 = custom_dictionary->GetWords();
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(actual1, expected1);
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
24490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  WordSet actual2 = custom_dictionary2->GetWords();
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(actual2, expected2);
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Legacy empty dictionary should be converted to new format empty dictionary.
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, LegacyEmptyDictionaryShouldBeConverted) {
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath path =
251a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      profile_.GetPath().Append(chrome::kCustomDictionaryFileName);
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string content;
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  file_util::WriteFile(path, content.c_str(), content.length());
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WordList loaded_custom_words = LoadDictionaryFile(path);
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(loaded_custom_words.empty());
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Legacy dictionary with two words should be converted to new format dictionary
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// with two words.
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest,
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       LegacyDictionaryWithTwoWordsShouldBeConverted) {
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath path =
264a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      profile_.GetPath().Append(chrome::kCustomDictionaryFileName);
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string content = "foo\nbar\nfoo\n";
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  file_util::WriteFile(path, content.c_str(), content.length());
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WordList loaded_custom_words = LoadDictionaryFile(path);
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WordList expected;
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected.push_back("bar");
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected.push_back("foo");
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(expected, loaded_custom_words);
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Illegal words should be removed. Leading and trailing whitespace should be
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// trimmed.
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest,
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       IllegalWordsShouldBeRemovedFromDictionary) {
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath path =
280a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      profile_.GetPath().Append(chrome::kCustomDictionaryFileName);
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string content = "foo\n foo bar \n\n \nbar\n"
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "01234567890123456789012345678901234567890123456789"
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "01234567890123456789012345678901234567890123456789";
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  file_util::WriteFile(path, content.c_str(), content.length());
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WordList loaded_custom_words = LoadDictionaryFile(path);
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WordList expected;
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected.push_back("bar");
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected.push_back("foo");
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected.push_back("foo bar");
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(expected, loaded_custom_words);
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Write to dictionary should backup previous version and write the word to the
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// end of the dictionary. If the dictionary file is corrupted on disk, the
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// previous version should be reloaded.
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, CorruptedWriteShouldBeRecovered) {
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath path =
299a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      profile_.GetPath().Append(chrome::kCustomDictionaryFileName);
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string content = "foo\nbar";
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  file_util::WriteFile(path, content.c_str(), content.length());
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WordList loaded_custom_words = LoadDictionaryFile(path);
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WordList expected;
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected.push_back("bar");
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected.push_back("foo");
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(expected, loaded_custom_words);
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary::Change change;
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  change.AddWord("baz");
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateDictionaryFile(change, path);
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content.clear();
31358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  base::ReadFileToString(path, &content);
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content.append("corruption");
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  file_util::WriteFile(path, content.c_str(), content.length());
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  loaded_custom_words = LoadDictionaryFile(path);
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(expected, loaded_custom_words);
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest,
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       GetAllSyncDataAccuratelyReflectsDictionaryState) {
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* dictionary =
323d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      SpellcheckServiceFactory::GetForContext(
324a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch          &profile_)->GetCustomDictionary();
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  syncer::SyncDataList data = dictionary->GetAllSyncData(syncer::DICTIONARY);
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.empty());
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(dictionary->AddWord("bar"));
33090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(dictionary->AddWord("foo"));
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data = dictionary->GetAllSyncData(syncer::DICTIONARY);
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(2UL, data.size());
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::string> words;
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  words.push_back("bar");
33690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  words.push_back("foo");
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < data.size(); i++) {
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_TRUE(data[i].GetSpecifics().has_dictionary());
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(syncer::DICTIONARY, data[i].GetDataType());
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(words[i], data[i].GetTag());
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(words[i], data[i].GetSpecifics().dictionary().word());
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(dictionary->RemoveWord("bar"));
34590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(dictionary->RemoveWord("foo"));
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data = dictionary->GetAllSyncData(syncer::DICTIONARY);
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(data.empty());
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, GetAllSyncDataHasLimit) {
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* dictionary =
353d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      SpellcheckServiceFactory::GetForContext(
354a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch          &profile_)->GetCustomDictionary();
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary::Change change;
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0;
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS - 1;
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       i++) {
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    change.AddWord("foo" + base::Uint64ToString(i));
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Apply(*dictionary, change);
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS - 1,
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            dictionary->GetWords().size());
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS - 1,
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            dictionary->GetAllSyncData(syncer::DICTIONARY).size());
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dictionary->AddWord("baz");
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            dictionary->GetWords().size());
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            dictionary->GetAllSyncData(syncer::DICTIONARY).size());
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dictionary->AddWord("bar");
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1,
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            dictionary->GetWords().size());
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            dictionary->GetAllSyncData(syncer::DICTIONARY).size());
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dictionary->AddWord("snafoo");
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 2,
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            dictionary->GetWords().size());
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            dictionary->GetAllSyncData(syncer::DICTIONARY).size());
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, ProcessSyncChanges) {
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service =
389d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      SpellcheckServiceFactory::GetForContext(&profile_);
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* dictionary =
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service->GetCustomDictionary();
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dictionary->AddWord("foo");
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dictionary->AddWord("bar");
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  syncer::SyncChangeList changes;
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Add existing word.
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string word = "foo";
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_pb::EntitySpecifics specifics;
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    specifics.mutable_dictionary()->set_word(word);
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    changes.push_back(syncer::SyncChange(
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE,
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        syncer::SyncChange::ACTION_ADD,
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        syncer::SyncData::CreateLocalData(word, word, specifics)));
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Add invalid word. This word is too long.
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string word = "01234567890123456789012345678901234567890123456789"
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "01234567890123456789012345678901234567890123456789";
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_pb::EntitySpecifics specifics;
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    specifics.mutable_dictionary()->set_word(word);
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    changes.push_back(syncer::SyncChange(
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE,
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        syncer::SyncChange::ACTION_ADD,
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        syncer::SyncData::CreateLocalData(word, word, specifics)));
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Add valid word.
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string word = "baz";
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_pb::EntitySpecifics specifics;
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    specifics.mutable_dictionary()->set_word(word);
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    changes.push_back(syncer::SyncChange(
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE,
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        syncer::SyncChange::ACTION_ADD,
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        syncer::SyncData::CreateLocalData(word, word, specifics)));
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Remove missing word.
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string word = "snafoo";
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_pb::EntitySpecifics specifics;
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    specifics.mutable_dictionary()->set_word(word);
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    changes.push_back(syncer::SyncChange(
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE,
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        syncer::SyncChange::ACTION_DELETE,
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        syncer::SyncData::CreateLocalData(word, word, specifics)));
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Remove existing word.
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string word = "bar";
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sync_pb::EntitySpecifics specifics;
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    specifics.mutable_dictionary()->set_word(word);
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    changes.push_back(syncer::SyncChange(
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE,
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        syncer::SyncChange::ACTION_DELETE,
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        syncer::SyncData::CreateLocalData(word, word, specifics)));
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(dictionary->ProcessSyncChanges(FROM_HERE, changes).IsSet());
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
45190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const WordSet& words = dictionary->GetWords();
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(2UL, words.size());
45390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(0UL, words.count("bar"));
45490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(1UL, words.count("foo"));
45590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(1UL, words.count("baz"));
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, MergeDataAndStartSyncing) {
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service =
460d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      SpellcheckServiceFactory::GetForContext(&profile_);
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary =
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service->GetCustomDictionary();
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestingProfile profile2;
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service2 =
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<SpellcheckService*>(
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              &profile2, &BuildSpellcheckService));
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary2 =
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service2->GetCustomDictionary();
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary::Change change;
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0;
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS / 2;
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++i) {
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    change.AddWord("foo" + base::Uint64ToString(i));
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Apply(*custom_dictionary, change);
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary::Change change2;
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0;
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS / 2;
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++i) {
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    change2.AddWord("bar" + base::Uint64ToString(i));
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Apply(*custom_dictionary2, change2);
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int error_counter = 0;
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(custom_dictionary->MergeDataAndStartSyncing(
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      syncer::DICTIONARY,
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      custom_dictionary2->GetAllSyncData(syncer::DICTIONARY),
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      scoped_ptr<syncer::SyncChangeProcessor>(
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          new SyncChangeProcessorDelegate(custom_dictionary2)),
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      scoped_ptr<syncer::SyncErrorFactory>(
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          new SyncErrorFactoryStub(&error_counter))).error().IsSet());
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, error_counter);
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(custom_dictionary->IsSyncing());
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
49890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  WordSet words = custom_dictionary->GetWords();
49990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  WordSet words2 = custom_dictionary2->GetWords();
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(words.size(), words2.size());
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(words, words2);
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, DictionaryTooBigBeforeSyncing) {
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service =
506d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      SpellcheckServiceFactory::GetForContext(&profile_);
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary =
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service->GetCustomDictionary();
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestingProfile profile2;
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service2 =
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<SpellcheckService*>(
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              &profile2, &BuildSpellcheckService));
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary2 =
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service2->GetCustomDictionary();
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary::Change change;
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0;
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1;
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++i) {
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    change.AddWord("foo" + base::Uint64ToString(i));
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Apply(*custom_dictionary, change);
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int error_counter = 0;
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(custom_dictionary->MergeDataAndStartSyncing(
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      syncer::DICTIONARY,
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      custom_dictionary2->GetAllSyncData(syncer::DICTIONARY),
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      scoped_ptr<syncer::SyncChangeProcessor>(
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          new SyncChangeProcessorDelegate(custom_dictionary2)),
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      scoped_ptr<syncer::SyncErrorFactory>(
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          new SyncErrorFactoryStub(&error_counter))).error().IsSet());
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, error_counter);
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(custom_dictionary->IsSyncing());
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1,
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary->GetWords().size());
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary2->GetWords().size());
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary->GetAllSyncData(syncer::DICTIONARY).size());
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary2->GetAllSyncData(syncer::DICTIONARY).size());
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, DictionaryTooBigAndServerFull) {
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service =
549d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      SpellcheckServiceFactory::GetForContext(&profile_);
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary =
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service->GetCustomDictionary();
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestingProfile profile2;
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service2 =
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<SpellcheckService*>(
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              &profile2, &BuildSpellcheckService));
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary2 =
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service2->GetCustomDictionary();
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary::Change change;
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary::Change change2;
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0;
5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS;
5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++i) {
5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    change.AddWord("foo" + base::Uint64ToString(i));
5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    change2.AddWord("bar" + base::Uint64ToString(i));
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  change.AddWord("foo");
5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Apply(*custom_dictionary, change);
5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Apply(*custom_dictionary2, change2);
5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1,
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary->GetWords().size());
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary2->GetWords().size());
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int error_counter = 0;
5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(custom_dictionary->MergeDataAndStartSyncing(
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      syncer::DICTIONARY,
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      custom_dictionary2->GetAllSyncData(syncer::DICTIONARY),
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      scoped_ptr<syncer::SyncChangeProcessor>(
5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          new SyncChangeProcessorDelegate(custom_dictionary2)),
5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      scoped_ptr<syncer::SyncErrorFactory>(
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          new SyncErrorFactoryStub(&error_counter))).error().IsSet());
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, error_counter);
5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(custom_dictionary->IsSyncing());
5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS * 2 + 1,
5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary->GetWords().size());
5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary2->GetWords().size());
5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary->GetAllSyncData(syncer::DICTIONARY).size());
5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary2->GetAllSyncData(syncer::DICTIONARY).size());
5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, ServerTooBig) {
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service =
601d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      SpellcheckServiceFactory::GetForContext(&profile_);
6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary =
6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service->GetCustomDictionary();
6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestingProfile profile2;
6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service2 =
6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<SpellcheckService*>(
6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              &profile2, &BuildSpellcheckService));
6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary2 =
6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service2->GetCustomDictionary();
6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary::Change change;
6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary::Change change2;
6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0;
6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1;
6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++i) {
6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    change.AddWord("foo" + base::Uint64ToString(i));
6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    change2.AddWord("bar" + base::Uint64ToString(i));
6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Apply(*custom_dictionary, change);
6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Apply(*custom_dictionary2, change2);
6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1,
6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary->GetWords().size());
6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1,
6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary2->GetWords().size());
6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int error_counter = 0;
6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(custom_dictionary->MergeDataAndStartSyncing(
6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      syncer::DICTIONARY,
6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetAllSyncDataNoLimit(custom_dictionary2),
6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      scoped_ptr<syncer::SyncChangeProcessor>(
6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          new SyncChangeProcessorDelegate(custom_dictionary2)),
6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      scoped_ptr<syncer::SyncErrorFactory>(
6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          new SyncErrorFactoryStub(&error_counter))).error().IsSet());
6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, error_counter);
6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(custom_dictionary->IsSyncing());
6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS * 2 + 2,
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary->GetWords().size());
6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1,
6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary2->GetWords().size());
6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary->GetAllSyncData(syncer::DICTIONARY).size());
6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary2->GetAllSyncData(syncer::DICTIONARY).size());
6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, DictionaryTooBigToStartSyncing) {
6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service =
652d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      SpellcheckServiceFactory::GetForContext(&profile_);
6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary =
6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service->GetCustomDictionary();
6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestingProfile profile2;
6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service2 =
6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<SpellcheckService*>(
6582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
6592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              &profile2, &BuildSpellcheckService));
6602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary2 =
6612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service2->GetCustomDictionary();
6622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary::Change change;
6642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0;
6652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS - 1;
6662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++i) {
6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    change.AddWord("foo" + base::Uint64ToString(i));
6682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Apply(*custom_dictionary, change);
6702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary2->AddWord("bar");
6722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary2->AddWord("baz");
6732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int error_counter = 0;
6752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(custom_dictionary->MergeDataAndStartSyncing(
6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      syncer::DICTIONARY,
6772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      custom_dictionary2->GetAllSyncData(syncer::DICTIONARY),
6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      scoped_ptr<syncer::SyncChangeProcessor>(
6792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          new SyncChangeProcessorDelegate(custom_dictionary2)),
6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      scoped_ptr<syncer::SyncErrorFactory>(
6812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          new SyncErrorFactoryStub(&error_counter))).error().IsSet());
6822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, error_counter);
6832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(custom_dictionary->IsSyncing());
6842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1,
6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary->GetWords().size());
6872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary2->GetWords().size());
6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary->GetAllSyncData(syncer::DICTIONARY).size());
6922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
6932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary2->GetAllSyncData(syncer::DICTIONARY).size());
6942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, DictionaryTooBigToContiueSyncing) {
6972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service =
698d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      SpellcheckServiceFactory::GetForContext(&profile_);
6992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary =
7002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service->GetCustomDictionary();
7012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestingProfile profile2;
7022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service2 =
7032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<SpellcheckService*>(
7042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              &profile2, &BuildSpellcheckService));
7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary2 =
7072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service2->GetCustomDictionary();
7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary::Change change;
7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0;
7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS - 1;
7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++i) {
7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    change.AddWord("foo" + base::Uint64ToString(i));
7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Apply(*custom_dictionary, change);
7162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int error_counter = 0;
7182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(custom_dictionary->MergeDataAndStartSyncing(
7192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      syncer::DICTIONARY,
7202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      custom_dictionary2->GetAllSyncData(syncer::DICTIONARY),
7212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      scoped_ptr<syncer::SyncChangeProcessor>(
7222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          new SyncChangeProcessorDelegate(custom_dictionary2)),
7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      scoped_ptr<syncer::SyncErrorFactory>(
7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          new SyncErrorFactoryStub(&error_counter))).error().IsSet());
7252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, error_counter);
7262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(custom_dictionary->IsSyncing());
7272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary->AddWord("bar");
7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, error_counter);
7302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(custom_dictionary->IsSyncing());
7312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary->AddWord("baz");
7332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, error_counter);
7342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(custom_dictionary->IsSyncing());
7352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1,
7372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary->GetWords().size());
7382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
7392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary2->GetWords().size());
7402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
7422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary->GetAllSyncData(syncer::DICTIONARY).size());
7432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
7442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary2->GetAllSyncData(syncer::DICTIONARY).size());
7452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, LoadAfterSyncStart) {
7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service =
749d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      SpellcheckServiceFactory::GetForContext(&profile_);
7502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary =
7512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service->GetCustomDictionary();
7522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestingProfile profile2;
7532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service2 =
7542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<SpellcheckService*>(
7552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
7562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              &profile2, &BuildSpellcheckService));
7572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary2 =
7582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service2->GetCustomDictionary();
7592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary->AddWord("foo");
7612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int error_counter = 0;
7632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(custom_dictionary->MergeDataAndStartSyncing(
7642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      syncer::DICTIONARY,
7652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      custom_dictionary2->GetAllSyncData(syncer::DICTIONARY),
7662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      scoped_ptr<syncer::SyncChangeProcessor>(
7672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          new SyncChangeProcessorDelegate(custom_dictionary2)),
7682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      scoped_ptr<syncer::SyncErrorFactory>(
7692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          new SyncErrorFactoryStub(&error_counter))).error().IsSet());
7702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, error_counter);
7712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(custom_dictionary->IsSyncing());
7722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WordList custom_words;
7742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_words.push_back("bar");
7752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OnLoaded(*custom_dictionary, custom_words);
7762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(custom_dictionary->IsSyncing());
7772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(2UL, custom_dictionary->GetWords().size());
7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(2UL, custom_dictionary2->GetWords().size());
7802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(2UL, custom_dictionary->GetAllSyncData(syncer::DICTIONARY).size());
7822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(2UL, custom_dictionary2->GetAllSyncData(syncer::DICTIONARY).size());
7832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, LoadAfterSyncStartTooBigToSync) {
7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service =
787d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      SpellcheckServiceFactory::GetForContext(&profile_);
7882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary =
7892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service->GetCustomDictionary();
7902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestingProfile profile2;
7912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service2 =
7922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<SpellcheckService*>(
7932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
7942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              &profile2, &BuildSpellcheckService));
7952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary2 =
7962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service2->GetCustomDictionary();
7972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary->AddWord("foo");
7992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int error_counter = 0;
8012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(custom_dictionary->MergeDataAndStartSyncing(
8022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      syncer::DICTIONARY,
8032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      custom_dictionary2->GetAllSyncData(syncer::DICTIONARY),
8042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      scoped_ptr<syncer::SyncChangeProcessor>(
8052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          new SyncChangeProcessorDelegate(custom_dictionary2)),
8062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      scoped_ptr<syncer::SyncErrorFactory>(
8072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          new SyncErrorFactoryStub(&error_counter))).error().IsSet());
8082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, error_counter);
8092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(custom_dictionary->IsSyncing());
8102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WordList custom_words;
8122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0;
8132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS;
8142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++i) {
8152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    custom_words.push_back("foo" + base::Uint64ToString(i));
8162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OnLoaded(*custom_dictionary, custom_words);
8182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, error_counter);
8192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(custom_dictionary->IsSyncing());
8202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS + 1,
8222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary->GetWords().size());
8232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
8242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary2->GetWords().size());
8252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
8272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary->GetAllSyncData(syncer::DICTIONARY).size());
8282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
8292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary2->GetAllSyncData(syncer::DICTIONARY).size());
8302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, LoadDuplicatesAfterSync) {
8332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service =
834d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      SpellcheckServiceFactory::GetForContext(&profile_);
8352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary =
8362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service->GetCustomDictionary();
8372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestingProfile profile2;
8382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service2 =
8392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<SpellcheckService*>(
8402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
8412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              &profile2, &BuildSpellcheckService));
8422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary2 =
8432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service2->GetCustomDictionary();
8442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WordList to_add;
8462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0;
8472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS / 2;
8482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++i) {
8492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    to_add.push_back("foo" + base::Uint64ToString(i));
8502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Apply(*custom_dictionary, SpellcheckCustomDictionary::Change(to_add));
8522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int error_counter = 0;
8542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(custom_dictionary->MergeDataAndStartSyncing(
8552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      syncer::DICTIONARY,
8562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      custom_dictionary2->GetAllSyncData(syncer::DICTIONARY),
8572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      scoped_ptr<syncer::SyncChangeProcessor>(
8582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          new SyncChangeProcessorDelegate(custom_dictionary2)),
8592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      scoped_ptr<syncer::SyncErrorFactory>(
8602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          new SyncErrorFactoryStub(&error_counter))).error().IsSet());
8612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, error_counter);
8622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(custom_dictionary->IsSyncing());
8632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OnLoaded(*custom_dictionary, to_add);
8652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, error_counter);
8662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(custom_dictionary->IsSyncing());
8672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS / 2,
8692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary->GetWords().size());
8702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS / 2,
8712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary2->GetWords().size());
8722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS / 2,
8742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary->GetAllSyncData(syncer::DICTIONARY).size());
8752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS / 2,
8762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            custom_dictionary2->GetAllSyncData(syncer::DICTIONARY).size());
8772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, DictionaryLoadNotification) {
8802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service =
881d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      SpellcheckServiceFactory::GetForContext(&profile_);
8822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary =
8832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service->GetCustomDictionary();
8842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DictionaryObserverCounter observer;
8862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary->AddObserver(&observer);
8872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WordList custom_words;
8892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_words.push_back("foo");
8902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_words.push_back("bar");
8912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OnLoaded(*custom_dictionary, custom_words);
8922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_GE(observer.loads(), 1);
8942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_LE(observer.loads(), 2);
8952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, observer.changes());
8962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary->RemoveObserver(&observer);
8982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, DictionaryAddWordNotification) {
9012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service =
902d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      SpellcheckServiceFactory::GetForContext(&profile_);
9032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary =
9042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service->GetCustomDictionary();
9052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OnLoaded(*custom_dictionary, WordList());
9072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DictionaryObserverCounter observer;
9092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary->AddObserver(&observer);
9102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(custom_dictionary->AddWord("foo"));
9122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(custom_dictionary->AddWord("bar"));
9132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(custom_dictionary->AddWord("bar"));
9142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(2, observer.changes());
9162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary->RemoveObserver(&observer);
9182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, DictionaryRemoveWordNotification) {
9212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service =
922d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      SpellcheckServiceFactory::GetForContext(&profile_);
9232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary =
9242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service->GetCustomDictionary();
9252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OnLoaded(*custom_dictionary, WordList());
9272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(custom_dictionary->AddWord("foo"));
9292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(custom_dictionary->AddWord("bar"));
9302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DictionaryObserverCounter observer;
9322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary->AddObserver(&observer);
9332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(custom_dictionary->RemoveWord("foo"));
9352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(custom_dictionary->RemoveWord("bar"));
9362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(custom_dictionary->RemoveWord("baz"));
9372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(2, observer.changes());
9392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary->RemoveObserver(&observer);
9412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, DictionarySyncNotification) {
9442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service =
945d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      SpellcheckServiceFactory::GetForContext(&profile_);
9462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary =
9472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service->GetCustomDictionary();
9482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestingProfile profile2;
9492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* spellcheck_service2 =
9502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<SpellcheckService*>(
9512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
9522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              &profile2, &BuildSpellcheckService));
9532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary2 =
9542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      spellcheck_service2->GetCustomDictionary();
9552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OnLoaded(*custom_dictionary, WordList());
9572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OnLoaded(*custom_dictionary2, WordList());
9582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary->AddWord("foo");
9602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary->AddWord("bar");
9612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary2->AddWord("foo");
9622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary2->AddWord("baz");
9632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DictionaryObserverCounter observer;
9652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary->AddObserver(&observer);
9662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DictionaryObserverCounter observer2;
9682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary2->AddObserver(&observer2);
9692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int error_counter = 0;
9712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(custom_dictionary->MergeDataAndStartSyncing(
9722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      syncer::DICTIONARY,
9732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      custom_dictionary2->GetAllSyncData(syncer::DICTIONARY),
9742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      scoped_ptr<syncer::SyncChangeProcessor>(
9752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          new SyncChangeProcessorDelegate(custom_dictionary2)),
9762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      scoped_ptr<syncer::SyncErrorFactory>(
9772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          new SyncErrorFactoryStub(&error_counter))).error().IsSet());
9782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, error_counter);
9792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(custom_dictionary->IsSyncing());
9802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(1, observer.changes());
9822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(1, observer2.changes());
9832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary->RemoveObserver(&observer);
9852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  custom_dictionary2->RemoveObserver(&observer2);
9862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The server has maximum number of words and the client has maximum number of
9892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// different words before association time. No new words should be pushed to the
9902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// sync server upon association. The client should accept words from the sync
9912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// server, however.
9922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, DictionarySyncLimit) {
9932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestingProfile server_profile;
9942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckService* server_spellcheck_service =
9952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<SpellcheckService*>(
9962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
9972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              &server_profile, &BuildSpellcheckService));
9982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Here, |server_custom_dictionary| plays the role of the sync server.
10002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SpellcheckCustomDictionary* server_custom_dictionary =
10012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      server_spellcheck_service->GetCustomDictionary();
10022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Upload the maximum number of words to the sync server.
10042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
10052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SpellcheckService* spellcheck_service =
1006d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        SpellcheckServiceFactory::GetForContext(&profile_);
10072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SpellcheckCustomDictionary* custom_dictionary =
10082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        spellcheck_service->GetCustomDictionary();
10092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SpellcheckCustomDictionary::Change change;
10112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (size_t i = 0;
10122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS;
10132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         ++i) {
10142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      change.AddWord("foo" + base::Uint64ToString(i));
10152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
10162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Apply(*custom_dictionary, change);
10172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int error_counter = 0;
10192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_FALSE(custom_dictionary->MergeDataAndStartSyncing(
10202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        syncer::DICTIONARY,
10212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        server_custom_dictionary->GetAllSyncData(syncer::DICTIONARY),
10222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        scoped_ptr<syncer::SyncChangeProcessor>(
10232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            new SyncChangeProcessorDelegate(server_custom_dictionary)),
10242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        scoped_ptr<syncer::SyncErrorFactory>(
10252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            new SyncErrorFactoryStub(&error_counter))).error().IsSet());
10262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(0, error_counter);
10272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_TRUE(custom_dictionary->IsSyncing());
10282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
10292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              custom_dictionary->GetWords().size());
10302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
10312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The sync server now has the maximum number of words.
10332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
10342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            server_custom_dictionary->GetWords().size());
10352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Associate the sync server with a client that also has the maximum number of
10372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // words, but all of these words are different from the ones on the sync
10382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // server.
10392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
10402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TestingProfile client_profile;
10412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SpellcheckService* client_spellcheck_service =
10422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        static_cast<SpellcheckService*>(
10432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
10442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                &client_profile, &BuildSpellcheckService));
10452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Here, |client_custom_dictionary| plays the role of the client.
10472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SpellcheckCustomDictionary* client_custom_dictionary =
10482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        client_spellcheck_service->GetCustomDictionary();
10492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Add the maximum number of words to the client. These words are all
10512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // different from those on the server.
10522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SpellcheckCustomDictionary::Change change;
10532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (size_t i = 0;
10542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         i < chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS;
10552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         ++i) {
10562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      change.AddWord("bar" + base::Uint64ToString(i));
10572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
10582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Apply(*client_custom_dictionary, change);
10592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Associate the server and the client.
10612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int error_counter = 0;
10622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_FALSE(client_custom_dictionary->MergeDataAndStartSyncing(
10632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        syncer::DICTIONARY,
10642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        server_custom_dictionary->GetAllSyncData(syncer::DICTIONARY),
10652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        scoped_ptr<syncer::SyncChangeProcessor>(
10662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            new SyncChangeProcessorDelegate(server_custom_dictionary)),
10672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        scoped_ptr<syncer::SyncErrorFactory>(
10682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            new SyncErrorFactoryStub(&error_counter))).error().IsSet());
10692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(0, error_counter);
10702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_FALSE(client_custom_dictionary->IsSyncing());
10712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS * 2,
10722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              client_custom_dictionary->GetWords().size());
10732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
10742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The sync server should not receive more words, because it has the maximum
10762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // number of words already.
10772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS,
10782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            server_custom_dictionary->GetWords().size());
10792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1080c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1081c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, RecordSizeStatsCorrectly) {
10823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#if defined(OS_WIN)
10833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Failing consistently on Win7. See crbug.com/230534.
10843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (base::win::GetVersion() >= base::win::VERSION_VISTA)
10853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return;
10863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#endif
1087c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Record a baseline.
1088c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SpellCheckHostMetrics::RecordCustomWordCountStats(123);
1089c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
10903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Determine if test failures are due the statistics recorder not being
10913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // available or because the histogram just isn't there: crbug.com/230534.
10923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_TRUE(StatisticsRecorder::IsActive());
10933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1094c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  HistogramBase* histogram =
1095c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      StatisticsRecorder::FindHistogram("SpellCheck.CustomWords");
1096c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(histogram != NULL);
1097c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<HistogramSamples> baseline = histogram->SnapshotSamples();
1098c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1099c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Load the dictionary which should be empty.
1100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::FilePath path =
1101a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      profile_.GetPath().Append(chrome::kCustomDictionaryFileName);
1102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  WordList loaded_custom_words = LoadDictionaryFile(path);
1103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(0u, loaded_custom_words.size());
1104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // We expect there to be an entry with 0.
1106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  histogram =
1107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      StatisticsRecorder::FindHistogram("SpellCheck.CustomWords");
1108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(histogram != NULL);
1109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<HistogramSamples> samples = histogram->SnapshotSamples();
1110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  samples->Subtract(*baseline);
1112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(0,samples->sum());
1113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SpellcheckCustomDictionary::Change change;
1115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  change.AddWord("bar");
1116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  change.AddWord("foo");
1117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  UpdateDictionaryFile(change, path);
1118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Load the dictionary again and it should have 2 entries.
1120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  loaded_custom_words = LoadDictionaryFile(path);
1121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(2u, loaded_custom_words.size());
1122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  histogram =
1124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      StatisticsRecorder::FindHistogram("SpellCheck.CustomWords");
1125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(histogram != NULL);
1126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<HistogramSamples> samples2 = histogram->SnapshotSamples();
1127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  samples2->Subtract(*baseline);
1129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(2,samples2->sum());
1130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
113190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
113290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TEST_F(SpellcheckCustomDictionaryTest, HasWord) {
113390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SpellcheckService* spellcheck_service =
1134d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      SpellcheckServiceFactory::GetForContext(&profile_);
113590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SpellcheckCustomDictionary* custom_dictionary =
113690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spellcheck_service->GetCustomDictionary();
113790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  OnLoaded(*custom_dictionary, WordList());
113890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_FALSE(custom_dictionary->HasWord("foo"));
113990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_FALSE(custom_dictionary->HasWord("bar"));
114090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  custom_dictionary->AddWord("foo");
114190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(custom_dictionary->HasWord("foo"));
114290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_FALSE(custom_dictionary->HasWord("bar"));
114390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
1144