password_store_default_unittest.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "base/basictypes.h" 6#include "base/bind.h" 7#include "base/bind_helpers.h" 8#include "base/files/scoped_temp_dir.h" 9#include "base/prefs/pref_service.h" 10#include "base/stl_util.h" 11#include "base/strings/string_util.h" 12#include "base/strings/utf_string_conversions.h" 13#include "base/synchronization/waitable_event.h" 14#include "base/time/time.h" 15#include "components/password_manager/core/browser/password_form_data.h" 16#include "components/password_manager/core/browser/password_store_change.h" 17#include "components/password_manager/core/browser/password_store_consumer.h" 18#include "components/password_manager/core/browser/password_store_default.h" 19#include "testing/gmock/include/gmock/gmock.h" 20#include "testing/gtest/include/gtest/gtest.h" 21 22using autofill::PasswordForm; 23using base::WaitableEvent; 24using testing::_; 25using testing::DoAll; 26using testing::ElementsAreArray; 27using testing::Pointee; 28using testing::Property; 29using testing::WithArg; 30 31namespace { 32 33class MockPasswordStoreConsumer : public PasswordStoreConsumer { 34 public: 35 MOCK_METHOD1(OnGetPasswordStoreResults, 36 void(const std::vector<PasswordForm*>&)); 37}; 38 39class MockPasswordStoreObserver : public PasswordStore::Observer { 40 public: 41 MOCK_METHOD1(OnLoginsChanged, 42 void(const PasswordStoreChangeList& changes)); 43}; 44 45} // anonymous namespace 46 47class PasswordStoreDefaultTest : public testing::Test { 48 protected: 49 virtual void SetUp() OVERRIDE { 50 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 51 login_db_.reset(new LoginDatabase()); 52 ASSERT_TRUE(login_db_->Init(temp_dir_.path().Append( 53 FILE_PATH_LITERAL("login_test")))); 54 } 55 56 virtual void TearDown() OVERRIDE { 57 ASSERT_TRUE(temp_dir_.Delete()); 58 } 59 60 base::MessageLoopForUI message_loop_; 61 scoped_ptr<LoginDatabase> login_db_; 62 base::ScopedTempDir temp_dir_; 63}; 64 65ACTION(STLDeleteElements0) { 66 STLDeleteContainerPointers(arg0.begin(), arg0.end()); 67} 68 69TEST_F(PasswordStoreDefaultTest, NonASCIIData) { 70 scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault( 71 base::MessageLoopProxy::current(), 72 base::MessageLoopProxy::current(), 73 login_db_.release())); 74 store->Init(syncer::SyncableService::StartSyncFlare()); 75 76 // Some non-ASCII password form data. 77 static const PasswordFormData form_data[] = { 78 { PasswordForm::SCHEME_HTML, 79 "http://foo.example.com", 80 "http://foo.example.com/origin", 81 "http://foo.example.com/action", 82 L"มีสีสัน", 83 L"お元気ですか?", 84 L"盆栽", 85 L"أحب كرة", 86 L"£éä국수çà", 87 true, false, 1 }, 88 }; 89 90 // Build the expected forms vector and add the forms to the store. 91 std::vector<PasswordForm*> expected_forms; 92 for (unsigned int i = 0; i < ARRAYSIZE_UNSAFE(form_data); ++i) { 93 PasswordForm* form = CreatePasswordFormFromData(form_data[i]); 94 expected_forms.push_back(form); 95 store->AddLogin(*form); 96 } 97 98 base::MessageLoop::current()->RunUntilIdle(); 99 100 MockPasswordStoreConsumer consumer; 101 102 // We expect to get the same data back, even though it's not all ASCII. 103 EXPECT_CALL(consumer, 104 OnGetPasswordStoreResults(ContainsAllPasswordForms(expected_forms))) 105 .WillOnce(WithArg<0>(STLDeleteElements0())); 106 store->GetAutofillableLogins(&consumer); 107 108 base::MessageLoop::current()->RunUntilIdle(); 109 110 STLDeleteElements(&expected_forms); 111 store->Shutdown(); 112 base::MessageLoop::current()->RunUntilIdle(); 113} 114 115TEST_F(PasswordStoreDefaultTest, Notifications) { 116 scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault( 117 base::MessageLoopProxy::current(), 118 base::MessageLoopProxy::current(), 119 login_db_.release())); 120 store->Init(syncer::SyncableService::StartSyncFlare()); 121 122 PasswordFormData form_data = 123 { PasswordForm::SCHEME_HTML, 124 "http://bar.example.com", 125 "http://bar.example.com/origin", 126 "http://bar.example.com/action", 127 L"submit_element", 128 L"username_element", 129 L"password_element", 130 L"username_value", 131 L"password_value", 132 true, false, 1 }; 133 scoped_ptr<PasswordForm> form(CreatePasswordFormFromData(form_data)); 134 135 MockPasswordStoreObserver observer; 136 store->AddObserver(&observer); 137 138 const PasswordStoreChange expected_add_changes[] = { 139 PasswordStoreChange(PasswordStoreChange::ADD, *form), 140 }; 141 142 EXPECT_CALL( 143 observer, 144 OnLoginsChanged(ElementsAreArray(expected_add_changes))); 145 146 // Adding a login should trigger a notification. 147 store->AddLogin(*form); 148 base::MessageLoop::current()->RunUntilIdle(); 149 150 // Change the password. 151 form->password_value = base::ASCIIToUTF16("a different password"); 152 153 const PasswordStoreChange expected_update_changes[] = { 154 PasswordStoreChange(PasswordStoreChange::UPDATE, *form), 155 }; 156 157 EXPECT_CALL( 158 observer, 159 OnLoginsChanged(ElementsAreArray(expected_update_changes))); 160 161 // Updating the login with the new password should trigger a notification. 162 store->UpdateLogin(*form); 163 base::MessageLoop::current()->RunUntilIdle(); 164 165 const PasswordStoreChange expected_delete_changes[] = { 166 PasswordStoreChange(PasswordStoreChange::REMOVE, *form), 167 }; 168 169 EXPECT_CALL( 170 observer, 171 OnLoginsChanged(ElementsAreArray(expected_delete_changes))); 172 173 // Deleting the login should trigger a notification. 174 store->RemoveLogin(*form); 175 base::MessageLoop::current()->RunUntilIdle(); 176 177 store->RemoveObserver(&observer); 178 store->Shutdown(); 179 base::MessageLoop::current()->RunUntilIdle(); 180} 181