summaryrefslogtreecommitdiffstats
path: root/chrome/test
diff options
context:
space:
mode:
authorthakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-09-25 18:02:54 +0000
committerthakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-09-25 18:02:54 +0000
commit626a84f8de401f6d778a315fbab491a7574da234 (patch)
treec7334656c457a6fa7a6d01c1a05d115d5547f319 /chrome/test
parent80dbd7e3ae7e010c3286ec824893d1f58d127fc1 (diff)
downloadchromium_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')
-rw-r--r--chrome/test/live_sync/live_sync_test.cc4
-rw-r--r--chrome/test/live_sync/live_sync_test.h8
-rw-r--r--chrome/test/live_sync/multiple_client_live_bookmarks_sync_test.cc2
-rw-r--r--chrome/test/live_sync/profile_sync_service_test_harness.cc430
-rw-r--r--chrome/test/live_sync/profile_sync_service_test_harness.h164
-rw-r--r--chrome/test/live_sync/two_client_live_autofill_sync_test.cc20
-rw-r--r--chrome/test/live_sync/two_client_live_bookmarks_sync_test.cc24
-rw-r--r--chrome/test/live_sync/two_client_live_preferences_sync_test.cc6
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));