summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authoralbertb@chromium.org <albertb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-14 20:04:01 +0000
committeralbertb@chromium.org <albertb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-14 20:04:01 +0000
commit18b147138e014805955bfcb5dc93e2191d6e2447 (patch)
treed9ce47b6dc2569738022cb083f49838b52cb8fc7 /chrome
parent50e3e21c297fcc1945ece4ed163053d7128a141d (diff)
downloadchromium_src-18b147138e014805955bfcb5dc93e2191d6e2447.zip
chromium_src-18b147138e014805955bfcb5dc93e2191d6e2447.tar.gz
chromium_src-18b147138e014805955bfcb5dc93e2191d6e2447.tar.bz2
Integration tests for password sync.
BUG=none TEST=self Review URL: http://codereview.chromium.org/3701007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@62632 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/password_manager/password_form_data.cc74
-rw-r--r--chrome/browser/password_manager/password_form_data.h57
-rw-r--r--chrome/browser/password_manager/password_store.h1
-rw-r--r--chrome/chrome_tests.gypi6
-rw-r--r--chrome/test/live_sync/live_passwords_sync_test.h125
-rw-r--r--chrome/test/live_sync/live_sync_test.cc5
-rw-r--r--chrome/test/live_sync/many_client_live_passwords_sync_test.cc33
-rw-r--r--chrome/test/live_sync/multiple_client_live_passwords_sync_test.cc36
-rw-r--r--chrome/test/live_sync/single_client_live_passwords_sync_test.cc31
-rw-r--r--chrome/test/live_sync/two_client_live_passwords_sync_test.cc65
10 files changed, 386 insertions, 47 deletions
diff --git a/chrome/browser/password_manager/password_form_data.cc b/chrome/browser/password_manager/password_form_data.cc
index ef9391d..b428d9a 100644
--- a/chrome/browser/password_manager/password_form_data.cc
+++ b/chrome/browser/password_manager/password_form_data.cc
@@ -36,3 +36,77 @@ PasswordForm* CreatePasswordFormFromData(
}
return form;
}
+
+bool operator==(const PasswordForm& lhs, const PasswordForm& rhs) {
+ return (lhs.scheme == rhs.scheme &&
+ lhs.signon_realm == rhs.signon_realm &&
+ lhs.origin == rhs.origin &&
+ lhs.action == rhs.action &&
+ lhs.submit_element == rhs.submit_element &&
+ lhs.username_element == rhs.username_element &&
+ lhs.password_element == rhs.password_element &&
+ lhs.username_value == rhs.username_value &&
+ lhs.password_value == rhs.password_value &&
+ lhs.blacklisted_by_user == rhs.blacklisted_by_user &&
+ lhs.preferred == rhs.preferred &&
+ lhs.ssl_valid == rhs.ssl_valid &&
+ lhs.date_created == rhs.date_created);
+}
+
+std::ostream& operator<<(std::ostream& os, const PasswordForm& form) {
+ return os << "scheme: " << form.scheme << std::endl
+ << "signon_realm: " << form.signon_realm << std::endl
+ << "origin: " << form.origin << std::endl
+ << "action: " << form.action << std::endl
+ << "submit_element: " << form.submit_element << std::endl
+ << "username_elem: " << form.username_element << std::endl
+ << "password_elem: " << form.password_element << std::endl
+ << "username_value: " << form.username_value << std::endl
+ << "password_value: " << form.password_value << std::endl
+ << "blacklisted: " << form.blacklisted_by_user << std::endl
+ << "preferred: " << form.preferred << std::endl
+ << "ssl_valid: " << form.ssl_valid << std::endl
+ << "date_created: " << form.date_created.ToDoubleT();
+}
+
+typedef std::set<const webkit_glue::PasswordForm*> SetOfForms;
+
+bool ContainsSamePasswordFormsPtr(
+ const std::vector<PasswordForm*>& first,
+ const std::vector<PasswordForm*>& second) {
+ if (first.size() != second.size())
+ return false;
+ SetOfForms expectations(first.begin(), first.end());
+ for (unsigned int i = 0; i < second.size(); ++i) {
+ const PasswordForm* actual = second[i];
+ bool found_match = false;
+ for (SetOfForms::iterator it = expectations.begin();
+ it != expectations.end(); ++it) {
+ const PasswordForm* expected = *it;
+ if (*expected == *actual) {
+ found_match = true;
+ expectations.erase(it);
+ break;
+ }
+ }
+ if (!found_match) {
+ LOG(ERROR) << "No match for:" << std::endl << *actual;
+ return false;
+ }
+ }
+ return true;
+}
+
+bool ContainsSamePasswordForms(
+ std::vector<webkit_glue::PasswordForm>& first,
+ std::vector<webkit_glue::PasswordForm>& second) {
+ std::vector<PasswordForm*> first_ptr;
+ for (unsigned int i = 0; i < first.size(); ++i) {
+ first_ptr.push_back(&first[i]);
+ }
+ std::vector<PasswordForm*> second_ptr;
+ for (unsigned int i = 0; i < second.size(); ++i) {
+ second_ptr.push_back(&second[i]);
+ }
+ return ContainsSamePasswordFormsPtr(first_ptr, second_ptr);
+}
diff --git a/chrome/browser/password_manager/password_form_data.h b/chrome/browser/password_manager/password_form_data.h
index 838c3ce..8b3d248 100644
--- a/chrome/browser/password_manager/password_form_data.h
+++ b/chrome/browser/password_manager/password_form_data.h
@@ -31,57 +31,20 @@ struct PasswordFormData {
webkit_glue::PasswordForm* CreatePasswordFormFromData(
const PasswordFormData& form_data);
-typedef std::set<webkit_glue::PasswordForm*> SetOfForms;
+// Checks whether two vectors of PasswordForms contain equivalent elements,
+// regardless of order.
+bool ContainsSamePasswordFormsPtr(
+ const std::vector<webkit_glue::PasswordForm*>& first,
+ const std::vector<webkit_glue::PasswordForm*>& second);
+
+bool ContainsSamePasswordForms(
+ std::vector<webkit_glue::PasswordForm>& first,
+ std::vector<webkit_glue::PasswordForm>& second);
// This gmock matcher is used to check that the |arg| contains exactly the same
// PasswordForms as |forms|, regardless of order.
MATCHER_P(ContainsAllPasswordForms, forms, "") {
- if (forms.size() != arg.size())
- return false;
- SetOfForms expectations(forms.begin(), forms.end());
- for (unsigned int i = 0; i < arg.size(); ++i) {
- webkit_glue::PasswordForm* actual = arg[i];
- bool found_match = false;
- for (SetOfForms::iterator it = expectations.begin();
- it != expectations.end(); ++it) {
- webkit_glue::PasswordForm* expected = *it;
- if (expected->scheme == actual->scheme &&
- expected->signon_realm == actual->signon_realm &&
- expected->origin == actual->origin &&
- expected->action == actual->action &&
- expected->submit_element == actual->submit_element &&
- expected->username_element == actual->username_element &&
- expected->password_element == actual->password_element &&
- expected->username_value == actual->username_value &&
- expected->password_value == actual->password_value &&
- expected->blacklisted_by_user == actual->blacklisted_by_user &&
- expected->preferred == actual->preferred &&
- expected->ssl_valid == actual->ssl_valid &&
- expected->date_created == actual->date_created) {
- found_match = true;
- expectations.erase(it);
- break;
- }
- }
- if (!found_match) {
- LOG(ERROR) << "No match for:" << std::endl
- << "scheme: " << actual->scheme << std::endl
- << "signon_realm: " << actual->signon_realm << std::endl
- << "origin: " << actual->origin << std::endl
- << "action: " << actual->action << std::endl
- << "submit_element: " << actual->submit_element << std::endl
- << "username_elem: " << actual->username_element << std::endl
- << "password_elem: " << actual->password_element << std::endl
- << "username_value: " << actual->username_value << std::endl
- << "password_value: " << actual->password_value << std::endl
- << "blacklisted: " << actual->blacklisted_by_user << std::endl
- << "preferred: " << actual->preferred << std::endl
- << "ssl_valid: " << actual->ssl_valid << std::endl
- << "date_created: " << actual->date_created.ToDoubleT();
- return false;
- }
- }
- return true;
+ return ContainsSamePasswordFormsPtr(forms, arg);
}
#endif // CHROME_BROWSER_PASSWORD_MANAGER_PASSWORD_FORM_DATA_H_
diff --git a/chrome/browser/password_manager/password_store.h b/chrome/browser/password_manager/password_store.h
index 6b6efa8..6b538d9 100644
--- a/chrome/browser/password_manager/password_store.h
+++ b/chrome/browser/password_manager/password_store.h
@@ -83,6 +83,7 @@ class PasswordStore : public base::RefCountedThreadSafe<PasswordStore> {
friend class browser_sync::PasswordDataTypeController;
friend class browser_sync::PasswordModelAssociator;
friend class browser_sync::PasswordModelWorker;
+ friend class LivePasswordsSyncTest;
virtual ~PasswordStore() {}
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 8707cdb..a9a8fc2 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -2636,6 +2636,7 @@
'app/chrome_dll_version.rc.version',
'browser/autofill/autofill_common_test.cc',
'browser/autofill/autofill_common_test.h',
+ 'browser/password_manager/password_form_data.cc',
'test/bookmark_load_observer.h',
'test/in_process_browser_test.cc',
'test/in_process_browser_test.h',
@@ -2646,20 +2647,25 @@
'test/live_sync/bookmark_model_verifier.h',
'test/live_sync/live_autofill_sync_test.h',
'test/live_sync/live_bookmarks_sync_test.h',
+ 'test/live_sync/live_passwords_sync_test.h',
'test/live_sync/live_preferences_sync_test.h',
'test/live_sync/live_sync_test.cc',
'test/live_sync/live_sync_test.h',
'test/live_sync/many_client_live_bookmarks_sync_test.cc',
+ 'test/live_sync/many_client_live_passwords_sync_test.cc',
'test/live_sync/many_client_live_preferences_sync_test.cc',
'test/live_sync/multiple_client_live_bookmarks_sync_test.cc',
+ 'test/live_sync/multiple_client_live_passwords_sync_test.cc',
'test/live_sync/multiple_client_live_preferences_sync_test.cc',
'test/live_sync/profile_sync_service_test_harness.cc',
'test/live_sync/profile_sync_service_test_harness.h',
'test/live_sync/single_client_live_bookmarks_sync_test.cc',
+ 'test/live_sync/single_client_live_passwords_sync_test.cc',
'test/live_sync/single_client_live_preferences_sync_test.cc',
'test/live_sync/two_client_live_autofill_sync_test.cc',
'test/live_sync/two_client_live_bookmarks_sync_test.cc',
'test/live_sync/two_client_live_preferences_sync_test.cc',
+ 'test/live_sync/two_client_live_passwords_sync_test.cc',
'test/test_notification_tracker.cc',
'test/test_notification_tracker.h',
'test/testing_browser_process.h',
diff --git a/chrome/test/live_sync/live_passwords_sync_test.h b/chrome/test/live_sync/live_passwords_sync_test.h
new file mode 100644
index 0000000..019b146
--- /dev/null
+++ b/chrome/test/live_sync/live_passwords_sync_test.h
@@ -0,0 +1,125 @@
+// 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_LIVE_PASSWORDS_SYNC_TEST_H_
+#define CHROME_TEST_LIVE_SYNC_LIVE_PASSWORDS_SYNC_TEST_H_
+#pragma once
+
+#include <set>
+
+#include "chrome/browser/profile.h"
+#include "chrome/browser/password_manager/password_store.h"
+#include "chrome/test/live_sync/live_sync_test.h"
+#include "chrome/test/ui_test_utils.h"
+#include "chrome/test/signaling_task.h"
+#include "webkit/glue/password_form.h"
+
+class LivePasswordsSyncTest : public LiveSyncTest {
+ public:
+ explicit LivePasswordsSyncTest(TestType test_type)
+ : LiveSyncTest(test_type) {}
+
+ virtual ~LivePasswordsSyncTest() {}
+
+ // Adds the login held in |form| to the password store |store|. Even though
+ // logins are normally added asynchronously, this method will block until the
+ // login is added.
+ void AddLogin(PasswordStore* store, const webkit_glue::PasswordForm& form) {
+ EXPECT_TRUE(store);
+
+ store->AddLogin(form);
+
+ base::WaitableEvent login_added(false, false);
+ store->ScheduleTask(new SignalingTask(&login_added));
+ login_added.Wait();
+ }
+
+ // Searches |store| for all logins matching |form|, the results are added to
+ // |matches|. Note that the caller is responsible for deleting the forms added
+ // to |matches|.
+ void GetLogins(PasswordStore* store,
+ const webkit_glue::PasswordForm& form,
+ std::vector<webkit_glue::PasswordForm>& matches) {
+ EXPECT_TRUE(store);
+
+ PasswordStoreConsumerHelper consumer(matches);
+ store->GetLogins(form, &consumer);
+ ui_test_utils::RunMessageLoop();
+ }
+
+ PasswordStore* GetPasswordStore(int index) {
+ return GetProfile(index)->GetPasswordStore(Profile::IMPLICIT_ACCESS);
+ }
+
+ PasswordStore* GetVerififerPasswordStore() {
+ return verifier()->GetPasswordStore(Profile::IMPLICIT_ACCESS);
+ }
+
+ private:
+ class PasswordStoreConsumerHelper : public PasswordStoreConsumer {
+ public:
+ explicit PasswordStoreConsumerHelper(
+ std::vector<webkit_glue::PasswordForm>& result)
+ : PasswordStoreConsumer(), result_(result) {}
+
+ virtual void OnPasswordStoreRequestDone(
+ int handle, const std::vector<webkit_glue::PasswordForm*>& result) {
+ result_.clear();
+ for (std::vector<webkit_glue::PasswordForm*>::const_iterator it =
+ result.begin(); it != result.end(); ++it) {
+ // Make a copy of the form since it gets deallocated after the caller of
+ // this method returns.
+ result_.push_back(**it);
+ }
+ MessageLoopForUI::current()->Quit();
+ }
+
+ private:
+ std::vector<webkit_glue::PasswordForm>& result_;
+
+ DISALLOW_COPY_AND_ASSIGN(PasswordStoreConsumerHelper);
+ };
+
+ DISALLOW_COPY_AND_ASSIGN(LivePasswordsSyncTest);
+};
+
+class SingleClientLivePasswordsSyncTest : public LivePasswordsSyncTest {
+ public:
+ SingleClientLivePasswordsSyncTest()
+ : LivePasswordsSyncTest(SINGLE_CLIENT) {}
+ virtual ~SingleClientLivePasswordsSyncTest() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SingleClientLivePasswordsSyncTest);
+};
+
+class TwoClientLivePasswordsSyncTest : public LivePasswordsSyncTest {
+ public:
+ TwoClientLivePasswordsSyncTest() : LivePasswordsSyncTest(TWO_CLIENT) {}
+ virtual ~TwoClientLivePasswordsSyncTest() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TwoClientLivePasswordsSyncTest);
+};
+
+class MultipleClientLivePasswordsSyncTest : public LivePasswordsSyncTest {
+ public:
+ MultipleClientLivePasswordsSyncTest()
+ : LivePasswordsSyncTest(MULTIPLE_CLIENT) {}
+ virtual ~MultipleClientLivePasswordsSyncTest() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MultipleClientLivePasswordsSyncTest);
+};
+
+class ManyClientLivePasswordsSyncTest : public LivePasswordsSyncTest {
+ public:
+ ManyClientLivePasswordsSyncTest() : LivePasswordsSyncTest(MANY_CLIENT) {}
+ virtual ~ManyClientLivePasswordsSyncTest() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ManyClientLivePasswordsSyncTest);
+};
+
+#endif // CHROME_TEST_LIVE_SYNC_LIVE_PASSWORDS_SYNC_TEST_H_
diff --git a/chrome/test/live_sync/live_sync_test.cc b/chrome/test/live_sync/live_sync_test.cc
index ba55dd4..6fd16cb 100644
--- a/chrome/test/live_sync/live_sync_test.cc
+++ b/chrome/test/live_sync/live_sync_test.cc
@@ -118,6 +118,11 @@ void LiveSyncTest::SetUp() {
cl->AppendSwitch(switches::kSyncUseSslTcp);
}
+ // TODO(sync): Remove this once passwords sync is enabled by default.
+ if (!cl->HasSwitch(switches::kEnableSyncPasswords)) {
+ cl->AppendSwitch(switches::kEnableSyncPasswords);
+ }
+
// Mock the Mac Keychain service. The real Keychain can block on user input.
#if defined(OS_MACOSX)
Encryptor::UseMockKeychain(true);
diff --git a/chrome/test/live_sync/many_client_live_passwords_sync_test.cc b/chrome/test/live_sync/many_client_live_passwords_sync_test.cc
new file mode 100644
index 0000000..b279883
--- /dev/null
+++ b/chrome/test/live_sync/many_client_live_passwords_sync_test.cc
@@ -0,0 +1,33 @@
+// 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 "chrome/browser/password_manager/password_form_data.h"
+#include "chrome/test/live_sync/live_passwords_sync_test.h"
+
+using webkit_glue::PasswordForm;
+
+IN_PROC_BROWSER_TEST_F(ManyClientLivePasswordsSyncTest, Sanity) {
+ ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
+
+ PasswordForm form;
+ form.origin = GURL("http://www.google.com/");
+ form.username_value = ASCIIToUTF16("username");
+ form.password_value = ASCIIToUTF16("password");
+
+ AddLogin(GetVerififerPasswordStore(), form);
+ AddLogin(GetPasswordStore(0), form);
+
+ EXPECT_TRUE(GetClient(0)->AwaitGroupSyncCycleCompletion(clients()));
+
+ std::vector<PasswordForm> expected;
+ GetLogins(GetVerififerPasswordStore(), form, expected);
+ EXPECT_EQ(1U, expected.size());
+
+ for (int i = 0; i < num_clients(); ++i) {
+ std::vector<PasswordForm> actual;
+ GetLogins(GetPasswordStore(i), form, actual);
+
+ EXPECT_TRUE(ContainsSamePasswordForms(expected, actual));
+ }
+}
diff --git a/chrome/test/live_sync/multiple_client_live_passwords_sync_test.cc b/chrome/test/live_sync/multiple_client_live_passwords_sync_test.cc
new file mode 100644
index 0000000..c277446
--- /dev/null
+++ b/chrome/test/live_sync/multiple_client_live_passwords_sync_test.cc
@@ -0,0 +1,36 @@
+// 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/stringprintf.h"
+#include "chrome/browser/password_manager/password_form_data.h"
+#include "chrome/test/live_sync/live_passwords_sync_test.h"
+
+using webkit_glue::PasswordForm;
+
+IN_PROC_BROWSER_TEST_F(MultipleClientLivePasswordsSyncTest, Sanity) {
+ ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
+
+ for (int i = 0; i < num_clients(); ++i) {
+ PasswordForm form;
+ form.origin = GURL(StringPrintf("http://www.google.com/%d", i));
+ form.username_value = ASCIIToUTF16(StringPrintf("username%d", i));
+ form.password_value = ASCIIToUTF16(StringPrintf("password%d", i));
+
+ AddLogin(GetPasswordStore(i), form);
+ }
+
+ EXPECT_TRUE(ProfileSyncServiceTestHarness::AwaitQuiescence(clients()));
+
+ PasswordForm form; // Don't set any fields, so that all logins match.
+ std::vector<PasswordForm> expected;
+ GetLogins(GetPasswordStore(0), form, expected);
+ EXPECT_EQ((size_t) num_clients(), expected.size());
+
+ for (int i = 1; i < num_clients(); ++i) {
+ std::vector<PasswordForm> actual;
+ GetLogins(GetPasswordStore(i), form, actual);
+
+ EXPECT_TRUE(ContainsSamePasswordForms(expected, actual));
+ }
+}
diff --git a/chrome/test/live_sync/single_client_live_passwords_sync_test.cc b/chrome/test/live_sync/single_client_live_passwords_sync_test.cc
new file mode 100644
index 0000000..ea5b183
--- /dev/null
+++ b/chrome/test/live_sync/single_client_live_passwords_sync_test.cc
@@ -0,0 +1,31 @@
+// 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 "chrome/browser/password_manager/password_form_data.h"
+#include "chrome/test/live_sync/live_passwords_sync_test.h"
+
+using webkit_glue::PasswordForm;
+
+IN_PROC_BROWSER_TEST_F(SingleClientLivePasswordsSyncTest, Sanity) {
+ ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
+
+ PasswordForm form;
+ form.origin = GURL("http://www.google.com/");
+ form.username_value = ASCIIToUTF16("username");
+ form.password_value = ASCIIToUTF16("password");
+
+ AddLogin(GetVerififerPasswordStore(), form);
+ AddLogin(GetPasswordStore(0), form);
+
+ EXPECT_TRUE(GetClient(0)->AwaitSyncCycleCompletion(
+ "Waiting for passwords change."));
+
+ std::vector<PasswordForm> expected;
+ GetLogins(GetVerififerPasswordStore(), form, expected);
+ EXPECT_EQ(1U, expected.size());
+
+ std::vector<PasswordForm> actual;
+ GetLogins(GetPasswordStore(0), form, actual);
+ EXPECT_TRUE(ContainsSamePasswordForms(expected, actual));
+}
diff --git a/chrome/test/live_sync/two_client_live_passwords_sync_test.cc b/chrome/test/live_sync/two_client_live_passwords_sync_test.cc
new file mode 100644
index 0000000..6114bdd
--- /dev/null
+++ b/chrome/test/live_sync/two_client_live_passwords_sync_test.cc
@@ -0,0 +1,65 @@
+// 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 "chrome/browser/password_manager/password_form_data.h"
+#include "chrome/test/live_sync/live_passwords_sync_test.h"
+
+using webkit_glue::PasswordForm;
+
+IN_PROC_BROWSER_TEST_F(TwoClientLivePasswordsSyncTest, Add) {
+ ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
+
+ PasswordForm form;
+ form.origin = GURL("http://www.google.com/");
+ form.username_value = ASCIIToUTF16("username");
+ form.password_value = ASCIIToUTF16("password");
+
+ AddLogin(GetVerififerPasswordStore(), form);
+ AddLogin(GetPasswordStore(0), form);
+
+ EXPECT_TRUE(GetClient(0)->AwaitMutualSyncCycleCompletion(GetClient(1)));
+
+ std::vector<PasswordForm> expected;
+ GetLogins(GetVerififerPasswordStore(), form, expected);
+ EXPECT_EQ(1U, expected.size());
+
+ std::vector<PasswordForm> actual_zero;
+ GetLogins(GetPasswordStore(0), form, actual_zero);
+ EXPECT_TRUE(ContainsSamePasswordForms(expected, actual_zero));
+
+ std::vector<PasswordForm> actual_one;
+ GetLogins(GetPasswordStore(1), form, actual_one);
+ EXPECT_TRUE(ContainsSamePasswordForms(expected, actual_one));
+}
+
+IN_PROC_BROWSER_TEST_F(TwoClientLivePasswordsSyncTest, Race) {
+ ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
+
+ PasswordForm form;
+ form.origin = GURL("http://www.google.com/");
+
+ PasswordForm form_zero;
+ form_zero.origin = GURL("http://www.google.com/");
+ form_zero.username_value = ASCIIToUTF16("username");
+ form_zero.password_value = ASCIIToUTF16("zero");
+ AddLogin(GetPasswordStore(0), form_zero);
+
+ PasswordForm form_one;
+ form_one.origin = GURL("http://www.google.com/");
+ form_one.username_value = ASCIIToUTF16("username");
+ form_one.password_value = ASCIIToUTF16("one");
+ AddLogin(GetPasswordStore(1), form_one);
+
+ EXPECT_TRUE(ProfileSyncServiceTestHarness::AwaitQuiescence(clients()));
+
+ std::vector<PasswordForm> actual_zero;
+ GetLogins(GetPasswordStore(0), form, actual_zero);
+ EXPECT_EQ(1U, actual_zero.size());
+
+ std::vector<PasswordForm> actual_one;
+ GetLogins(GetPasswordStore(1), form, actual_one);
+ EXPECT_EQ(1U, actual_one.size());
+
+ EXPECT_TRUE(ContainsSamePasswordForms(actual_zero, actual_one));
+}