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 @@
#include "chrome/browser/sync/test/integration/single_client_status_change_checker.h"
#include "chrome/browser/ui/browser.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/common/channel_info.h"
#include "chrome/common/chrome_switches.h"
......@@ -130,19 +132,30 @@ void ProfileSyncServiceHarness::SetCredentials(const std::string& username,
}
bool ProfileSyncServiceHarness::SetupSync() {
bool result = SetupSync(syncer::UserSelectableTypes());
if (result == false) {
std::string status = GetServiceStatus();
LOG(ERROR) << profile_debug_name_
<< ": SetupSync failed. Syncer status:\n" << status;
bool result = SetupSync(syncer::UserSelectableTypes(), false);
if (!result) {
LOG(ERROR) << profile_debug_name_ << ": SetupSync failed. Syncer status:\n"
<< GetServiceStatus();
} else {
DVLOG(1) << profile_debug_name_ << ": SetupSync successful.";
}
return result;
}
bool ProfileSyncServiceHarness::SetupSync(
syncer::ModelTypeSet synced_datatypes) {
bool ProfileSyncServiceHarness::SetupSyncForClearingServerData() {
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())
<< "SetupSync should not be used for legacy supervised users.";
......@@ -179,17 +192,20 @@ bool ProfileSyncServiceHarness::SetupSync(
// Now that auth is completed, request that sync actually start.
service()->RequestStart();
if (!AwaitEngineInitialization()) {
if (!AwaitEngineInitialization(skip_passphrase_verification)) {
return false;
}
// Choose the datatypes to be synced. If all datatypes are to be synced,
// set sync_everything to true; otherwise, set it to false.
bool sync_everything = (synced_datatypes == syncer::UserSelectableTypes());
service()->OnUserChoseDatatypes(sync_everything, synced_datatypes);
// Notify ProfileSyncService that we are done with configuration.
FinishSyncSetup();
if (skip_passphrase_verification) {
sync_blocker_.reset();
} else {
FinishSyncSetup();
}
if ((signin_type_ == SigninType::UI_SIGNIN) &&
!login_ui_test_utils::DismissSyncConfirmationDialog(
......@@ -199,6 +215,20 @@ bool ProfileSyncServiceHarness::SetupSync(
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
// been set. If an explicit passphrase has been set, immediately return false,
// since a decryption passphrase is required.
......@@ -212,7 +242,43 @@ bool ProfileSyncServiceHarness::SetupSync(
// Wait for initial sync cycle to be completed.
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;
}
......@@ -246,7 +312,8 @@ bool ProfileSyncServiceHarness::AwaitQuiescence(
return QuiesceStatusChangeChecker(services).Wait();
}
bool ProfileSyncServiceHarness::AwaitEngineInitialization() {
bool ProfileSyncServiceHarness::AwaitEngineInitialization(
bool skip_passphrase_verification) {
if (!EngineInitializeChecker(service()).Wait()) {
LOG(ERROR) << "EngineInitializeChecker timed out.";
return false;
......@@ -258,7 +325,8 @@ bool ProfileSyncServiceHarness::AwaitEngineInitialization() {
}
// 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"
" until SetDecryptionPassphrase is called.";
return false;
......
......@@ -55,9 +55,21 @@ class ProfileSyncServiceHarness {
// changes.
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
// 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
// |partner| have both completed a sync cycle. When calling this method,
......@@ -86,7 +98,7 @@ class ProfileSyncServiceHarness {
// (e.g., auth error) is reached. Returns true if and only if the engine
// initialized successfully. See ProfileSyncService's IsEngineInitialized()
// 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
// if sync setup completed successfully. See syncer::SyncService's
......
......@@ -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.
for (int i = 0; i < num_clients_; ++i) {
if (!GetClient(i)->SetupSync()) {
for (; clientIndex < num_clients_; clientIndex++) {
DVLOG(1) << "Setting up " << clientIndex << " client";
if (!GetClient(clientIndex)->SetupSync()) {
LOG(FATAL) << "SetupSync() failed.";
return false;
}
......@@ -669,6 +681,23 @@ bool SyncTest::SetupSync() {
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() {
for (size_t i = 0; i < clients_.size(); ++i) {
clients_[i]->service()->RequestStop(ProfileSyncService::CLEAR_DATA);
......@@ -1148,3 +1177,14 @@ void SyncTest::SetPreexistingPreferencesFileContents(
const std::string& 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 {
// Initializes sync clients and profiles if required and syncs each of them.
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
// notifications of their own commits. Real sync clients do not do this, but
// many test assertions require this behavior.
......@@ -376,6 +379,9 @@ class SyncTest : public InProcessBrowserTest {
// value of |server_type_|.
void InitializeInvalidations(int index);
// Clear server data, and restart sync.
bool ClearServerData(ProfileSyncServiceHarness* harness);
// Python sync test server, started on demand.
syncer::LocalSyncTestServer sync_server_;
......
......@@ -1197,6 +1197,14 @@ void ProfileSyncService::OnClearServerDataDone() {
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(
const DataTypeManager::ConfigureResult& result) {
DCHECK(thread_checker_.CalledOnValidThread());
......@@ -1384,6 +1392,7 @@ bool ProfileSyncService::IsFirstSetupInProgress() const {
std::unique_ptr<syncer::SyncSetupInProgressHandle>
ProfileSyncService::GetSetupInProgressHandle() {
DCHECK(thread_checker_.CalledOnValidThread());
if (++outstanding_setup_in_progress_handles_ == 1) {
DCHECK(!startup_controller_->IsSetupInProgress());
startup_controller_->SetSetupInProgress(true);
......@@ -2434,5 +2443,4 @@ void ProfileSyncService::OnSetupInProgressHandleDestroyed() {
ReconfigureDatatypeManager();
NotifyObservers();
}
} // namespace browser_sync
......@@ -571,6 +571,10 @@ class ProfileSyncService : public syncer::SyncServiceBase,
// Triggers sync cycle with request to update specified |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:
// SyncServiceBase implementation.
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