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 24 class 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 42 namespace dictionary_helper { 43 namespace { 44 45 SpellcheckCustomDictionary* GetDictionary(int index) { 46 return SpellcheckServiceFactory::GetForContext( 47 sync_datatype_helper::test()->GetProfile(index))->GetCustomDictionary(); 48 } 49 50 SpellcheckCustomDictionary* GetVerifierDictionary() { 51 return SpellcheckServiceFactory::GetForContext( 52 sync_datatype_helper::test()->verifier())->GetCustomDictionary(); 53 } 54 55 void 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 70 void 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 77 size_t GetDictionarySize(int index) { 78 return GetDictionary(index)->GetWords().size(); 79 } 80 81 size_t GetVerifierDictionarySize() { 82 return GetVerifierDictionary()->GetWords().size(); 83 } 84 85 bool 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 101 namespace { 102 103 // Helper class used in the implementation of AwaitDictionariesMatch. 104 class 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 113 DictionaryMatchStatusChecker::DictionaryMatchStatusChecker() 114 : MultiClientStatusChangeChecker( 115 sync_datatype_helper::test()->GetSyncServices()) {} 116 117 DictionaryMatchStatusChecker::~DictionaryMatchStatusChecker() {} 118 119 bool DictionaryMatchStatusChecker::IsExitConditionSatisfied() { 120 return DictionariesMatch(); 121 } 122 123 std::string DictionaryMatchStatusChecker::GetDebugMessage() const { 124 return "Waiting for matching dictionaries"; 125 } 126 127 // Helper class used in the implementation of AwaitNumDictionaryEntries. 128 class 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 141 NumDictionaryEntriesStatusChecker::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 148 NumDictionaryEntriesStatusChecker::~NumDictionaryEntriesStatusChecker() {} 149 150 bool NumDictionaryEntriesStatusChecker::IsExitConditionSatisfied() { 151 return GetDictionarySize(index_) == num_words_; 152 } 153 154 std::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 162 bool AwaitDictionariesMatch() { 163 DictionaryMatchStatusChecker checker; 164 checker.Wait(); 165 return !checker.TimedOut(); 166 } 167 168 bool AwaitNumDictionaryEntries(int index, size_t num_words) { 169 NumDictionaryEntriesStatusChecker checker(index, num_words); 170 checker.Wait(); 171 return !checker.TimedOut(); 172 } 173 174 bool 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 183 bool 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 195 bool 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