diff options
author | thakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-09-25 18:02:54 +0000 |
---|---|---|
committer | thakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-09-25 18:02:54 +0000 |
commit | 626a84f8de401f6d778a315fbab491a7574da234 (patch) | |
tree | c7334656c457a6fa7a6d01c1a05d115d5547f319 /chrome/test | |
parent | 80dbd7e3ae7e010c3286ec824893d1f58d127fc1 (diff) | |
download | chromium_src-626a84f8de401f6d778a315fbab491a7574da234.zip chromium_src-626a84f8de401f6d778a315fbab491a7574da234.tar.gz chromium_src-626a84f8de401f6d778a315fbab491a7574da234.tar.bz2 |
Revert 60556 (broke chrome, at least on linux) - Refactor, rename and relocate ProfileSyncServiceTestHarness.
ProfileSyncServiceTestHarness needs to support a specialization that can use a WaitableEvent instead of starting and stopping the UI Message loop. Required for automation provider support for sync.
The class also needs to live in chrome/browser, instead of chrome/test, and could do with a rename.
BUG=56460
TEST=sync_integration_tests
Review URL: http://codereview.chromium.org/3492005
TBR=rsimha@chromium.org
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@60584 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/test')
8 files changed, 626 insertions, 32 deletions
diff --git a/chrome/test/live_sync/live_sync_test.cc b/chrome/test/live_sync/live_sync_test.cc index 4298d80..01c5361 100644 --- a/chrome/test/live_sync/live_sync_test.cc +++ b/chrome/test/live_sync/live_sync_test.cc @@ -176,7 +176,7 @@ Profile* LiveSyncTest::GetProfile(int index) { return profiles_[index]; } -ProfileSyncServiceHarness* LiveSyncTest::GetClient(int index) { +ProfileSyncServiceTestHarness* LiveSyncTest::GetClient(int index) { EXPECT_FALSE(clients_.empty()) << "SetupClients() has not yet been called."; EXPECT_TRUE((index >= 0) && (index < static_cast<int>(clients_.size()))) << "GetClient(): Index is out of bounds."; @@ -199,7 +199,7 @@ bool LiveSyncTest::SetupClients() { profiles_.push_back(MakeProfile( StringPrintf(FILE_PATH_LITERAL("Profile%d"), i))); EXPECT_FALSE(GetProfile(i) == NULL) << "GetProfile(" << i << ") failed."; - clients_.push_back(new ProfileSyncServiceHarness( + clients_.push_back(new ProfileSyncServiceTestHarness( GetProfile(i), username_, password_, i)); EXPECT_FALSE(GetClient(i) == NULL) << "GetClient(" << i << ") failed."; } diff --git a/chrome/test/live_sync/live_sync_test.h b/chrome/test/live_sync/live_sync_test.h index 78a3abc..ee5ab08 100644 --- a/chrome/test/live_sync/live_sync_test.h +++ b/chrome/test/live_sync/live_sync_test.h @@ -12,7 +12,7 @@ #include "base/file_util.h" #include "base/scoped_ptr.h" #include "base/scoped_vector.h" -#include "chrome/browser/sync/profile_sync_service_harness.h" +#include "chrome/test/live_sync/profile_sync_service_test_harness.h" #include "net/base/mock_host_resolver.h" #include "net/test/test_server.h" @@ -105,11 +105,11 @@ class LiveSyncTest : public InProcessBrowserTest { // Returns a pointer to a particular sync client. Callee owns the object // and manages its lifetime. - ProfileSyncServiceHarness* GetClient(int index); + ProfileSyncServiceTestHarness* GetClient(int index); // Returns a reference to the collection of sync clients. Callee owns the // object and manages its lifetime. - std::vector<ProfileSyncServiceHarness*>& clients() { + std::vector<ProfileSyncServiceTestHarness*>& clients() { return clients_.get(); } @@ -182,7 +182,7 @@ class LiveSyncTest : public InProcessBrowserTest { // Collection of sync clients used by a test. A sync client is associated with // a sync profile, and implements methods that sync the contents of the // profile with the server. - ScopedVector<ProfileSyncServiceHarness> clients_; + ScopedVector<ProfileSyncServiceTestHarness> clients_; // Sync profile against which changes to individual profiles are verified. We // don't need a corresponding verifier sync client because the contents of the diff --git a/chrome/test/live_sync/multiple_client_live_bookmarks_sync_test.cc b/chrome/test/live_sync/multiple_client_live_bookmarks_sync_test.cc index 2700e22..5a570dd 100644 --- a/chrome/test/live_sync/multiple_client_live_bookmarks_sync_test.cc +++ b/chrome/test/live_sync/multiple_client_live_bookmarks_sync_test.cc @@ -14,7 +14,7 @@ IN_PROC_BROWSER_TEST_F(MultipleClientLiveBookmarksSyncTest, Sanity) { StringPrintf(L"Google URL %d", i), GURL(StringPrintf("http://www.google.com/%d", i))); } - ProfileSyncServiceHarness::AwaitQuiescence(clients()); + ProfileSyncServiceTestHarness::AwaitQuiescence(clients()); for (int i = 1; i < num_clients(); ++i) { BookmarkModelVerifier::ExpectModelsMatch(GetBookmarkModel(0), GetBookmarkModel(i)); diff --git a/chrome/test/live_sync/profile_sync_service_test_harness.cc b/chrome/test/live_sync/profile_sync_service_test_harness.cc new file mode 100644 index 0000000..dbf3ef1 --- /dev/null +++ b/chrome/test/live_sync/profile_sync_service_test_harness.cc @@ -0,0 +1,430 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/message_loop.h" +#include "chrome/browser/browser.h" +#include "chrome/browser/defaults.h" +#include "chrome/browser/prefs/pref_service.h" +#include "chrome/browser/profile.h" +#include "chrome/browser/net/gaia/token_service.h" +#include "chrome/browser/sync/glue/sync_backend_host.h" +#include "chrome/browser/sync/sessions/session_state.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/common/net/gaia/gaia_constants.h" +#include "chrome/common/net/gaia/google_service_auth_error.h" +#include "chrome/common/pref_names.h" +#include "chrome/test/live_sync/profile_sync_service_test_harness.h" +#include "chrome/test/test_timeouts.h" +#include "chrome/test/ui_test_utils.h" +#include "testing/gtest/include/gtest/gtest.h" + +// The default value for min_timestamp_needed_ when we're not in the +// WAITING_FOR_UPDATES state. +static const int kMinTimestampNeededNone = -1; + +// Simple class to implement a timeout using PostDelayedTask. If it is not +// aborted before picked up by a message queue, then it asserts with the message +// provided. This class is not thread safe. +class StateChangeTimeoutEvent + : public base::RefCountedThreadSafe<StateChangeTimeoutEvent> { + public: + explicit StateChangeTimeoutEvent(ProfileSyncServiceTestHarness* caller, + const std::string& message); + + // The entry point to the class from PostDelayedTask. + void Callback(); + + // Cancels the actions of the callback. Returns true if success, false + // if the callback has already timed out. + bool Abort(); + + private: + friend class base::RefCountedThreadSafe<StateChangeTimeoutEvent>; + + ~StateChangeTimeoutEvent(); + + bool aborted_; + bool did_timeout_; + + // Due to synchronization of the IO loop, the caller will always be alive + // if the class is not aborted. + ProfileSyncServiceTestHarness* caller_; + + // Informative message to assert in the case of a timeout. + std::string message_; + + DISALLOW_COPY_AND_ASSIGN(StateChangeTimeoutEvent); +}; + +StateChangeTimeoutEvent::StateChangeTimeoutEvent( + ProfileSyncServiceTestHarness* caller, + const std::string& message) + : aborted_(false), did_timeout_(false), caller_(caller), message_(message) { +} + +StateChangeTimeoutEvent::~StateChangeTimeoutEvent() { +} + +void StateChangeTimeoutEvent::Callback() { + if (!aborted_) { + if (!caller_->RunStateChangeMachine()) { + // Report the message. + did_timeout_ = true; + EXPECT_FALSE(aborted_) << message_; + caller_->SignalStateComplete(); + } + } +} + +bool StateChangeTimeoutEvent::Abort() { + aborted_ = true; + caller_ = NULL; + return !did_timeout_; +} + +ProfileSyncServiceTestHarness::ProfileSyncServiceTestHarness(Profile* p, + const std::string& username, const std::string& password, int id) + : wait_state_(WAITING_FOR_ON_BACKEND_INITIALIZED), + profile_(p), service_(NULL), + last_timestamp_(0), + min_timestamp_needed_(kMinTimestampNeededNone), + username_(username), password_(password), id_(id) { + // Ensure the profile has enough prefs registered for use by sync. + if (!p->GetPrefs()->FindPreference(prefs::kAcceptLanguages)) + TabContents::RegisterUserPrefs(p->GetPrefs()); +} + +bool ProfileSyncServiceTestHarness::SetupSync() { + service_ = profile_->GetProfileSyncService(""); + EXPECT_FALSE(service_ == NULL) << "SetupSync(): service_ is null."; + service_->AddObserver(this); + service_->signin_.StartSignIn(username_, password_, "", ""); + return WaitForServiceInit(); +} + +void ProfileSyncServiceTestHarness::SignalStateCompleteWithNextState( + WaitState next_state) { + wait_state_ = next_state; + SignalStateComplete(); +} + +void ProfileSyncServiceTestHarness::SignalStateComplete() { + MessageLoopForUI::current()->Quit(); +} + +bool ProfileSyncServiceTestHarness::RunStateChangeMachine() { + WaitState original_wait_state = wait_state_; + switch (wait_state_) { + case WAITING_FOR_ON_BACKEND_INITIALIZED: { + LogClientInfo("WAITING_FOR_ON_BACKEND_INITIALIZED"); + if (service()->sync_initialized()) { + // The sync backend is initialized. Start waiting for the first sync + // cycle to complete. + SignalStateCompleteWithNextState(WAITING_FOR_INITIAL_SYNC); + } + break; + } + case WAITING_FOR_INITIAL_SYNC: { + LogClientInfo("WAITING_FOR_INITIAL_SYNC"); + if (IsSynced()) { + // The first sync cycle is now complete. We can start running tests. + SignalStateCompleteWithNextState(FULLY_SYNCED); + } + break; + } + case WAITING_FOR_SYNC_TO_FINISH: { + LogClientInfo("WAITING_FOR_SYNC_TO_FINISH"); + if (!IsSynced()) { + // The client is not yet fully synced. Continue waiting. + if (!GetStatus().server_reachable) { + // The client cannot reach the sync server because the network is + // disabled. There is no need to wait anymore. + SignalStateCompleteWithNextState(SERVER_UNREACHABLE); + } + break; + } + GetUpdatedTimestamp(); + SignalStateCompleteWithNextState(FULLY_SYNCED); + break; + } + case WAITING_FOR_UPDATES: { + LogClientInfo("WAITING_FOR_UPDATES"); + if (!IsSynced() || GetUpdatedTimestamp() < min_timestamp_needed_) { + // The client is not yet fully synced. Continue waiting until the client + // is at the required minimum timestamp. + break; + } + SignalStateCompleteWithNextState(FULLY_SYNCED); + break; + } + case SERVER_UNREACHABLE: { + LogClientInfo("SERVER_UNREACHABLE"); + if (GetStatus().server_reachable) { + // The client was offline due to the network being disabled, but is now + // back online. Wait for the pending sync cycle to complete. + SignalStateCompleteWithNextState(WAITING_FOR_SYNC_TO_FINISH); + } + break; + } + case FULLY_SYNCED: { + // The client is online and fully synced. There is nothing to do. + LogClientInfo("FULLY_SYNCED"); + break; + } + default: + // Invalid state during observer callback which may be triggered by other + // classes using the the UI message loop. Defer to their handling. + break; + } + return original_wait_state != wait_state_; +} + +void ProfileSyncServiceTestHarness::OnStateChanged() { + RunStateChangeMachine(); +} + +bool ProfileSyncServiceTestHarness::AwaitSyncCycleCompletion( + const std::string& reason) { + LogClientInfo("AwaitSyncCycleCompletion"); + if (!IsSynced()) { + if (wait_state_ == SERVER_UNREACHABLE) { + // Client was offline; wait for it to go online, and then wait for sync. + AwaitStatusChangeWithTimeout( + TestTimeouts::live_operation_timeout_ms(), reason); + EXPECT_EQ(wait_state_, WAITING_FOR_SYNC_TO_FINISH); + return AwaitStatusChangeWithTimeout( + TestTimeouts::live_operation_timeout_ms(), reason); + } else { + EXPECT_TRUE(service()->sync_initialized()); + wait_state_ = WAITING_FOR_SYNC_TO_FINISH; + AwaitStatusChangeWithTimeout( + TestTimeouts::live_operation_timeout_ms(), reason); + if (wait_state_ == FULLY_SYNCED) { + // Client is online; sync was successful. + return true; + } else if (wait_state_ == SERVER_UNREACHABLE){ + // Client is offline; sync was unsuccessful. + return false; + } else { + LOG(FATAL) << "Invalid wait state:" << wait_state_; + return false; + } + } + } else { + // Client is already synced; don't wait. + GetUpdatedTimestamp(); + return true; + } +} + +bool ProfileSyncServiceTestHarness::AwaitMutualSyncCycleCompletion( + ProfileSyncServiceTestHarness* partner) { + LogClientInfo("AwaitMutualSyncCycleCompletion"); + bool success = AwaitSyncCycleCompletion( + "Sync cycle completion on active client."); + if (!success) + return false; + return partner->WaitUntilTimestampIsAtLeast(last_timestamp_, + "Sync cycle completion on passive client."); +} + +bool ProfileSyncServiceTestHarness::AwaitGroupSyncCycleCompletion( + std::vector<ProfileSyncServiceTestHarness*>& partners) { + LogClientInfo("AwaitGroupSyncCycleCompletion"); + bool success = AwaitSyncCycleCompletion( + "Sync cycle completion on active client."); + if (!success) + return false; + bool return_value = true; + for (std::vector<ProfileSyncServiceTestHarness*>::iterator it = + partners.begin(); it != partners.end(); ++it) { + if (this != *it) { + return_value = return_value && + (*it)->WaitUntilTimestampIsAtLeast(last_timestamp_, + "Sync cycle completion on partner client."); + } + } + return return_value; +} + +// static +bool ProfileSyncServiceTestHarness::AwaitQuiescence( + std::vector<ProfileSyncServiceTestHarness*>& clients) { + LOG(INFO) << "AwaitQuiescence."; + bool return_value = true; + for (std::vector<ProfileSyncServiceTestHarness*>::iterator it = + clients.begin(); it != clients.end(); ++it) { + return_value = return_value && + (*it)->AwaitGroupSyncCycleCompletion(clients); + } + return return_value; +} + +bool ProfileSyncServiceTestHarness::WaitUntilTimestampIsAtLeast( + int64 timestamp, const std::string& reason) { + LogClientInfo("WaitUntilTimestampIsAtLeast"); + min_timestamp_needed_ = timestamp; + if (GetUpdatedTimestamp() < min_timestamp_needed_) { + wait_state_ = WAITING_FOR_UPDATES; + return AwaitStatusChangeWithTimeout( + TestTimeouts::live_operation_timeout_ms(), reason); + } else { + return true; + } +} + +bool ProfileSyncServiceTestHarness::AwaitStatusChangeWithTimeout( + int timeout_milliseconds, + const std::string& reason) { + LogClientInfo("AwaitStatusChangeWithTimeout"); + scoped_refptr<StateChangeTimeoutEvent> timeout_signal( + new StateChangeTimeoutEvent(this, reason)); + MessageLoopForUI* loop = MessageLoopForUI::current(); + loop->PostDelayedTask( + FROM_HERE, + NewRunnableMethod(timeout_signal.get(), + &StateChangeTimeoutEvent::Callback), + timeout_milliseconds); + LogClientInfo("Before RunMessageLoop"); + ui_test_utils::RunMessageLoop(); + LogClientInfo("After RunMessageLoop"); + return timeout_signal->Abort(); +} + +bool ProfileSyncServiceTestHarness::WaitForServiceInit() { + LogClientInfo("WaitForServiceInit"); + + // Wait for the OnBackendInitialized() callback. + EXPECT_EQ(wait_state_, WAITING_FOR_ON_BACKEND_INITIALIZED); + if (!AwaitStatusChangeWithTimeout(TestTimeouts::live_operation_timeout_ms(), + "Waiting for OnBackendInitialized().")) { + LOG(FATAL) << "OnBackendInitialized() not seen after " + << TestTimeouts::live_operation_timeout_ms() / 1000 + << " seconds."; + } + + // Choose datatypes to be synced. + syncable::ModelTypeSet synced_datatypes; + for (int i = syncable::FIRST_REAL_MODEL_TYPE; + i < syncable::MODEL_TYPE_COUNT; ++i) { + synced_datatypes.insert(syncable::ModelTypeFromInt(i)); + } + service()->OnUserChoseDatatypes(true, synced_datatypes); + + // Wait for initial sync cycle to complete. + EXPECT_EQ(wait_state_, WAITING_FOR_INITIAL_SYNC); + if (!AwaitStatusChangeWithTimeout(TestTimeouts::live_operation_timeout_ms(), + "Waiting for initial sync cycle to complete.")) { + LOG(FATAL) << "Initial sync cycle did not complete after " + << TestTimeouts::live_operation_timeout_ms() / 1000 + << " seconds."; + } + + return true; +} + +ProfileSyncService::Status ProfileSyncServiceTestHarness::GetStatus() { + EXPECT_FALSE(service() == NULL) << "GetStatus(): service() is NULL."; + return service()->QueryDetailedSyncStatus(); +} + +bool ProfileSyncServiceTestHarness::IsSynced() { + const SyncSessionSnapshot* snap = GetLastSessionSnapshot(); + // TODO(rsimha): Remove additional checks of snap->has_more_to_sync and + // snap->unsynced_count once http://crbug.com/48989 is fixed. + return (service() && + snap && + ServiceIsPushingChanges() && + GetStatus().notifications_enabled && + !service()->backend()->HasUnsyncedItems() && + !snap->has_more_to_sync && + snap->unsynced_count == 0); +} + +const SyncSessionSnapshot* + ProfileSyncServiceTestHarness::GetLastSessionSnapshot() const { + EXPECT_FALSE(service_ == NULL) << "Sync service has not yet been set up."; + if (service_->backend()) { + return service_->backend()->GetLastSessionSnapshot(); + } + return NULL; +} + +void ProfileSyncServiceTestHarness::EnableSyncForDatatype( + syncable::ModelType datatype) { + syncable::ModelTypeSet synced_datatypes; + EXPECT_FALSE(service() == NULL) + << "EnableSyncForDatatype(): service() is null."; + service()->GetPreferredDataTypes(&synced_datatypes); + syncable::ModelTypeSet::iterator it = synced_datatypes.find( + syncable::ModelTypeFromInt(datatype)); + if (it == synced_datatypes.end()) { + synced_datatypes.insert(syncable::ModelTypeFromInt(datatype)); + service()->OnUserChoseDatatypes(false, synced_datatypes); + AwaitSyncCycleCompletion("Waiting for datatype configuration."); + LOG(INFO) << "EnableSyncForDatatype(): Enabled sync for datatype " + << syncable::ModelTypeToString(datatype) << "."; + } else { + LOG(INFO) << "EnableSyncForDatatype(): Sync already enabled for datatype " + << syncable::ModelTypeToString(datatype) << "."; + } +} + +void ProfileSyncServiceTestHarness::DisableSyncForDatatype( + syncable::ModelType datatype) { + syncable::ModelTypeSet synced_datatypes; + EXPECT_FALSE(service() == NULL) + << "DisableSyncForDatatype(): service() is null."; + service()->GetPreferredDataTypes(&synced_datatypes); + syncable::ModelTypeSet::iterator it = synced_datatypes.find( + syncable::ModelTypeFromInt(datatype)); + if (it != synced_datatypes.end()) { + synced_datatypes.erase(it); + service()->OnUserChoseDatatypes(false, synced_datatypes); + AwaitSyncCycleCompletion("Waiting for datatype configuration."); + LOG(INFO) << "DisableSyncForDatatype(): Disabled sync for datatype " + << syncable::ModelTypeToString(datatype) << "."; + } else { + LOG(INFO) << "DisableSyncForDatatype(): Sync already disabled for datatype " + << syncable::ModelTypeToString(datatype) << "."; + } +} + +void ProfileSyncServiceTestHarness::EnableSyncForAllDatatypes() { + syncable::ModelTypeSet synced_datatypes; + for (int i = syncable::FIRST_REAL_MODEL_TYPE; + i < syncable::MODEL_TYPE_COUNT; ++i) { + synced_datatypes.insert(syncable::ModelTypeFromInt(i)); + } + EXPECT_FALSE(service() == NULL) + << "EnableSyncForAllDatatypes(): service() is null."; + service()->OnUserChoseDatatypes(true, synced_datatypes); + AwaitSyncCycleCompletion("Waiting for datatype configuration."); + LOG(INFO) << "EnableSyncForAllDatatypes(): Enabled sync for all datatypes."; +} + +int64 ProfileSyncServiceTestHarness::GetUpdatedTimestamp() { + const SyncSessionSnapshot* snap = GetLastSessionSnapshot(); + EXPECT_FALSE(snap == NULL) << "GetUpdatedTimestamp(): Sync snapshot is NULL."; + EXPECT_LE(last_timestamp_, snap->max_local_timestamp); + last_timestamp_ = snap->max_local_timestamp; + return last_timestamp_; +} + +void ProfileSyncServiceTestHarness::LogClientInfo(std::string message) { + const SyncSessionSnapshot* snap = GetLastSessionSnapshot(); + if (snap) { + LOG(INFO) << "Client " << id_ << ": " << message << ": " + << "max_local_timestamp: " << snap->max_local_timestamp + << ", has_more_to_sync: " << snap->has_more_to_sync + << ", unsynced_count: " << snap->unsynced_count + << ", has_unsynced_items: " << service()->backend()->HasUnsyncedItems() + << ", notifications_enabled: " << GetStatus().notifications_enabled + << ", ServiceIsPushingChanges(): " << ServiceIsPushingChanges() + << "."; + } else { + LOG(INFO) << "Client " << id_ << ": " << message << ": " + << "Snap not available."; + } +} diff --git a/chrome/test/live_sync/profile_sync_service_test_harness.h b/chrome/test/live_sync/profile_sync_service_test_harness.h new file mode 100644 index 0000000..a523c68 --- /dev/null +++ b/chrome/test/live_sync/profile_sync_service_test_harness.h @@ -0,0 +1,164 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_TEST_LIVE_SYNC_PROFILE_SYNC_SERVICE_TEST_HARNESS_H_ +#define CHROME_TEST_LIVE_SYNC_PROFILE_SYNC_SERVICE_TEST_HARNESS_H_ +#pragma once + +#include <string> +#include <vector> + +#include "base/time.h" +#include "chrome/browser/sync/profile_sync_service.h" + +using browser_sync::sessions::SyncSessionSnapshot; + +class Profile; + +// An instance of this class is basically our notion of a "sync client" for +// test purposes. It harnesses the ProfileSyncService member of the profile +// passed to it on construction and automates certain things like setup and +// authentication. It provides ways to "wait" adequate periods of time for +// several clients to get to the same state. +class ProfileSyncServiceTestHarness : public ProfileSyncServiceObserver { + public: + ProfileSyncServiceTestHarness(Profile* p, const std::string& username, + const std::string& password, int id); + + // Creates a ProfileSyncService for the profile passed at construction and + // enables sync. Returns true only after sync has been fully initialized and + // authenticated, and we are ready to process changes. + bool SetupSync(); + + // ProfileSyncServiceObserver implementation. + virtual void OnStateChanged(); + + // Blocks the caller until this harness has completed a single sync cycle + // since the previous one. Returns true if a sync cycle has completed. + bool AwaitSyncCycleCompletion(const std::string& reason); + + // Blocks the caller until this harness has observed that the sync engine + // has "synced" up to at least the specified local timestamp. + bool WaitUntilTimestampIsAtLeast(int64 timestamp, const std::string& reason); + + // Calling this acts as a barrier and blocks the caller until |this| and + // |partner| have both completed a sync cycle. When calling this method, + // the |partner| should be the passive responder who responds to the actions + // of |this|. This method relies upon the synchronization of callbacks + // from the message queue. Returns true if two sync cycles have completed. + // Note: Use this method when exactly one client makes local change(s), and + // exactly one client is waiting to receive those changes. + bool AwaitMutualSyncCycleCompletion(ProfileSyncServiceTestHarness* partner); + + // Blocks the caller until |this| completes its ongoing sync cycle and every + // other client in |partners| has a timestamp that is greater than or equal to + // the timestamp of |this|. Note: Use this method when exactly one client + // makes local change(s), and more than one client is waiting to receive those + // changes. + bool AwaitGroupSyncCycleCompletion( + std::vector<ProfileSyncServiceTestHarness*>& partners); + + // Blocks the caller until every client in |clients| completes its ongoing + // sync cycle and all the clients' timestamps match. Note: Use this method + // when more than one client makes local change(s), and more than one client + // is waiting to receive those changes. + static bool AwaitQuiescence( + std::vector<ProfileSyncServiceTestHarness*>& clients); + + // Returns the ProfileSyncService member of the the sync client. + ProfileSyncService* service() { return service_; } + + // Returns the status of the ProfileSyncService member of the the sync client. + ProfileSyncService::Status GetStatus(); + + // See ProfileSyncService::ShouldPushChanges(). + bool ServiceIsPushingChanges() { return service_->ShouldPushChanges(); } + + // Enables sync for a particular sync datatype. + void EnableSyncForDatatype(syncable::ModelType datatype); + + // Disables sync for a particular sync datatype. + void DisableSyncForDatatype(syncable::ModelType datatype); + + // Enables sync for all sync datatypes. + void EnableSyncForAllDatatypes(); + + private: + friend class StateChangeTimeoutEvent; + + enum WaitState { + // The sync client awaits the OnBackendInitialized() callback. + WAITING_FOR_ON_BACKEND_INITIALIZED = 0, + + // The sync client is waiting for the first sync cycle to complete. + WAITING_FOR_INITIAL_SYNC, + + // The sync client is waiting for an ongoing sync cycle to complete. + WAITING_FOR_SYNC_TO_FINISH, + + // The sync client anticipates incoming updates leading to a new sync cycle. + WAITING_FOR_UPDATES, + + // The sync client cannot reach the server. + SERVER_UNREACHABLE, + + // The sync client is fully synced and there are no pending updates. + FULLY_SYNCED, + NUMBER_OF_STATES, + }; + + // Called from the observer when the current wait state has been completed. + void SignalStateCompleteWithNextState(WaitState next_state); + void SignalStateComplete(); + + // Finite state machine for controlling state. Returns true only if a state + // change has taken place. + bool RunStateChangeMachine(); + + // Returns true if a status change took place, false on timeout. + virtual bool AwaitStatusChangeWithTimeout(int timeout_milliseconds, + const std::string& reason); + + // Returns true if the service initialized correctly. + bool WaitForServiceInit(); + + // Returns true if the sync client has no unsynced items. + bool IsSynced(); + + // Logs message with relevant info about client's sync state (if available). + void LogClientInfo(std::string message); + + WaitState wait_state_; + + Profile* profile_; + ProfileSyncService* service_; + + // Returns a snapshot of the current sync session. + const SyncSessionSnapshot* GetLastSessionSnapshot() const; + + // Updates |last_timestamp_| with the timestamp of the current sync session. + // Returns the new value of |last_timestamp_|. + int64 GetUpdatedTimestamp(); + + // This value tracks the max sync timestamp (e.g. synced-to revision) inside + // the sync engine. It gets updated when a sync cycle ends and the session + // snapshot implies syncing is "done". + int64 last_timestamp_; + + // The minimum value of the 'max_local_timestamp' member of a + // SyncSessionSnapshot we need to wait to observe in OnStateChanged when told + // to WaitUntilTimestampIsAtLeast(...). + int64 min_timestamp_needed_; + + // Credentials used for GAIA authentication. + std::string username_; + std::string password_; + + // Client ID, used for logging purposes. + int id_; + + DISALLOW_COPY_AND_ASSIGN(ProfileSyncServiceTestHarness); +}; + +#endif // CHROME_TEST_LIVE_SYNC_PROFILE_SYNC_SERVICE_TEST_HARNESS_H_ diff --git a/chrome/test/live_sync/two_client_live_autofill_sync_test.cc b/chrome/test/live_sync/two_client_live_autofill_sync_test.cc index 7f874f2..edda6a4 100644 --- a/chrome/test/live_sync/two_client_live_autofill_sync_test.cc +++ b/chrome/test/live_sync/two_client_live_autofill_sync_test.cc @@ -17,7 +17,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientLiveAutofillSyncTest, Client1HasData) { AddFormFieldsToWebData(GetWebDataService(0), keys); ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; - ASSERT_TRUE(ProfileSyncServiceHarness::AwaitQuiescence(clients())); + ASSERT_TRUE(ProfileSyncServiceTestHarness::AwaitQuiescence(clients())); AutofillKeys wd1_keys; GetAllAutofillKeys(GetWebDataService(1), &wd1_keys); @@ -48,7 +48,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientLiveAutofillSyncTest, BothHaveData) { AddFormFieldsToWebData(GetWebDataService(1), keys2); ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; - EXPECT_TRUE(ProfileSyncServiceHarness::AwaitQuiescence(clients())); + EXPECT_TRUE(ProfileSyncServiceTestHarness::AwaitQuiescence(clients())); // Note: In this test, name0-value0 and name0-value1 were added in separate // transactions -- one on Client0 and the other on Client1. Therefore, we @@ -153,7 +153,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientLiveAutofillSyncTest, ProfileClient1HasData) { AddProfile(GetPersonalDataManager(0), *expected_profiles[1]); ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; - ASSERT_TRUE(ProfileSyncServiceHarness::AwaitQuiescence(clients())); + ASSERT_TRUE(ProfileSyncServiceTestHarness::AwaitQuiescence(clients())); AutoFillProfile::AdjustInferredLabels(&expected_profiles); EXPECT_TRUE(CompareAutoFillProfiles(expected_profiles, @@ -181,7 +181,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientLiveAutofillSyncTest, ConflictLabels) { AddProfile(GetPersonalDataManager(1), *profiles2[0]); ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; - ASSERT_TRUE(ProfileSyncServiceHarness::AwaitQuiescence(clients())); + ASSERT_TRUE(ProfileSyncServiceTestHarness::AwaitQuiescence(clients())); // Since client1 associates first, client2's profile will // be overwritten by the one stored in the cloud by profile1. @@ -208,7 +208,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientLiveAutofillSyncTest, AddProfile(GetPersonalDataManager(0), *expected_profiles[1]); ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; - ASSERT_TRUE(ProfileSyncServiceHarness::AwaitQuiescence(clients())); + ASSERT_TRUE(ProfileSyncServiceTestHarness::AwaitQuiescence(clients())); // One of the duplicate profiles will have its label renamed to // the first label with "2" appended. @@ -363,7 +363,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientLiveAutofillSyncTest, AddMultipleProfiles) { FillProfile(PROFILE_FRASIER, expected_profiles[3]); AddProfile(GetPersonalDataManager(0), *expected_profiles[3]); - ASSERT_TRUE(ProfileSyncServiceHarness::AwaitQuiescence(clients())); + ASSERT_TRUE(ProfileSyncServiceTestHarness::AwaitQuiescence(clients())); EXPECT_TRUE(CompareAutoFillProfiles( GetAllAutoFillProfiles(GetPersonalDataManager(1)), @@ -381,7 +381,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientLiveAutofillSyncTest, AddUnicodeProfile) { AddFormFieldsToWebData(GetWebDataService(0), expected_keys); ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; - ASSERT_TRUE(ProfileSyncServiceHarness::AwaitQuiescence(clients())); + ASSERT_TRUE(ProfileSyncServiceTestHarness::AwaitQuiescence(clients())); AutofillKeys synced_keys; GetAllAutofillKeys(GetWebDataService(1), &synced_keys); @@ -470,7 +470,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientLiveAutofillSyncTest, UpdateFields) { AutoFillType(NAME_FIRST), ASCIIToUTF16("Lisa")); UpdateProfile(GetPersonalDataManager(0), expected_profiles[0]->Label(), AutoFillType(EMAIL_ADDRESS), ASCIIToUTF16("grrrl@TV.com")); - ASSERT_TRUE(ProfileSyncServiceHarness::AwaitQuiescence(clients())); + ASSERT_TRUE(ProfileSyncServiceTestHarness::AwaitQuiescence(clients())); EXPECT_TRUE(CompareAutoFillProfiles( GetAllAutoFillProfiles(GetPersonalDataManager(0)), @@ -497,7 +497,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientLiveAutofillSyncTest, UpdateLabel) { AddProfile(GetPersonalDataManager(0), *profiles0[0]); AddProfile(GetPersonalDataManager(1), *profiles1[0]); - ASSERT_TRUE(ProfileSyncServiceHarness::AwaitQuiescence(clients())); + ASSERT_TRUE(ProfileSyncServiceTestHarness::AwaitQuiescence(clients())); AutoFillProfile::AdjustInferredLabels(&expected_profiles); EXPECT_TRUE(CompareAutoFillProfiles(expected_profiles, @@ -529,7 +529,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientLiveAutofillSyncTest, ConflictFields) { UpdateProfile(GetPersonalDataManager(1), expected_profiles[0]->Label(), AutoFillType(NAME_FIRST), ASCIIToUTF16("Bart")); - ASSERT_TRUE(ProfileSyncServiceHarness::AwaitQuiescence(clients())); + ASSERT_TRUE(ProfileSyncServiceTestHarness::AwaitQuiescence(clients())); EXPECT_TRUE(CompareAutoFillProfiles( GetAllAutoFillProfiles(GetPersonalDataManager(0)), diff --git a/chrome/test/live_sync/two_client_live_bookmarks_sync_test.cc b/chrome/test/live_sync/two_client_live_bookmarks_sync_test.cc index ca11f57..845c949 100644 --- a/chrome/test/live_sync/two_client_live_bookmarks_sync_test.cc +++ b/chrome/test/live_sync/two_client_live_bookmarks_sync_test.cc @@ -100,7 +100,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientLiveBookmarksSyncTest, Sanity) { bm1->SetTitle(google_two, ASCIIToUTF16("Google--")); } - ASSERT_TRUE(ProfileSyncServiceHarness::AwaitQuiescence(clients())); + ASSERT_TRUE(ProfileSyncServiceTestHarness::AwaitQuiescence(clients())); BookmarkModelVerifier::ExpectModelsMatch(bm0, bm1); } @@ -142,7 +142,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientLiveBookmarksSyncTest, BookmarkEditor::EditDetails(google_two), title, third_url); } - ASSERT_TRUE(ProfileSyncServiceHarness::AwaitQuiescence(clients())); + ASSERT_TRUE(ProfileSyncServiceTestHarness::AwaitQuiescence(clients())); BookmarkModelVerifier::ExpectModelsMatch(bm0, bm1); { @@ -1879,7 +1879,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientLiveBookmarksSyncTest, ASSERT_TRUE(bm_foo4 != NULL); } - ASSERT_TRUE(ProfileSyncServiceHarness::AwaitQuiescence(clients())); + ASSERT_TRUE(ProfileSyncServiceTestHarness::AwaitQuiescence(clients())); BookmarkModelVerifier::ExpectModelsMatch(bm0, bm1); BookmarkModelVerifier::VerifyNoDuplicates(bm0); } @@ -1918,7 +1918,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientLiveBookmarksSyncTest, } ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; - ASSERT_TRUE(ProfileSyncServiceHarness::AwaitQuiescence(clients())); + ASSERT_TRUE(ProfileSyncServiceTestHarness::AwaitQuiescence(clients())); BookmarkModelVerifier::ExpectModelsMatch(profile0_bookmark_model, profile1_bookmark_model); BookmarkModelVerifier::VerifyNoDuplicates(profile0_bookmark_model); @@ -1931,7 +1931,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientLiveBookmarksSyncTest, BookmarkModelVerifier* v = verifier_helper(); BookmarkModel* bm0 = GetBookmarkModel(0); BookmarkModel* bm1 = GetBookmarkModel(1); - ASSERT_TRUE(ProfileSyncServiceHarness::AwaitQuiescence(clients())); + ASSERT_TRUE(ProfileSyncServiceTestHarness::AwaitQuiescence(clients())); v->ExpectMatch(bm0); v->ExpectMatch(bm1); } @@ -1981,7 +1981,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientLiveBookmarksSyncTest, } ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; - ASSERT_TRUE(ProfileSyncServiceHarness::AwaitQuiescence(clients())); + ASSERT_TRUE(ProfileSyncServiceTestHarness::AwaitQuiescence(clients())); BookmarkModelVerifier::ExpectModelsMatch(profile0_bookmark_model, profile1_bookmark_model); BookmarkModelVerifier::VerifyNoDuplicates(profile0_bookmark_model); @@ -2041,7 +2041,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientLiveBookmarksSyncTest, ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; // Wait for changes to propagate. - ASSERT_TRUE(ProfileSyncServiceHarness::AwaitQuiescence(clients())); + ASSERT_TRUE(ProfileSyncServiceTestHarness::AwaitQuiescence(clients())); // Let's make sure there aren't any duplicates after sync. BookmarkModelVerifier::VerifyNoDuplicates(bm0); // Let's compare and make sure both bookmark models are same after sync. @@ -2091,7 +2091,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientLiveBookmarksSyncTest, ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; // Wait for changes to propagate. - ASSERT_TRUE(ProfileSyncServiceHarness::AwaitQuiescence(clients())); + ASSERT_TRUE(ProfileSyncServiceTestHarness::AwaitQuiescence(clients())); // Let's make sure there aren't any duplicates after sync. BookmarkModelVerifier::VerifyNoDuplicates(bm0); // Let's compare and make sure both bookmark models are same after sync. @@ -2128,7 +2128,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientLiveBookmarksSyncTest, // Set up sync on both clients. ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; // Wait for changes to propagate. - ASSERT_TRUE(ProfileSyncServiceHarness::AwaitQuiescence(clients())); + ASSERT_TRUE(ProfileSyncServiceTestHarness::AwaitQuiescence(clients())); // Let's make sure there aren't any duplicates after sync. BookmarkModelVerifier::VerifyNoDuplicates(bm0); // Let's compare and make sure both bookmark models are same after sync. @@ -2175,7 +2175,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientLiveBookmarksSyncTest, ASSERT_TRUE(profile1_bookmark4 != NULL); ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; - ASSERT_TRUE(ProfileSyncServiceHarness::AwaitQuiescence(clients())); + ASSERT_TRUE(ProfileSyncServiceTestHarness::AwaitQuiescence(clients())); BookmarkModelVerifier::VerifyNoDuplicates(profile0_bookmark_model); BookmarkModelVerifier::ExpectModelsMatch(profile0_bookmark_model, profile1_bookmark_model); @@ -2285,7 +2285,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientLiveBookmarksSyncTest, } ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; - ASSERT_TRUE(ProfileSyncServiceHarness::AwaitQuiescence(clients())); + ASSERT_TRUE(ProfileSyncServiceTestHarness::AwaitQuiescence(clients())); BookmarkModelVerifier::VerifyNoDuplicates(profile0_bookmark_model); BookmarkModelVerifier::ExpectModelsMatch(profile0_bookmark_model, profile1_bookmark_model); @@ -2355,7 +2355,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientLiveBookmarksSyncTest, } ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; - ASSERT_TRUE(ProfileSyncServiceHarness::AwaitQuiescence(clients())); + ASSERT_TRUE(ProfileSyncServiceTestHarness::AwaitQuiescence(clients())); BookmarkModelVerifier::ExpectModelsMatch(profile0_bookmark_model, profile1_bookmark_model); } diff --git a/chrome/test/live_sync/two_client_live_preferences_sync_test.cc b/chrome/test/live_sync/two_client_live_preferences_sync_test.cc index c3b80d0..2d9f936 100644 --- a/chrome/test/live_sync/two_client_live_preferences_sync_test.cc +++ b/chrome/test/live_sync/two_client_live_preferences_sync_test.cc @@ -30,7 +30,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientLivePreferencesSyncTest, Race) { GetPrefs(0)->SetString(prefs::kHomePage, "http://www.google.com/1"); GetPrefs(1)->SetString(prefs::kHomePage, "http://www.google.com/2"); - ASSERT_TRUE(ProfileSyncServiceHarness::AwaitQuiescence(clients())); + ASSERT_TRUE(ProfileSyncServiceTestHarness::AwaitQuiescence(clients())); EXPECT_EQ(GetPrefs(0)->GetString(prefs::kHomePage), GetPrefs(1)->GetString(prefs::kHomePage)); @@ -81,7 +81,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientLivePreferencesSyncTest, kSyncPreferences) { GetPrefs(0)->SetBoolean(prefs::kPasswordManagerEnabled, 1); GetPrefs(1)->SetBoolean(prefs::kPasswordManagerEnabled, 0); - ASSERT_TRUE(ProfileSyncServiceHarness::AwaitQuiescence(clients())); + ASSERT_TRUE(ProfileSyncServiceTestHarness::AwaitQuiescence(clients())); EXPECT_NE(GetPrefs(0)->GetBoolean(prefs::kPasswordManagerEnabled), GetPrefs(1)->GetBoolean(prefs::kPasswordManagerEnabled)); @@ -113,7 +113,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientLivePreferencesSyncTest, SignInDialog) { GetClient(0)->DisableSyncForDatatype(syncable::THEMES); GetClient(1)->EnableSyncForDatatype(syncable::THEMES); - ASSERT_TRUE(ProfileSyncServiceHarness::AwaitQuiescence(clients())); + ASSERT_TRUE(ProfileSyncServiceTestHarness::AwaitQuiescence(clients())); EXPECT_NE(GetPrefs(0)->GetBoolean(prefs::kSyncPreferences), GetPrefs(1)->GetBoolean(prefs::kSyncPreferences)); |