| Index: components/password_manager/core/browser/password_store_default_unittest.cc
|
| diff --git a/components/password_manager/core/browser/password_store_default_unittest.cc b/components/password_manager/core/browser/password_store_default_unittest.cc
|
| index c2b0bbe158436a3336f4c204a74c089b194f0922..d3fd824645f7ad88bbe370222df20854fffe374b 100644
|
| --- a/components/password_manager/core/browser/password_store_default_unittest.cc
|
| +++ b/components/password_manager/core/browser/password_store_default_unittest.cc
|
| @@ -5,12 +5,14 @@
|
| #include "base/basictypes.h"
|
| #include "base/bind.h"
|
| #include "base/bind_helpers.h"
|
| +#include "base/files/file_util.h"
|
| #include "base/files/scoped_temp_dir.h"
|
| #include "base/prefs/pref_service.h"
|
| #include "base/stl_util.h"
|
| #include "base/strings/string_util.h"
|
| #include "base/strings/utf_string_conversions.h"
|
| #include "base/time/time.h"
|
| +#include "components/password_manager/core/browser/login_database.h"
|
| #include "components/password_manager/core/browser/password_form_data.h"
|
| #include "components/password_manager/core/browser/password_store_change.h"
|
| #include "components/password_manager/core/browser/password_store_consumer.h"
|
| @@ -39,21 +41,37 @@ class MockPasswordStoreObserver : public PasswordStore::Observer {
|
| void(const PasswordStoreChangeList& changes));
|
| };
|
|
|
| +PasswordFormData CreateTestPasswordFormData() {
|
| + return (PasswordFormData){
|
| + PasswordForm::SCHEME_HTML,
|
| + "http://bar.example.com",
|
| + "http://bar.example.com/origin",
|
| + "http://bar.example.com/action",
|
| + L"submit_element",
|
| + L"username_element",
|
| + L"password_element",
|
| + L"username_value",
|
| + L"password_value",
|
| + true,
|
| + false,
|
| + 1};
|
| +}
|
| +
|
| } // anonymous namespace
|
|
|
| class PasswordStoreDefaultTest : public testing::Test {
|
| protected:
|
| void SetUp() override {
|
| ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
|
| - login_db_.reset(new LoginDatabase());
|
| - ASSERT_TRUE(login_db_->Init(temp_dir_.path().Append(
|
| - FILE_PATH_LITERAL("login_test"))));
|
| }
|
|
|
| void TearDown() override { ASSERT_TRUE(temp_dir_.Delete()); }
|
|
|
| + base::FilePath test_login_db_file_path() const {
|
| + return temp_dir_.path().Append(FILE_PATH_LITERAL("login_test"));
|
| + }
|
| +
|
| base::MessageLoopForUI message_loop_;
|
| - scoped_ptr<LoginDatabase> login_db_;
|
| base::ScopedTempDir temp_dir_;
|
| };
|
|
|
| @@ -65,7 +83,7 @@ TEST_F(PasswordStoreDefaultTest, NonASCIIData) {
|
| scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault(
|
| base::MessageLoopProxy::current(),
|
| base::MessageLoopProxy::current(),
|
| - login_db_.release()));
|
| + test_login_db_file_path()));
|
| store->Init(syncer::SyncableService::StartSyncFlare());
|
|
|
| // Some non-ASCII password form data.
|
| @@ -111,21 +129,11 @@ TEST_F(PasswordStoreDefaultTest, Notifications) {
|
| scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault(
|
| base::MessageLoopProxy::current(),
|
| base::MessageLoopProxy::current(),
|
| - login_db_.release()));
|
| + test_login_db_file_path()));
|
| store->Init(syncer::SyncableService::StartSyncFlare());
|
|
|
| - PasswordFormData form_data =
|
| - { PasswordForm::SCHEME_HTML,
|
| - "http://bar.example.com",
|
| - "http://bar.example.com/origin",
|
| - "http://bar.example.com/action",
|
| - L"submit_element",
|
| - L"username_element",
|
| - L"password_element",
|
| - L"username_value",
|
| - L"password_value",
|
| - true, false, 1 };
|
| - scoped_ptr<PasswordForm> form(CreatePasswordFormFromData(form_data));
|
| + scoped_ptr<PasswordForm> form(
|
| + CreatePasswordFormFromData(CreateTestPasswordFormData()));
|
|
|
| MockPasswordStoreObserver observer;
|
| store->AddObserver(&observer);
|
| @@ -174,4 +182,70 @@ TEST_F(PasswordStoreDefaultTest, Notifications) {
|
| base::MessageLoop::current()->RunUntilIdle();
|
| }
|
|
|
| +// Verify that operations on a PasswordStore with a bad database cause no
|
| +// explosions, but fail without side effect, return no data and trigger no
|
| +// notifications.
|
| +TEST_F(PasswordStoreDefaultTest, OperationsOnABadDatabaseSilentlyFail) {
|
| + scoped_refptr<PasswordStoreDefault> bad_store(new PasswordStoreDefault(
|
| + base::MessageLoopProxy::current(), base::MessageLoopProxy::current(),
|
| + test_login_db_file_path()));
|
| +
|
| + LoginDatabase::set_simulate_init_failure_for_testing(true);
|
| + bad_store->Init(syncer::SyncableService::StartSyncFlare());
|
| + base::MessageLoop::current()->RunUntilIdle();
|
| + LoginDatabase::set_simulate_init_failure_for_testing(false);
|
| + ASSERT_EQ(nullptr, bad_store->login_db());
|
| +
|
| + testing::StrictMock<MockPasswordStoreObserver> mock_observer;
|
| + bad_store->AddObserver(&mock_observer);
|
| +
|
| + // Add a new autofillable login + a blacklisted login.
|
| + scoped_ptr<PasswordForm> form(
|
| + CreatePasswordFormFromData(CreateTestPasswordFormData()));
|
| + scoped_ptr<PasswordForm> blacklisted_form(new PasswordForm(*form));
|
| + blacklisted_form->signon_realm = "http://foo.example.com";
|
| + blacklisted_form->origin = GURL("http://foo.example.com/origin");
|
| + blacklisted_form->action = GURL("http://foo.example.com/action");
|
| + blacklisted_form->blacklisted_by_user = true;
|
| + bad_store->AddLogin(*form);
|
| + bad_store->AddLogin(*blacklisted_form);
|
| + base::MessageLoop::current()->RunUntilIdle();
|
| +
|
| + // Get all logins; autofillable logins; blacklisted logins.
|
| + testing::StrictMock<MockPasswordStoreConsumer> mock_consumer;
|
| + EXPECT_CALL(mock_consumer, OnGetPasswordStoreResults(testing::ElementsAre()));
|
| + bad_store->GetLogins(*form, PasswordStore::DISALLOW_PROMPT, &mock_consumer);
|
| + base::MessageLoop::current()->RunUntilIdle();
|
| + testing::Mock::VerifyAndClearExpectations(&mock_consumer);
|
| + EXPECT_CALL(mock_consumer, OnGetPasswordStoreResults(testing::ElementsAre()));
|
| + bad_store->GetAutofillableLogins(&mock_consumer);
|
| + base::MessageLoop::current()->RunUntilIdle();
|
| + testing::Mock::VerifyAndClearExpectations(&mock_consumer);
|
| + EXPECT_CALL(mock_consumer, OnGetPasswordStoreResults(testing::ElementsAre()));
|
| + bad_store->GetBlacklistLogins(&mock_consumer);
|
| + base::MessageLoop::current()->RunUntilIdle();
|
| +
|
| + // Report metrics.
|
| + bad_store->ReportMetrics("Test Username", true);
|
| + base::MessageLoop::current()->RunUntilIdle();
|
| +
|
| + // Change the login.
|
| + form->password_value = base::ASCIIToUTF16("a different password");
|
| + bad_store->UpdateLogin(*form);
|
| + base::MessageLoop::current()->RunUntilIdle();
|
| +
|
| + // Delete one login; a range of logins.
|
| + bad_store->RemoveLogin(*form);
|
| + base::MessageLoop::current()->RunUntilIdle();
|
| + bad_store->RemoveLoginsCreatedBetween(base::Time(), base::Time::Max());
|
| + base::MessageLoop::current()->RunUntilIdle();
|
| + bad_store->RemoveLoginsSyncedBetween(base::Time(), base::Time::Max());
|
| + base::MessageLoop::current()->RunUntilIdle();
|
| +
|
| + // Ensure no notifications and no explosions during shutdown either.
|
| + bad_store->RemoveObserver(&mock_observer);
|
| + bad_store->Shutdown();
|
| + base::MessageLoop::current()->RunUntilIdle();
|
| +}
|
| +
|
| } // namespace password_manager
|
|
|