diff options
author | rsimha@chromium.org <rsimha@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-03 23:27:31 +0000 |
---|---|---|
committer | rsimha@chromium.org <rsimha@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-03 23:27:31 +0000 |
commit | 909a81eaa4568f4b13562dc3f34ac7268b590f09 (patch) | |
tree | 958829ea557102634d623123a77f0ae20a7dd6da /chrome/browser/sync | |
parent | c09fb1c79c0a3e76dbb6091e4b718fd9bb197395 (diff) | |
download | chromium_src-909a81eaa4568f4b13562dc3f34ac7268b590f09.zip chromium_src-909a81eaa4568f4b13562dc3f34ac7268b590f09.tar.gz chromium_src-909a81eaa4568f4b13562dc3f34ac7268b590f09.tar.bz2 |
PyAuto hooks for Sync in TestingAutomationProvider
This patch exposes hooks for sync in TestingAutomationProvider that the chrome pyauto test suite can use. It contains the following changes:
- Partial revert of an earlier change to ProfileSyncServiceHarness. Some of its methods were made pure virtual, but this ended up being unnecessary. Also ripped out unnecessary code from LiveSyncTest.
- Minor refactor of ProfileSyncServiceHarness to allow for scenarios where the browser is restarted.
- A bunch of new methods in TestingAutomationProvider: SignInToSync, GetSyncInfo, AwaitSyncCycleCompletion, EnableSyncForDatatypes and DisableSyncForDatatypes.
- A new method in model_type.h/cc called ModelTypeFromString. Required for automation.
- New APIs in pyauto.py for sync.
- New test suite sync.py with sample tests.
BUG=53651, 60970, 56460, 61639
TEST=run pyauto sync tests
Review URL: http://codereview.chromium.org/4096004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@64988 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/sync')
-rw-r--r-- | chrome/browser/sync/profile_sync_service_harness.cc | 86 | ||||
-rw-r--r-- | chrome/browser/sync/profile_sync_service_harness.h | 41 | ||||
-rw-r--r-- | chrome/browser/sync/syncable/model_type.cc | 30 | ||||
-rw-r--r-- | chrome/browser/sync/syncable/model_type.h | 4 |
4 files changed, 119 insertions, 42 deletions
diff --git a/chrome/browser/sync/profile_sync_service_harness.cc b/chrome/browser/sync/profile_sync_service_harness.cc index 3ecafb7..4750033 100644 --- a/chrome/browser/sync/profile_sync_service_harness.cc +++ b/chrome/browser/sync/profile_sync_service_harness.cc @@ -84,18 +84,44 @@ bool StateChangeTimeoutEvent::Abort() { } ProfileSyncServiceHarness::ProfileSyncServiceHarness( - Profile* p, + Profile* profile, const std::string& username, const std::string& password, int id) - : wait_state_(WAITING_FOR_ON_BACKEND_INITIALIZED), - profile_(p), + : wait_state_(INITIAL_WAIT_STATE), + profile_(profile), service_(NULL), last_timestamp_(0), min_timestamp_needed_(kMinTimestampNeededNone), username_(username), password_(password), - id_(id) {} + id_(id) { + if (IsSyncAlreadySetup()) { + service_ = profile_->GetProfileSyncService(); + service_->AddObserver(this); + wait_state_ = FULLY_SYNCED; + } +} + +// static +ProfileSyncServiceHarness* ProfileSyncServiceHarness::CreateAndAttach( + Profile* profile) { + if (!profile->HasProfileSyncService()) { + NOTREACHED() << "Profile has never signed into sync."; + return NULL; + } + return new ProfileSyncServiceHarness(profile, "", "", 0); +} + +void ProfileSyncServiceHarness::SetCredentials(const std::string& username, + const std::string& password) { + username_ = username; + password_ = password; +} + +bool ProfileSyncServiceHarness::IsSyncAlreadySetup() { + return profile_->HasProfileSyncService(); +} bool ProfileSyncServiceHarness::SetupSync() { syncable::ModelTypeSet synced_datatypes; @@ -109,7 +135,7 @@ bool ProfileSyncServiceHarness::SetupSync() { bool ProfileSyncServiceHarness::SetupSync( const syncable::ModelTypeSet& synced_datatypes) { // Initialize the sync client's profile sync service object. - service_ = profile_->GetProfileSyncService(""); + service_ = profile_->GetProfileSyncService(); if (service_ == NULL) { LOG(ERROR) << "SetupSync(): service_ is null."; return false; @@ -123,7 +149,7 @@ bool ProfileSyncServiceHarness::SetupSync( service_->signin()->StartSignIn(username_, password_, "", ""); // Wait for the OnBackendInitialized() callback. - DCHECK_EQ(wait_state_, WAITING_FOR_ON_BACKEND_INITIALIZED); + wait_state_ = WAITING_FOR_ON_BACKEND_INITIALIZED; if (!AwaitStatusChangeWithTimeout(kLiveSyncOperationTimeoutMs, "Waiting for OnBackendInitialized().")) { LOG(ERROR) << "OnBackendInitialized() not seen after " @@ -148,6 +174,9 @@ bool ProfileSyncServiceHarness::SetupSync( return false; } + // Indicate to the browser that sync setup is complete. + service()->SetSyncSetupCompleted(); + return true; } @@ -157,6 +186,10 @@ void ProfileSyncServiceHarness::SignalStateCompleteWithNextState( SignalStateComplete(); } +void ProfileSyncServiceHarness::SignalStateComplete() { + MessageLoop::current()->Quit(); +} + bool ProfileSyncServiceHarness::RunStateChangeMachine() { WaitState original_wait_state = wait_state_; switch (wait_state_) { @@ -353,13 +386,16 @@ bool ProfileSyncServiceHarness::AwaitStatusChangeWithTimeout( } scoped_refptr<StateChangeTimeoutEvent> timeout_signal( new StateChangeTimeoutEvent(this, reason)); - MessageLoopForUI* loop = MessageLoopForUI::current(); + MessageLoop* loop = MessageLoop::current(); + bool did_allow_nestable_tasks = loop->NestableTasksAllowed(); + loop->SetNestableTasksAllowed(true); loop->PostDelayedTask( FROM_HERE, NewRunnableMethod(timeout_signal.get(), &StateChangeTimeoutEvent::Callback), timeout_milliseconds); - AwaitStatusChange(); + loop->Run(); + loop->SetNestableTasksAllowed(did_allow_nestable_tasks); LogClientInfo("AwaitStatusChangeWithTimeout succeeded"); return timeout_signal->Abort(); } @@ -370,11 +406,12 @@ ProfileSyncService::Status ProfileSyncServiceHarness::GetStatus() { } bool ProfileSyncServiceHarness::IsSynced() { + if (service() == NULL) + return false; 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 && + return (snap && ServiceIsPushingChanges() && GetStatus().notifications_enabled && !service()->backend()->HasUnsyncedItems() && @@ -478,19 +515,24 @@ int64 ProfileSyncServiceHarness::GetUpdatedTimestamp() { } void ProfileSyncServiceHarness::LogClientInfo(std::string message) { - const SyncSessionSnapshot* snap = GetLastSessionSnapshot(); - if (snap) { - VLOG(1) << "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 - << ", service_is_pushing_changes: " << ServiceIsPushingChanges(); + if (service()) { + const SyncSessionSnapshot* snap = GetLastSessionSnapshot(); + if (snap) { + VLOG(1) << "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 + << ", service_is_pushing_changes: " << ServiceIsPushingChanges(); + } else { + VLOG(1) << "Client " << id_ << ": " << message + << ": Sync session snapshot not available."; + } } else { VLOG(1) << "Client " << id_ << ": " << message - << ": Sync session snapshot not available."; + << ": Sync service not available."; } } diff --git a/chrome/browser/sync/profile_sync_service_harness.h b/chrome/browser/sync/profile_sync_service_harness.h index 90f4540..a50bb8a 100644 --- a/chrome/browser/sync/profile_sync_service_harness.h +++ b/chrome/browser/sync/profile_sync_service_harness.h @@ -20,18 +20,27 @@ class Profile; // automation 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. In order to use this class for -// automation, derived classes must implement 2 methods: SignalStateComplete() -// and AwaitStatusChange(). +// several clients to get to the same state. class ProfileSyncServiceHarness : public ProfileSyncServiceObserver { public: - ProfileSyncServiceHarness(Profile* p, + ProfileSyncServiceHarness(Profile* profile, const std::string& username, const std::string& password, int id); virtual ~ProfileSyncServiceHarness() {} + // Creates a ProfileSyncServiceHarness object and attaches it to |profile|, a + // profile that is assumed to have been signed into sync in the past. Caller + // takes ownership. + static ProfileSyncServiceHarness* CreateAndAttach(Profile* profile); + + // Sets the GAIA credentials with which to sign in to sync. + void SetCredentials(const std::string& username, const std::string& password); + + // Returns true if sync has been enabled on |profile_|. + bool IsSyncAlreadySetup(); + // Creates a ProfileSyncService for the profile passed at construction and // enables sync for all available datatypes. Returns true only after sync has // been fully initialized and authenticated, and we are ready to process @@ -109,8 +118,11 @@ class ProfileSyncServiceHarness : public ProfileSyncServiceObserver { friend class StateChangeTimeoutEvent; enum WaitState { + // The sync client has just been initialized. + INITIAL_WAIT_STATE = 0, + // The sync client awaits the OnBackendInitialized() callback. - WAITING_FOR_ON_BACKEND_INITIALIZED = 0, + WAITING_FOR_ON_BACKEND_INITIALIZED, // The sync client is waiting for the first sync cycle to complete. WAITING_FOR_INITIAL_SYNC, @@ -139,10 +151,8 @@ class ProfileSyncServiceHarness : public ProfileSyncServiceObserver { // Called from the observer when the current wait state has been completed. void SignalStateCompleteWithNextState(WaitState next_state); - // Indicates that the operation being waited on is complete. Derived classes - // may implement this either by quitting the UI message loop, or by signaling - // a WaitableEvent object. - virtual void SignalStateComplete() = 0; + // Indicates that the operation being waited on is complete. + void SignalStateComplete(); // Finite state machine for controlling state. Returns true only if a state // change has taken place. @@ -152,26 +162,21 @@ class ProfileSyncServiceHarness : public ProfileSyncServiceObserver { bool AwaitStatusChangeWithTimeout(int timeout_milliseconds, const std::string& reason); - // Waits until the sync client's status changes. Derived classes may implement - // this either by running the UI message loop, or by waiting on a - // WaitableEvent object. - virtual void AwaitStatusChange() = 0; - // 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); + // Updates |last_timestamp_| with the timestamp of the current sync session. + // Returns the new value of |last_timestamp_|. + int64 GetUpdatedTimestamp(); + WaitState wait_state_; Profile* profile_; ProfileSyncService* service_; - // 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". diff --git a/chrome/browser/sync/syncable/model_type.cc b/chrome/browser/sync/syncable/model_type.cc index 5a06be8..2d17ebc 100644 --- a/chrome/browser/sync/syncable/model_type.cc +++ b/chrome/browser/sync/syncable/model_type.cc @@ -150,6 +150,33 @@ std::string ModelTypeToString(ModelType model_type) { } } +ModelType ModelTypeFromString(const std::string& model_type_string) { + if (model_type_string == "Bookmarks") + return BOOKMARKS; + else if (model_type_string == "Preferences") + return PREFERENCES; + else if (model_type_string == "Passwords") + return PASSWORDS; + else if (model_type_string == "Autofill") + return AUTOFILL; + else if (model_type_string == "Themes") + return THEMES; + else if (model_type_string == "Typed URLs") + return TYPED_URLS; + else if (model_type_string == "Extensions") + return EXTENSIONS; + else if (model_type_string == "Encryption keys") + return NIGORI; + else if (model_type_string == "Sessions") + return SESSIONS; + else if (model_type_string == "Apps") + return APPS; + else + NOTREACHED() << "No known model type corresponding to " + << model_type_string << "."; + return UNSPECIFIED; +} + // TODO(akalin): Figure out a better way to do these mappings. namespace { @@ -247,8 +274,7 @@ bool NotificationTypeToRealModelType(const std::string& notification_type, } else if (notification_type == kSessionNotificationType) { *model_type = SESSIONS; return true; - } - else if (notification_type == kUnknownNotificationType) { + } else if (notification_type == kUnknownNotificationType) { // TODO(akalin): This is a hack to make new sync data types work with // server-issued notifications. Remove this when it's not needed // anymore. diff --git a/chrome/browser/sync/syncable/model_type.h b/chrome/browser/sync/syncable/model_type.h index 077d243..c619b7e 100644 --- a/chrome/browser/sync/syncable/model_type.h +++ b/chrome/browser/sync/syncable/model_type.h @@ -89,8 +89,12 @@ ModelType GetModelType(const sync_pb::SyncEntity& sync_entity); // prefer using GetModelType where possible. ModelType GetModelTypeFromSpecifics(const sync_pb::EntitySpecifics& specifics); +// Returns a string that represents the name of |model_type|. std::string ModelTypeToString(ModelType model_type); +// Returns the ModelType corresponding to the name |model_type_string|. +ModelType ModelTypeFromString(const std::string& model_type_string); + // Convert a real model type to a notification type (used for // subscribing to server-issued notifications). Returns true iff // |model_type| was a real model type and |notification_type| was |