Commit 0b596d6a authored by wylieb's avatar wylieb Committed by Commit bot

Initial clear server data impl.

When we run integration tests, we need accounts with a clean slate.
This CL clears out the data on sync servers for the given test account,
and restarts sync. This operation doesn't require read/writing any data
to the account, and thus passphrase decryption is by-passed (Some tests
have the side-effect of setting a decryption passphrase that requires
clear server data to be run without decryption).

R=pavely@chromium.org,skym@chromium.org

TEST=run this command
ninja -C out/Debug sync_integration_tests -j 200 && \
xvfb-run --server-args="-screen 0 1920x1080x24" \
out/Debug/sync_integration_tests \
--gtest_also_run_disabled_tests \
--gtest_filter=*E2ETest* \
--sync-url=https://clients4.google.com/chrome-sync/dev \
--sync-user-for-test=testuser@gmail.com\
--sync-password-for-test=testpassword
--vmodule=*sync*=1

BUG=

Review-Url: https://codereview.chromium.org/2716413003
Cr-Commit-Position: refs/heads/master@{#456199}
parent 18de5022
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
#include "chrome/browser/sync/test/integration/single_client_status_change_checker.h" #include "chrome/browser/sync/test/integration/single_client_status_change_checker.h"
#include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/webui/signin/login_ui_service.h"
#include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
#include "chrome/browser/ui/webui/signin/login_ui_test_utils.h" #include "chrome/browser/ui/webui/signin/login_ui_test_utils.h"
#include "chrome/common/channel_info.h" #include "chrome/common/channel_info.h"
#include "chrome/common/chrome_switches.h" #include "chrome/common/chrome_switches.h"
...@@ -130,19 +132,30 @@ void ProfileSyncServiceHarness::SetCredentials(const std::string& username, ...@@ -130,19 +132,30 @@ void ProfileSyncServiceHarness::SetCredentials(const std::string& username,
} }
bool ProfileSyncServiceHarness::SetupSync() { bool ProfileSyncServiceHarness::SetupSync() {
bool result = SetupSync(syncer::UserSelectableTypes()); bool result = SetupSync(syncer::UserSelectableTypes(), false);
if (result == false) { if (!result) {
std::string status = GetServiceStatus(); LOG(ERROR) << profile_debug_name_ << ": SetupSync failed. Syncer status:\n"
LOG(ERROR) << profile_debug_name_ << GetServiceStatus();
<< ": SetupSync failed. Syncer status:\n" << status;
} else { } else {
DVLOG(1) << profile_debug_name_ << ": SetupSync successful."; DVLOG(1) << profile_debug_name_ << ": SetupSync successful.";
} }
return result; return result;
} }
bool ProfileSyncServiceHarness::SetupSync( bool ProfileSyncServiceHarness::SetupSyncForClearingServerData() {
syncer::ModelTypeSet synced_datatypes) { bool result = SetupSync(syncer::UserSelectableTypes(), true);
if (!result) {
LOG(ERROR) << profile_debug_name_
<< ": SetupSyncForClear failed. Syncer status:\n"
<< GetServiceStatus();
} else {
DVLOG(1) << profile_debug_name_ << ": SetupSyncForClear successful.";
}
return result;
}
bool ProfileSyncServiceHarness::SetupSync(syncer::ModelTypeSet synced_datatypes,
bool skip_passphrase_verification) {
DCHECK(!profile_->IsLegacySupervised()) DCHECK(!profile_->IsLegacySupervised())
<< "SetupSync should not be used for legacy supervised users."; << "SetupSync should not be used for legacy supervised users.";
...@@ -179,17 +192,20 @@ bool ProfileSyncServiceHarness::SetupSync( ...@@ -179,17 +192,20 @@ bool ProfileSyncServiceHarness::SetupSync(
// Now that auth is completed, request that sync actually start. // Now that auth is completed, request that sync actually start.
service()->RequestStart(); service()->RequestStart();
if (!AwaitEngineInitialization()) { if (!AwaitEngineInitialization(skip_passphrase_verification)) {
return false; return false;
} }
// Choose the datatypes to be synced. If all datatypes are to be synced, // Choose the datatypes to be synced. If all datatypes are to be synced,
// set sync_everything to true; otherwise, set it to false. // set sync_everything to true; otherwise, set it to false.
bool sync_everything = (synced_datatypes == syncer::UserSelectableTypes()); bool sync_everything = (synced_datatypes == syncer::UserSelectableTypes());
service()->OnUserChoseDatatypes(sync_everything, synced_datatypes); service()->OnUserChoseDatatypes(sync_everything, synced_datatypes);
// Notify ProfileSyncService that we are done with configuration. // Notify ProfileSyncService that we are done with configuration.
FinishSyncSetup(); if (skip_passphrase_verification) {
sync_blocker_.reset();
} else {
FinishSyncSetup();
}
if ((signin_type_ == SigninType::UI_SIGNIN) && if ((signin_type_ == SigninType::UI_SIGNIN) &&
!login_ui_test_utils::DismissSyncConfirmationDialog( !login_ui_test_utils::DismissSyncConfirmationDialog(
...@@ -199,6 +215,20 @@ bool ProfileSyncServiceHarness::SetupSync( ...@@ -199,6 +215,20 @@ bool ProfileSyncServiceHarness::SetupSync(
return false; return false;
} }
// OneClickSigninSyncStarter observer is created with a real user sign in.
// It is deleted on certain conditions which are not satisfied by our tests,
// and this causes the SigninTracker observer to stay hanging at shutdown.
// Calling LoginUIService::SyncConfirmationUIClosed forces the observer to
// be removed. http://crbug.com/484388
if (signin_type_ == SigninType::UI_SIGNIN) {
LoginUIServiceFactory::GetForProfile(profile_)->SyncConfirmationUIClosed(
LoginUIService::SYNC_WITH_DEFAULT_SETTINGS);
}
if (skip_passphrase_verification) {
return true;
}
// Set an implicit passphrase for encryption if an explicit one hasn't already // Set an implicit passphrase for encryption if an explicit one hasn't already
// been set. If an explicit passphrase has been set, immediately return false, // been set. If an explicit passphrase has been set, immediately return false,
// since a decryption passphrase is required. // since a decryption passphrase is required.
...@@ -212,7 +242,43 @@ bool ProfileSyncServiceHarness::SetupSync( ...@@ -212,7 +242,43 @@ bool ProfileSyncServiceHarness::SetupSync(
// Wait for initial sync cycle to be completed. // Wait for initial sync cycle to be completed.
if (!AwaitSyncSetupCompletion()) { if (!AwaitSyncSetupCompletion()) {
LOG(ERROR) << "Initial sync cycle timed out."; return false;
}
return true;
}
bool ProfileSyncServiceHarness::RestartSyncService() {
DVLOG(1) << "Requesting stop for service.";
service()->RequestStop(ProfileSyncService::CLEAR_DATA);
std::unique_ptr<syncer::SyncSetupInProgressHandle> blocker =
service()->GetSetupInProgressHandle();
DVLOG(1) << "Requesting start for service";
service()->RequestStart();
if (!AwaitEngineInitialization()) {
LOG(ERROR) << "AwaitEngineInitialization failed.";
return false;
}
DVLOG(1) << "Engine Initialized successfully.";
// This passphrase should be implicit because ClearServerData should be called
// prior.
if (!service()->IsUsingSecondaryPassphrase()) {
service()->SetEncryptionPassphrase(password_, ProfileSyncService::IMPLICIT);
} else {
LOG(ERROR) << "A passphrase is required for decryption. Sync cannot proceed"
" until SetDecryptionPassphrase is called.";
return false;
}
DVLOG(1) << "Passphrase decryption success.";
blocker.reset();
service()->SetFirstSetupComplete();
if (!AwaitSyncSetupCompletion()) {
LOG(FATAL) << "AwaitSyncSetupCompletion failed.";
return false; return false;
} }
...@@ -246,7 +312,8 @@ bool ProfileSyncServiceHarness::AwaitQuiescence( ...@@ -246,7 +312,8 @@ bool ProfileSyncServiceHarness::AwaitQuiescence(
return QuiesceStatusChangeChecker(services).Wait(); return QuiesceStatusChangeChecker(services).Wait();
} }
bool ProfileSyncServiceHarness::AwaitEngineInitialization() { bool ProfileSyncServiceHarness::AwaitEngineInitialization(
bool skip_passphrase_verification) {
if (!EngineInitializeChecker(service()).Wait()) { if (!EngineInitializeChecker(service()).Wait()) {
LOG(ERROR) << "EngineInitializeChecker timed out."; LOG(ERROR) << "EngineInitializeChecker timed out.";
return false; return false;
...@@ -258,7 +325,8 @@ bool ProfileSyncServiceHarness::AwaitEngineInitialization() { ...@@ -258,7 +325,8 @@ bool ProfileSyncServiceHarness::AwaitEngineInitialization() {
} }
// Make sure that initial sync wasn't blocked by a missing passphrase. // Make sure that initial sync wasn't blocked by a missing passphrase.
if (service()->passphrase_required_reason() == syncer::REASON_DECRYPTION) { if (!skip_passphrase_verification &&
service()->passphrase_required_reason() == syncer::REASON_DECRYPTION) {
LOG(ERROR) << "A passphrase is required for decryption. Sync cannot proceed" LOG(ERROR) << "A passphrase is required for decryption. Sync cannot proceed"
" until SetDecryptionPassphrase is called."; " until SetDecryptionPassphrase is called.";
return false; return false;
......
...@@ -55,9 +55,21 @@ class ProfileSyncServiceHarness { ...@@ -55,9 +55,21 @@ class ProfileSyncServiceHarness {
// changes. // changes.
bool SetupSync(); bool SetupSync();
// Setup sync without the authenticating through the passphrase encryption.
// Use this method when you need to setup a client that you're going to call
// RestartSyncService() directly after.
bool SetupSyncForClearingServerData();
// Both SetupSync and SetupSyncForClear call into this method.
// Same as the above method, but enables sync only for the datatypes contained // Same as the above method, but enables sync only for the datatypes contained
// in |synced_datatypes|. // in |synced_datatypes|.
bool SetupSync(syncer::ModelTypeSet synced_datatypes); bool SetupSync(syncer::ModelTypeSet synced_datatypes,
bool skip_passphrase_verification = false);
// Restart sync service to simulate a sign-in/sign-out. This is useful
// to recover from a lost birthday. Use directly after a clear server data
// command to start from clean slate.
bool RestartSyncService();
// Calling this acts as a barrier and blocks the caller until |this| and // Calling this acts as a barrier and blocks the caller until |this| and
// |partner| have both completed a sync cycle. When calling this method, // |partner| have both completed a sync cycle. When calling this method,
...@@ -86,7 +98,7 @@ class ProfileSyncServiceHarness { ...@@ -86,7 +98,7 @@ class ProfileSyncServiceHarness {
// (e.g., auth error) is reached. Returns true if and only if the engine // (e.g., auth error) is reached. Returns true if and only if the engine
// initialized successfully. See ProfileSyncService's IsEngineInitialized() // initialized successfully. See ProfileSyncService's IsEngineInitialized()
// method for the definition of engine initialization. // method for the definition of engine initialization.
bool AwaitEngineInitialization(); bool AwaitEngineInitialization(bool skip_passphrase_verification = false);
// Blocks the caller until sync setup is complete. Returns true if and only // Blocks the caller until sync setup is complete. Returns true if and only
// if sync setup completed successfully. See syncer::SyncService's // if sync setup completed successfully. See syncer::SyncService's
......
...@@ -620,9 +620,21 @@ bool SyncTest::SetupSync() { ...@@ -620,9 +620,21 @@ bool SyncTest::SetupSync() {
} }
} }
int clientIndex = 0;
// If we're using external servers, clear server data so the account starts
// with a clean slate.
if (UsingExternalServers()) {
if (!SetupAndClearClient(clientIndex++)) {
LOG(FATAL) << "Setting up and clearing data for client "
<< clientIndex - 1 << " failed";
return false;
}
}
// Sync each of the profiles. // Sync each of the profiles.
for (int i = 0; i < num_clients_; ++i) { for (; clientIndex < num_clients_; clientIndex++) {
if (!GetClient(i)->SetupSync()) { DVLOG(1) << "Setting up " << clientIndex << " client";
if (!GetClient(clientIndex)->SetupSync()) {
LOG(FATAL) << "SetupSync() failed."; LOG(FATAL) << "SetupSync() failed.";
return false; return false;
} }
...@@ -669,6 +681,23 @@ bool SyncTest::SetupSync() { ...@@ -669,6 +681,23 @@ bool SyncTest::SetupSync() {
return true; return true;
} }
bool SyncTest::SetupAndClearClient(size_t index) {
// Setup the first client so the sync engine is initialized, which is
// required to clear server data.
DVLOG(1) << "Setting up first client for clear.";
if (!GetClient(index)->SetupSyncForClearingServerData()) {
LOG(FATAL) << "SetupSync() failed.";
return false;
}
DVLOG(1) << "Done setting up first client for clear.";
if (!ClearServerData(GetClient(index++))) {
LOG(FATAL) << "ClearServerData failed.";
return false;
}
return true;
}
void SyncTest::TearDownOnMainThread() { void SyncTest::TearDownOnMainThread() {
for (size_t i = 0; i < clients_.size(); ++i) { for (size_t i = 0; i < clients_.size(); ++i) {
clients_[i]->service()->RequestStop(ProfileSyncService::CLEAR_DATA); clients_[i]->service()->RequestStop(ProfileSyncService::CLEAR_DATA);
...@@ -1148,3 +1177,14 @@ void SyncTest::SetPreexistingPreferencesFileContents( ...@@ -1148,3 +1177,14 @@ void SyncTest::SetPreexistingPreferencesFileContents(
const std::string& contents) { const std::string& contents) {
preexisting_preferences_file_contents_ = contents; preexisting_preferences_file_contents_ = contents;
} }
bool SyncTest::ClearServerData(ProfileSyncServiceHarness* harness) {
// At this point our birthday is good.
base::RunLoop run_loop;
harness->service()->ClearServerDataForTest(run_loop.QuitClosure());
run_loop.Run();
// Our birthday is invalidated on the server here so restart sync to get
// the new birthday from the server.
return harness->RestartSyncService();
}
...@@ -180,6 +180,9 @@ class SyncTest : public InProcessBrowserTest { ...@@ -180,6 +180,9 @@ class SyncTest : public InProcessBrowserTest {
// Initializes sync clients and profiles if required and syncs each of them. // Initializes sync clients and profiles if required and syncs each of them.
virtual bool SetupSync() WARN_UNUSED_RESULT; virtual bool SetupSync() WARN_UNUSED_RESULT;
// Initialize, and clear data for given client.
bool SetupAndClearClient(size_t index);
// Sets whether or not the sync clients in this test should respond to // Sets whether or not the sync clients in this test should respond to
// notifications of their own commits. Real sync clients do not do this, but // notifications of their own commits. Real sync clients do not do this, but
// many test assertions require this behavior. // many test assertions require this behavior.
...@@ -376,6 +379,9 @@ class SyncTest : public InProcessBrowserTest { ...@@ -376,6 +379,9 @@ class SyncTest : public InProcessBrowserTest {
// value of |server_type_|. // value of |server_type_|.
void InitializeInvalidations(int index); void InitializeInvalidations(int index);
// Clear server data, and restart sync.
bool ClearServerData(ProfileSyncServiceHarness* harness);
// Python sync test server, started on demand. // Python sync test server, started on demand.
syncer::LocalSyncTestServer sync_server_; syncer::LocalSyncTestServer sync_server_;
......
...@@ -1197,6 +1197,14 @@ void ProfileSyncService::OnClearServerDataDone() { ...@@ -1197,6 +1197,14 @@ void ProfileSyncService::OnClearServerDataDone() {
syncer::CLEAR_SERVER_DATA_MAX); syncer::CLEAR_SERVER_DATA_MAX);
} }
void ProfileSyncService::ClearServerDataForTest(const base::Closure& callback) {
DCHECK(thread_checker_.CalledOnValidThread());
// Sync has a restriction that the engine must be in configuration mode
// in order to run clear server data.
engine_->StartConfiguration();
engine_->ClearServerData(callback);
}
void ProfileSyncService::OnConfigureDone( void ProfileSyncService::OnConfigureDone(
const DataTypeManager::ConfigureResult& result) { const DataTypeManager::ConfigureResult& result) {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
...@@ -1384,6 +1392,7 @@ bool ProfileSyncService::IsFirstSetupInProgress() const { ...@@ -1384,6 +1392,7 @@ bool ProfileSyncService::IsFirstSetupInProgress() const {
std::unique_ptr<syncer::SyncSetupInProgressHandle> std::unique_ptr<syncer::SyncSetupInProgressHandle>
ProfileSyncService::GetSetupInProgressHandle() { ProfileSyncService::GetSetupInProgressHandle() {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
if (++outstanding_setup_in_progress_handles_ == 1) { if (++outstanding_setup_in_progress_handles_ == 1) {
DCHECK(!startup_controller_->IsSetupInProgress()); DCHECK(!startup_controller_->IsSetupInProgress());
startup_controller_->SetSetupInProgress(true); startup_controller_->SetSetupInProgress(true);
...@@ -2434,5 +2443,4 @@ void ProfileSyncService::OnSetupInProgressHandleDestroyed() { ...@@ -2434,5 +2443,4 @@ void ProfileSyncService::OnSetupInProgressHandleDestroyed() {
ReconfigureDatatypeManager(); ReconfigureDatatypeManager();
NotifyObservers(); NotifyObservers();
} }
} // namespace browser_sync } // namespace browser_sync
...@@ -571,6 +571,10 @@ class ProfileSyncService : public syncer::SyncServiceBase, ...@@ -571,6 +571,10 @@ class ProfileSyncService : public syncer::SyncServiceBase,
// Triggers sync cycle with request to update specified |types|. // Triggers sync cycle with request to update specified |types|.
void RefreshTypesForTest(syncer::ModelTypeSet types); void RefreshTypesForTest(syncer::ModelTypeSet types);
// Calls sync engine to send ClearServerDataMessage to server. This is used
// to start accounts with a clean slate when performing end to end testing.
void ClearServerDataForTest(const base::Closure& callback);
protected: protected:
// SyncServiceBase implementation. // SyncServiceBase implementation.
syncer::SyncCredentials GetCredentials() override; syncer::SyncCredentials GetCredentials() override;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment