1// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/sync/test/integration/dictionary_helper.h" 6 7#include <algorithm> 8 9#include "base/format_macros.h" 10#include "base/strings/stringprintf.h" 11#include "chrome/browser/profiles/profile.h" 12#include "chrome/browser/spellchecker/spellcheck_factory.h" 13#include "chrome/browser/spellchecker/spellcheck_service.h" 14#include "chrome/browser/sync/test/integration/dictionary_load_observer.h" 15#include "chrome/browser/sync/test/integration/multi_client_status_change_checker.h" 16#include "chrome/browser/sync/test/integration/profile_sync_service_harness.h" 17#include "chrome/browser/sync/test/integration/single_client_status_change_checker.h" 18#include "chrome/browser/sync/test/integration/sync_datatype_helper.h" 19#include "chrome/browser/sync/test/integration/sync_test.h" 20#include "chrome/common/chrome_switches.h" 21#include "chrome/common/spellcheck_common.h" 22#include "content/public/test/test_utils.h" 23 24class DictionarySyncIntegrationTestHelper { 25 public: 26 // Same as SpellcheckCustomDictionary::AddWord/RemoveWord, except does not 27 // write to disk. 28 static bool ApplyChange( 29 SpellcheckCustomDictionary* dictionary, 30 SpellcheckCustomDictionary::Change& change) { 31 int result = change.Sanitize(dictionary->GetWords()); 32 dictionary->Apply(change); 33 dictionary->Notify(change); 34 dictionary->Sync(change); 35 return !result; 36 } 37 38 DISALLOW_COPY_AND_ASSIGN(DictionarySyncIntegrationTestHelper); 39}; 40 41 42namespace dictionary_helper { 43namespace { 44 45SpellcheckCustomDictionary* GetDictionary(int index) { 46 return SpellcheckServiceFactory::GetForContext( 47 sync_datatype_helper::test()->GetProfile(index))->GetCustomDictionary(); 48} 49 50SpellcheckCustomDictionary* GetVerifierDictionary() { 51 return SpellcheckServiceFactory::GetForContext( 52 sync_datatype_helper::test()->verifier())->GetCustomDictionary(); 53} 54 55void LoadDictionary(SpellcheckCustomDictionary* dictionary) { 56 if (dictionary->IsLoaded()) 57 return; 58 base::RunLoop run_loop; 59 DictionaryLoadObserver observer(content::GetQuitTaskForRunLoop(&run_loop)); 60 dictionary->AddObserver(&observer); 61 dictionary->Load(); 62 content::RunThisRunLoop(&run_loop); 63 dictionary->RemoveObserver(&observer); 64 ASSERT_TRUE(dictionary->IsLoaded()); 65} 66 67} // namespace 68 69 70void LoadDictionaries() { 71 for (int i = 0; i < sync_datatype_helper::test()->num_clients(); ++i) 72 LoadDictionary(GetDictionary(i)); 73 if (sync_datatype_helper::test()->use_verifier()) 74 LoadDictionary(GetVerifierDictionary()); 75} 76 77size_t GetDictionarySize(int index) { 78 return GetDictionary(index)->GetWords().size(); 79} 80 81size_t GetVerifierDictionarySize() { 82 return GetVerifierDictionary()->GetWords().size(); 83} 84 85bool DictionariesMatch() { 86 const chrome::spellcheck_common::WordSet& reference = 87 sync_datatype_helper::test()->use_verifier() 88 ? GetVerifierDictionary()->GetWords() 89 : GetDictionary(0)->GetWords(); 90 for (int i = 0; i < sync_datatype_helper::test()->num_clients(); ++i) { 91 const chrome::spellcheck_common::WordSet& dictionary = 92 GetDictionary(i)->GetWords(); 93 if (reference.size() != dictionary.size() || 94 !std::equal(reference.begin(), reference.end(), dictionary.begin())) { 95 return false; 96 } 97 } 98 return true; 99} 100 101namespace { 102 103// Helper class used in the implementation of AwaitDictionariesMatch. 104class DictionaryMatchStatusChecker : public MultiClientStatusChangeChecker { 105 public: 106 DictionaryMatchStatusChecker(); 107 virtual ~DictionaryMatchStatusChecker(); 108 109 virtual bool IsExitConditionSatisfied() OVERRIDE; 110 virtual std::string GetDebugMessage() const OVERRIDE; 111}; 112 113DictionaryMatchStatusChecker::DictionaryMatchStatusChecker() 114 : MultiClientStatusChangeChecker( 115 sync_datatype_helper::test()->GetSyncServices()) {} 116 117DictionaryMatchStatusChecker::~DictionaryMatchStatusChecker() {} 118 119bool DictionaryMatchStatusChecker::IsExitConditionSatisfied() { 120 return DictionariesMatch(); 121} 122 123std::string DictionaryMatchStatusChecker::GetDebugMessage() const { 124 return "Waiting for matching dictionaries"; 125} 126 127// Helper class used in the implementation of AwaitNumDictionaryEntries. 128class NumDictionaryEntriesStatusChecker 129 : public SingleClientStatusChangeChecker { 130 public: 131 NumDictionaryEntriesStatusChecker(int index, size_t num_words); 132 virtual ~NumDictionaryEntriesStatusChecker(); 133 134 virtual bool IsExitConditionSatisfied() OVERRIDE; 135 virtual std::string GetDebugMessage() const OVERRIDE; 136 private: 137 int index_; 138 size_t num_words_; 139}; 140 141NumDictionaryEntriesStatusChecker::NumDictionaryEntriesStatusChecker( 142 int index, size_t num_words) 143 : SingleClientStatusChangeChecker( 144 sync_datatype_helper::test()->GetSyncService(index)), 145 index_(index), 146 num_words_(num_words) {} 147 148NumDictionaryEntriesStatusChecker::~NumDictionaryEntriesStatusChecker() {} 149 150bool NumDictionaryEntriesStatusChecker::IsExitConditionSatisfied() { 151 return GetDictionarySize(index_) == num_words_; 152} 153 154std::string NumDictionaryEntriesStatusChecker::GetDebugMessage() const { 155 return base::StringPrintf( 156 "Waiting for client %d: %" PRIuS " / %" PRIuS " words downloaded", 157 index_, GetDictionarySize(index_), num_words_); 158} 159 160} // namespace 161 162bool AwaitDictionariesMatch() { 163 DictionaryMatchStatusChecker checker; 164 checker.Wait(); 165 return !checker.TimedOut(); 166} 167 168bool AwaitNumDictionaryEntries(int index, size_t num_words) { 169 NumDictionaryEntriesStatusChecker checker(index, num_words); 170 checker.Wait(); 171 return !checker.TimedOut(); 172} 173 174bool DictionaryMatchesVerifier(int index) { 175 const chrome::spellcheck_common::WordSet& expected = 176 GetVerifierDictionary()->GetWords(); 177 const chrome::spellcheck_common::WordSet& actual = 178 GetDictionary(index)->GetWords(); 179 return expected.size() == actual.size() && 180 std::equal(expected.begin(), expected.end(), actual.begin()); 181} 182 183bool AddWord(int index, const std::string& word) { 184 SpellcheckCustomDictionary::Change dictionary_change; 185 dictionary_change.AddWord(word); 186 bool result = DictionarySyncIntegrationTestHelper::ApplyChange( 187 GetDictionary(index), dictionary_change); 188 if (sync_datatype_helper::test()->use_verifier()) { 189 result &= DictionarySyncIntegrationTestHelper::ApplyChange( 190 GetVerifierDictionary(), dictionary_change); 191 } 192 return result; 193} 194 195bool RemoveWord(int index, const std::string& word) { 196 SpellcheckCustomDictionary::Change dictionary_change; 197 dictionary_change.RemoveWord(word); 198 bool result = DictionarySyncIntegrationTestHelper::ApplyChange( 199 GetDictionary(index), dictionary_change); 200 if (sync_datatype_helper::test()->use_verifier()) { 201 result &= DictionarySyncIntegrationTestHelper::ApplyChange( 202 GetVerifierDictionary(), dictionary_change); 203 } 204 return result; 205} 206 207} // namespace dictionary_helper 208