summaryrefslogtreecommitdiffstats
path: root/chrome/browser/sync
diff options
context:
space:
mode:
authorkalman@chromium.org <kalman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-02-16 09:37:10 +0000
committerkalman@chromium.org <kalman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-02-16 09:37:10 +0000
commitdeb16806c9991b694052b4a6a34336bb261ccda3 (patch)
treee2b37f2afe9336f3724da7671d5254d0288f056d /chrome/browser/sync
parentb426e737a866aa08b258cc45d8bb7355fd284644 (diff)
downloadchromium_src-deb16806c9991b694052b4a6a34336bb261ccda3.zip
chromium_src-deb16806c9991b694052b4a6a34336bb261ccda3.tar.gz
chromium_src-deb16806c9991b694052b4a6a34336bb261ccda3.tar.bz2
Add sync integration tests for extension settings.
R=akalin@chromium.org BUG= TEST=sync_integrations_tests --gtest_filter=TwoClientExtensionSettingsSyncTest.* Review URL: http://codereview.chromium.org/9347014 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@122256 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/sync')
-rw-r--r--chrome/browser/sync/test/integration/apps_helper.cc2
-rw-r--r--chrome/browser/sync/test/integration/apps_helper.h5
-rw-r--r--chrome/browser/sync/test/integration/extension_settings_helper.cc119
-rw-r--r--chrome/browser/sync/test/integration/extension_settings_helper.h33
-rw-r--r--chrome/browser/sync/test/integration/extensions_helper.cc4
-rw-r--r--chrome/browser/sync/test/integration/extensions_helper.h7
-rw-r--r--chrome/browser/sync/test/integration/sync_extension_helper.cc10
-rw-r--r--chrome/browser/sync/test/integration/sync_extension_helper.h8
-rw-r--r--chrome/browser/sync/test/integration/two_client_extension_settings_sync_test.cc171
9 files changed, 344 insertions, 15 deletions
diff --git a/chrome/browser/sync/test/integration/apps_helper.cc b/chrome/browser/sync/test/integration/apps_helper.cc
index cdbbef6..d9501f5 100644
--- a/chrome/browser/sync/test/integration/apps_helper.cc
+++ b/chrome/browser/sync/test/integration/apps_helper.cc
@@ -40,7 +40,7 @@ bool AllProfilesHaveSameAppsAsVerifier() {
return true;
}
-void InstallApp(Profile* profile, int index) {
+std::string InstallApp(Profile* profile, int index) {
return SyncExtensionHelper::GetInstance()->InstallExtension(
profile, CreateFakeAppName(index), Extension::TYPE_HOSTED_APP);
}
diff --git a/chrome/browser/sync/test/integration/apps_helper.h b/chrome/browser/sync/test/integration/apps_helper.h
index b080866..c7faae0 100644
--- a/chrome/browser/sync/test/integration/apps_helper.h
+++ b/chrome/browser/sync/test/integration/apps_helper.h
@@ -22,8 +22,9 @@ bool HasSameAppsAsVerifier(int index) WARN_UNUSED_RESULT;
// Returns true iff all existing profiles have the same apps as the verifier.
bool AllProfilesHaveSameAppsAsVerifier() WARN_UNUSED_RESULT;
-// Installs the app for the given index to |profile|.
-void InstallApp(Profile* profile, int index);
+// Installs the app for the given index to |profile|, and returns the extension
+// ID of the new app.
+std::string InstallApp(Profile* profile, int index);
// Uninstalls the app for the given index from |profile|. Assumes that it was
// previously installed.
diff --git a/chrome/browser/sync/test/integration/extension_settings_helper.cc b/chrome/browser/sync/test/integration/extension_settings_helper.cc
new file mode 100644
index 0000000..b1a0a8b
--- /dev/null
+++ b/chrome/browser/sync/test/integration/extension_settings_helper.cc
@@ -0,0 +1,119 @@
+// Copyright (c) 2012 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 "chrome/browser/sync/test/integration/extension_settings_helper.h"
+
+#include "base/bind.h"
+#include "base/json/json_writer.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/logging.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/values.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/settings/settings_frontend.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/sync/test/integration/extensions_helper.h"
+#include "chrome/browser/sync/test/integration/sync_datatype_helper.h"
+#include "chrome/browser/sync/test/integration/sync_extension_helper.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/extension_set.h"
+
+using content::BrowserThread;
+using extensions::SettingsStorage;
+using sync_datatype_helper::test;
+
+namespace extension_settings_helper {
+
+namespace {
+
+std::string ToJson(const Value& value) {
+ std::string json;
+ base::JSONWriter::Write(&value, true /* pretty print */, &json);
+ return json;
+}
+
+void GetAllSettingsOnFileThread(
+ scoped_ptr<DictionaryValue>* out,
+ base::WaitableEvent* signal,
+ SettingsStorage* storage) {
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ out->reset(storage->Get().settings().DeepCopy());
+ signal->Signal();
+}
+
+scoped_ptr<DictionaryValue> GetAllSettings(
+ Profile* profile, const std::string& id) {
+ base::WaitableEvent signal(false, false);
+ scoped_ptr<DictionaryValue> settings;
+ profile->GetExtensionService()->settings_frontend()->RunWithStorage(
+ id,
+ extensions::settings_namespace::SYNC,
+ base::Bind(&GetAllSettingsOnFileThread, &settings, &signal));
+ signal.Wait();
+ return settings.Pass();
+}
+
+bool AreSettingsSame(Profile* expected_profile, Profile* actual_profile) {
+ const ExtensionSet* extensions =
+ expected_profile->GetExtensionService()->extensions();
+ if (extensions->size() !=
+ actual_profile->GetExtensionService()->extensions()->size()) {
+ ADD_FAILURE();
+ return false;
+ }
+
+ bool same = true;
+ for (ExtensionSet::const_iterator it = extensions->begin();
+ it != extensions->end(); ++it) {
+ const std::string& id = (*it)->id();
+ scoped_ptr<DictionaryValue> expected(GetAllSettings(expected_profile, id));
+ scoped_ptr<DictionaryValue> actual(GetAllSettings(actual_profile, id));
+ if (!expected->Equals(actual.get())) {
+ ADD_FAILURE() <<
+ "Expected " << ToJson(*expected) << " got " << ToJson(*actual);
+ same = false;
+ }
+ }
+ return same;
+}
+
+void SetSettingsOnFileThread(
+ const DictionaryValue* settings,
+ base::WaitableEvent* signal,
+ SettingsStorage* storage) {
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ storage->Set(SettingsStorage::DEFAULTS, *settings);
+ signal->Signal();
+}
+
+} // namespace
+
+void SetExtensionSettings(
+ Profile* profile, const std::string& id, const DictionaryValue& settings) {
+ base::WaitableEvent signal(false, false);
+ profile->GetExtensionService()->settings_frontend()->RunWithStorage(
+ id,
+ extensions::settings_namespace::SYNC,
+ base::Bind(&SetSettingsOnFileThread, &settings, &signal));
+ signal.Wait();
+}
+
+void SetExtensionSettingsForAllProfiles(
+ const std::string& id, const DictionaryValue& settings) {
+ for (int i = 0; i < test()->num_clients(); ++i)
+ SetExtensionSettings(test()->GetProfile(i), id, settings);
+ SetExtensionSettings(test()->verifier(), id, settings);
+}
+
+bool AllExtensionSettingsSameAsVerifier() {
+ bool all_profiles_same = true;
+ for (int i = 0; i < test()->num_clients(); ++i) {
+ // &= so that all profiles are tested; analogous to EXPECT over ASSERT.
+ all_profiles_same &=
+ AreSettingsSame(test()->verifier(), test()->GetProfile(i));
+ }
+ return all_profiles_same;
+}
+
+} // namespace extension_settings_helper
diff --git a/chrome/browser/sync/test/integration/extension_settings_helper.h b/chrome/browser/sync/test/integration/extension_settings_helper.h
new file mode 100644
index 0000000..7e92697
--- /dev/null
+++ b/chrome/browser/sync/test/integration/extension_settings_helper.h
@@ -0,0 +1,33 @@
+// Copyright (c) 2012 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_BROWSER_SYNC_TEST_INTEGRATION_EXTENSION_SETTINGS_HELPER_H_
+#define CHROME_BROWSER_SYNC_TEST_INTEGRATION_EXTENSION_SETTINGS_HELPER_H_
+#pragma once
+
+#include <string>
+
+class Profile;
+namespace base {
+class DictionaryValue;
+}
+
+namespace extension_settings_helper {
+
+// Calls Set() with |settings| for |profile| and the extension with ID |id|.
+void SetExtensionSettings(
+ Profile* profile,
+ const std::string& id,
+ const base::DictionaryValue& settings);
+
+// Calls Set() with |settings| for all profiles the extension with ID |id|.
+void SetExtensionSettingsForAllProfiles(
+ const std::string& id, const base::DictionaryValue& settings);
+
+// Returns whether the extension settings are the same across all profiles.
+bool AllExtensionSettingsSameAsVerifier();
+
+} // namespace extension_settings_helper
+
+#endif // CHROME_BROWSER_SYNC_TEST_INTEGRATION_EXTENSION_SETTINGS_HELPER_H_
diff --git a/chrome/browser/sync/test/integration/extensions_helper.cc b/chrome/browser/sync/test/integration/extensions_helper.cc
index 6358e88..346610a 100644
--- a/chrome/browser/sync/test/integration/extensions_helper.cc
+++ b/chrome/browser/sync/test/integration/extensions_helper.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -49,7 +49,7 @@ bool AllProfilesHaveSameExtensions() {
}
-void InstallExtension(Profile* profile, int index) {
+std::string InstallExtension(Profile* profile, int index) {
return SyncExtensionHelper::GetInstance()->InstallExtension(
profile, CreateFakeExtensionName(index), Extension::TYPE_EXTENSION);
}
diff --git a/chrome/browser/sync/test/integration/extensions_helper.h b/chrome/browser/sync/test/integration/extensions_helper.h
index 25fe367..20f95d6 100644
--- a/chrome/browser/sync/test/integration/extensions_helper.h
+++ b/chrome/browser/sync/test/integration/extensions_helper.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -28,8 +28,9 @@ bool AllProfilesHaveSameExtensionsAsVerifier() WARN_UNUSED_RESULT;
// Returns true iff all existing profiles have the same extensions.
bool AllProfilesHaveSameExtensions() WARN_UNUSED_RESULT;
-// Installs the extension for the given index to |profile|.
-void InstallExtension(Profile* profile, int index);
+// Installs the extension for the given index to |profile|, and returns the
+// extension ID of the new extension.
+std::string InstallExtension(Profile* profile, int index);
// Uninstalls the extension for the given index from |profile|. Assumes that
// it was previously installed.
diff --git a/chrome/browser/sync/test/integration/sync_extension_helper.cc b/chrome/browser/sync/test/integration/sync_extension_helper.cc
index 6eeb49d..39e6298 100644
--- a/chrome/browser/sync/test/integration/sync_extension_helper.cc
+++ b/chrome/browser/sync/test/integration/sync_extension_helper.cc
@@ -12,6 +12,7 @@
#include "chrome/browser/extensions/pending_extension_info.h"
#include "chrome/browser/extensions/pending_extension_manager.h"
#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/string_ordinal.h"
#include "chrome/browser/sync/test/integration/sync_test.h"
@@ -59,13 +60,16 @@ void SyncExtensionHelper::SetupIfNecessary(SyncTest* test) {
setup_completed_ = true;
}
-void SyncExtensionHelper::InstallExtension(
+std::string SyncExtensionHelper::InstallExtension(
Profile* profile, const std::string& name, Extension::Type type) {
scoped_refptr<Extension> extension = GetExtension(profile, name, type);
- ASSERT_TRUE(extension.get()) << "Could not get extension " << name
- << " (profile = " << profile << ")";
+ if (!extension.get()) {
+ NOTREACHED() << "Could not install extension " << name;
+ return "";
+ }
profile->GetExtensionService()->OnExtensionInstalled(
extension, extension->UpdatesFromGallery(), StringOrdinal());
+ return extension->id();
}
void SyncExtensionHelper::UninstallExtension(
diff --git a/chrome/browser/sync/test/integration/sync_extension_helper.h b/chrome/browser/sync/test/integration/sync_extension_helper.h
index 7968556..1e85afe 100644
--- a/chrome/browser/sync/test/integration/sync_extension_helper.h
+++ b/chrome/browser/sync/test/integration/sync_extension_helper.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -16,7 +16,6 @@
#include "base/memory/singleton.h"
#include "chrome/common/extensions/extension.h"
-class Extension;
class Profile;
class SyncTest;
@@ -32,8 +31,9 @@ class SyncExtensionHelper {
// internal data structures.
void SetupIfNecessary(SyncTest* test);
- // Installs the extension with the given name to |profile|.
- void InstallExtension(
+ // Installs the extension with the given name to |profile|, and returns the
+ // extension ID of the new extension.
+ std::string InstallExtension(
Profile* profile, const std::string& name, Extension::Type type);
// Uninstalls the extension with the given name from |profile|.
diff --git a/chrome/browser/sync/test/integration/two_client_extension_settings_sync_test.cc b/chrome/browser/sync/test/integration/two_client_extension_settings_sync_test.cc
new file mode 100644
index 0000000..bd581dd
--- /dev/null
+++ b/chrome/browser/sync/test/integration/two_client_extension_settings_sync_test.cc
@@ -0,0 +1,171 @@
+// Copyright (c) 2012 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/stringprintf.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/sync/profile_sync_service_harness.h"
+#include "chrome/browser/sync/test/integration/extension_settings_helper.h"
+#include "chrome/browser/sync/test/integration/extensions_helper.h"
+#include "chrome/browser/sync/test/integration/sync_datatype_helper.h"
+#include "chrome/browser/sync/test/integration/sync_test.h"
+
+namespace {
+
+using extension_settings_helper::SetExtensionSettings;
+using extension_settings_helper::SetExtensionSettingsForAllProfiles;
+using extension_settings_helper::AllExtensionSettingsSameAsVerifier;
+using extensions_helper::InstallExtension;
+using sync_datatype_helper::test;
+
+std::string InstallExtensionForAllProfiles(int index) {
+ for (int i = 0; i < test()->num_clients(); ++i)
+ InstallExtension(test()->GetProfile(i), index);
+ return InstallExtension(test()->verifier(), index);
+}
+
+// Generic mutations done after the initial setup of all tests. Note that
+// unfortuately we can't test existing configurations of the sync server since
+// the tests don't support that.
+void MutateSomeSettings(
+ int seed, // used to modify the mutation values, not keys.
+ const std::string& extension0,
+ const std::string& extension1,
+ const std::string& extension2) {
+ {
+ // Write to extension0 from profile 0 but not profile 1.
+ DictionaryValue settings;
+ settings.SetString("asdf", StringPrintf("asdfasdf-%d", seed));
+ SetExtensionSettings(test()->verifier(), extension0, settings);
+ SetExtensionSettings(test()->GetProfile(0), extension0, settings);
+ }
+ {
+ // Write the same data to extension1 from both profiles.
+ DictionaryValue settings;
+ settings.SetString("asdf", StringPrintf("asdfasdf-%d", seed));
+ settings.SetString("qwer", StringPrintf("qwerqwer-%d", seed));
+ SetExtensionSettingsForAllProfiles(extension1, settings);
+ }
+ {
+ // Write different data to extension2 from each profile.
+ DictionaryValue settings0;
+ settings0.SetString("zxcv", StringPrintf("zxcvzxcv-%d", seed));
+ SetExtensionSettings(test()->verifier(), extension2, settings0);
+ SetExtensionSettings(test()->GetProfile(0), extension2, settings0);
+
+ DictionaryValue settings1;
+ settings1.SetString("1324", StringPrintf("12341234-%d", seed));
+ settings1.SetString("5687", StringPrintf("56785678-%d", seed));
+ SetExtensionSettings(test()->verifier(), extension2, settings1);
+ SetExtensionSettings(test()->GetProfile(1), extension2, settings1);
+ }
+}
+
+class TwoClientExtensionSettingsSyncTest : public SyncTest {
+ public:
+ TwoClientExtensionSettingsSyncTest() : SyncTest(TWO_CLIENT) {}
+ virtual ~TwoClientExtensionSettingsSyncTest() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TwoClientExtensionSettingsSyncTest);
+};
+
+// For three independent extensions:
+//
+// Set up each extension with the same (but not necessarily empty) settings for
+// all profiles, start syncing, add some new settings, sync, mutate those
+// settings, sync.
+IN_PROC_BROWSER_TEST_F(TwoClientExtensionSettingsSyncTest,
+ StartWithSameSettings) {
+ ASSERT_TRUE(SetupClients());
+
+ const std::string& extension0 = InstallExtensionForAllProfiles(0);
+ const std::string& extension1 = InstallExtensionForAllProfiles(1);
+ const std::string& extension2 = InstallExtensionForAllProfiles(2);
+
+ {
+ // Leave extension0 empty.
+ }
+ {
+ DictionaryValue settings;
+ settings.SetString("foo", "bar");
+ SetExtensionSettingsForAllProfiles(extension1, settings);
+ }
+ {
+ DictionaryValue settings;
+ settings.SetString("foo", "bar");
+ settings.SetString("baz", "qux");
+ SetExtensionSettingsForAllProfiles(extension2, settings);
+ }
+
+ ASSERT_TRUE(SetupSync());
+ ASSERT_TRUE(AwaitQuiescence());
+ ASSERT_TRUE(AllExtensionSettingsSameAsVerifier());
+
+ MutateSomeSettings(0, extension0, extension1, extension2);
+ ASSERT_TRUE(AwaitQuiescence());
+ ASSERT_TRUE(AllExtensionSettingsSameAsVerifier());
+
+ MutateSomeSettings(1, extension0, extension1, extension2);
+ ASSERT_TRUE(AwaitQuiescence());
+ ASSERT_TRUE(AllExtensionSettingsSameAsVerifier());
+}
+
+// For three independent extensions:
+//
+// Set up each extension with different settings for each profile, start
+// syncing, add some settings, sync, mutate those settings, sync, have a no-op
+// (non-)change to those settings, sync, mutate again, sync.
+IN_PROC_BROWSER_TEST_F(TwoClientExtensionSettingsSyncTest,
+ StartWithDifferentSettings) {
+ ASSERT_TRUE(SetupClients());
+
+ const std::string& extension0 = InstallExtensionForAllProfiles(0);
+ const std::string& extension1 = InstallExtensionForAllProfiles(1);
+ const std::string& extension2 = InstallExtensionForAllProfiles(2);
+
+ {
+ // Leave extension0 empty again for no particular reason other than it's
+ // the only remaining unique combination given the other 2 tests have
+ // (empty, nonempty) and (nonempty, nonempty) configurations. We can't test
+ // (nonempty, nonempty) because the merging will provide unpredictable
+ // results, so test (empty, empty).
+ }
+ {
+ DictionaryValue settings;
+ settings.SetString("foo", "bar");
+ SetExtensionSettings(test()->verifier(), extension1, settings);
+ SetExtensionSettings(test()->GetProfile(0), extension1, settings);
+ }
+ {
+ DictionaryValue settings;
+ settings.SetString("foo", "bar");
+ settings.SetString("baz", "qux");
+ SetExtensionSettings(test()->verifier(), extension2, settings);
+ SetExtensionSettings(test()->GetProfile(1), extension2, settings);
+ }
+
+ ASSERT_TRUE(SetupSync());
+ ASSERT_TRUE(AwaitQuiescence());
+ ASSERT_TRUE(AllExtensionSettingsSameAsVerifier());
+
+ MutateSomeSettings(2, extension0, extension1, extension2);
+ ASSERT_TRUE(AwaitQuiescence());
+ ASSERT_TRUE(AllExtensionSettingsSameAsVerifier());
+
+ MutateSomeSettings(3, extension0, extension1, extension2);
+ ASSERT_TRUE(AwaitQuiescence());
+ ASSERT_TRUE(AllExtensionSettingsSameAsVerifier());
+
+ // Test a round of no-ops once, for sanity. Ideally we'd want to assert that
+ // this causes no sync activity, but that sounds tricky.
+ MutateSomeSettings(3, extension0, extension1, extension2);
+ ASSERT_TRUE(AwaitQuiescence());
+ ASSERT_TRUE(AllExtensionSettingsSameAsVerifier());
+
+ MutateSomeSettings(4, extension0, extension1, extension2);
+ ASSERT_TRUE(AwaitQuiescence());
+ ASSERT_TRUE(AllExtensionSettingsSameAsVerifier());
+}
+
+} // namespace