Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(27)

Side by Side Diff: chrome/browser/password_manager/password_syncable_service_unittest.cc

Issue 131003006: Password sync refactoring: implemented |MergeDataAndStartSyncing| and unit_tests (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Merge with trunk Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2014 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 "chrome/browser/password_manager/password_syncable_service.h"
6
7 #include <algorithm>
8 #include <string>
9 #include <vector>
10
11 #include "base/basictypes.h"
12 #include "base/location.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "chrome/browser/password_manager/mock_password_store.h"
16 #include "sync/api/sync_change_processor.h"
17 #include "sync/api/sync_error.h"
18 #include "sync/api/sync_error_factory.h"
19 #include "testing/gmock/include/gmock/gmock.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21
22 using syncer::SyncChange;
23 using syncer::SyncData;
24 using syncer::SyncDataList;
25 using syncer::SyncError;
26 using testing::Invoke;
27 using testing::Return;
28 using testing::SetArgPointee;
29 using testing::_;
30
31 namespace {
32
33 typedef std::vector<SyncChange> SyncChangeList;
34
35 const sync_pb::PasswordSpecificsData& GetPasswordSpecifics(
36 const syncer::SyncData& sync_change) {
37 const sync_pb::EntitySpecifics& specifics = sync_change.GetSpecifics();
38 return specifics.password().client_only_encrypted_data();
39 }
40
41 void PasswordsEqual(const sync_pb::PasswordSpecificsData& expected_password,
42 const sync_pb::PasswordSpecificsData& actual_password) {
43 EXPECT_EQ(expected_password.scheme(), actual_password.scheme());
44 EXPECT_EQ(expected_password.signon_realm(), actual_password.signon_realm());
45 EXPECT_EQ(expected_password.origin(), actual_password.origin());
46 EXPECT_EQ(expected_password.action(), actual_password.action());
47 EXPECT_EQ(expected_password.username_element(),
48 actual_password.username_element());
49 EXPECT_EQ(expected_password.password_element(),
50 actual_password.password_element());
51 EXPECT_EQ(expected_password.username_value(),
52 actual_password.username_value());
53 EXPECT_EQ(expected_password.password_value(),
54 actual_password.password_value());
55 EXPECT_EQ(expected_password.ssl_valid(), actual_password.ssl_valid());
56 EXPECT_EQ(expected_password.preferred(), actual_password.preferred());
57 EXPECT_EQ(expected_password.date_created(), actual_password.date_created());
58 EXPECT_EQ(expected_password.blacklisted(), actual_password.blacklisted());
59 }
60
61 // Creates a sync data consisting of password specifics. The sign on realm is
62 // set to |signon_realm|.
63 SyncData CreateSyncData(const std::string& signon_realm) {
64 sync_pb::EntitySpecifics password_data;
65 sync_pb::PasswordSpecificsData* password_specifics =
66 password_data.mutable_password()->mutable_client_only_encrypted_data();
67 password_specifics->set_signon_realm(signon_realm);
68
69 std::string tag = MakePasswordSyncTag(*password_specifics);
70 return syncer::SyncData::CreateLocalData(tag, tag, password_data);
71 }
72
73 SyncChange CreateSyncChange(const autofill::PasswordForm& password,
74 SyncChange::SyncChangeType type) {
75 SyncData data = SyncDataFromPassword(password);
76 return SyncChange(FROM_HERE, type, data);
77 }
78
79 // A testable implementation of the |PasswordSyncableService| that mocks
80 // out all interaction with the password database.
81 class MockPasswordSyncableService : public PasswordSyncableService {
82 public:
83 explicit MockPasswordSyncableService(PasswordStore* password_store)
84 : PasswordSyncableService(password_store) {}
85 virtual ~MockPasswordSyncableService() {}
86
87 MOCK_METHOD1(NotifyPasswordStoreOfLoginChanges,
88 void (const PasswordStoreChangeList&));
89 };
90
91 // Class to verify the arguments passed to |PasswordStore|.
92 class PasswordStoreDataVerifier {
93 public:
94 PasswordStoreDataVerifier() {}
95 ~PasswordStoreDataVerifier() {
96 EXPECT_TRUE(expected_db_add_changes_.empty());
97 EXPECT_TRUE(expected_db_update_changes_.empty());
98 }
99
100 class TestSyncChangeProcessor;
101
102 // Sets expected changes to the password database.
103 void SetExpectedDBChanges(
104 const SyncDataList& add_forms,
105 const std::vector<autofill::PasswordForm*>& update_forms,
106 MockPasswordStore* password_store);
107 // Sets expected changes to TestSyncChangeProcessor.
108 void SetExpectedSyncChanges(SyncChangeList list);
109
110 private:
111 // Checks that |change_list| matches |expected_sync_change_list_|.
112 SyncError TestSyncChanges(const SyncChangeList& change_list);
113
114 // Verifies that the |password| is present in the |expected_db_add_changes_|
115 // list. If found |password| would be removed from
116 // |expected_db_add_changes_| list.
117 PasswordStoreChangeList VerifyAdd(const autofill::PasswordForm& password) {
118 return VerifyChange(PasswordStoreChange::ADD, password,
119 &expected_db_add_changes_);
120 }
121
122 // Verifies that the |password| is present in the
123 // |expected_db_update_changes_| list.
124 PasswordStoreChangeList VerifyUpdate(const autofill::PasswordForm& password) {
125 return VerifyChange(PasswordStoreChange::UPDATE, password,
126 &expected_db_update_changes_);
127 }
128
129 static PasswordStoreChangeList VerifyChange(
130 PasswordStoreChange::Type type,
131 const autofill::PasswordForm& password,
132 std::vector<autofill::PasswordForm>* password_list);
133
134 std::vector<autofill::PasswordForm> expected_db_add_changes_;
135 std::vector<autofill::PasswordForm> expected_db_update_changes_;
136 SyncChangeList expected_sync_change_list_;
137
138 DISALLOW_COPY_AND_ASSIGN(PasswordStoreDataVerifier);
139 };
140
141 class PasswordStoreDataVerifier::TestSyncChangeProcessor
142 : public syncer::SyncChangeProcessor {
143 public:
144 explicit TestSyncChangeProcessor(PasswordStoreDataVerifier* verifier)
145 : verifier_(verifier) {
146 }
147 virtual ~TestSyncChangeProcessor() {}
148
149 virtual SyncError ProcessSyncChanges(const tracked_objects::Location&,
150 const SyncChangeList& list) OVERRIDE {
151 return verifier_->TestSyncChanges(list);
152 }
153
154 virtual SyncDataList GetAllSyncData(syncer::ModelType type) const OVERRIDE {
155 return SyncDataList();
156 }
157 private:
158 PasswordStoreDataVerifier* verifier_;
159
160 DISALLOW_COPY_AND_ASSIGN(TestSyncChangeProcessor);
161 };
162
163 void PasswordStoreDataVerifier::SetExpectedDBChanges(
164 const SyncDataList& add_forms,
165 const std::vector<autofill::PasswordForm*>& update_forms,
166 MockPasswordStore* password_store) {
167 DCHECK(expected_db_add_changes_.empty());
168 DCHECK(expected_db_update_changes_.empty());
169 DCHECK(password_store);
170
171 for (SyncDataList::const_iterator i = add_forms.begin();
172 i != add_forms.end(); ++i) {
173 autofill::PasswordForm form;
174 PasswordFromSpecifics(GetPasswordSpecifics(*i), &form);
175 expected_db_add_changes_.push_back(form);
176 }
177 if (expected_db_add_changes_.empty()) {
178 EXPECT_CALL(*password_store, AddLoginImpl(_)).Times(0);
179 } else {
180 EXPECT_CALL(*password_store, AddLoginImpl(_))
181 .Times(expected_db_add_changes_.size())
182 .WillRepeatedly(Invoke(this, &PasswordStoreDataVerifier::VerifyAdd));
183 }
184
185 for (std::vector<autofill::PasswordForm*>::const_iterator i =
186 update_forms.begin();
187 i != update_forms.end(); ++i) {
188 expected_db_update_changes_.push_back(**i);
189 }
190 if (expected_db_update_changes_.empty()) {
191 EXPECT_CALL(*password_store, UpdateLoginImpl(_)).Times(0);
192 } else {
193 EXPECT_CALL(*password_store, UpdateLoginImpl(_))
194 .Times(expected_db_update_changes_.size())
195 .WillRepeatedly(Invoke(this, &PasswordStoreDataVerifier::VerifyUpdate));
196 }
197 }
198
199 void PasswordStoreDataVerifier::SetExpectedSyncChanges(SyncChangeList list) {
200 expected_sync_change_list_.swap(list);
201 }
202
203 SyncError PasswordStoreDataVerifier::TestSyncChanges(
204 const SyncChangeList& change_list) {
205 for (SyncChangeList::const_iterator it = change_list.begin();
206 it != change_list.end(); ++it) {
207 const SyncChange& data = *it;
208 const sync_pb::PasswordSpecificsData& actual_password(
209 GetPasswordSpecifics(data.sync_data()));
210 std::string actual_tag = MakePasswordSyncTag(actual_password);
211
212 bool matched = false;
213 for (SyncChangeList::iterator expected_it =
214 expected_sync_change_list_.begin();
215 expected_it != expected_sync_change_list_.end();
216 ++expected_it) {
217 const sync_pb::PasswordSpecificsData& expected_password(
218 GetPasswordSpecifics(expected_it->sync_data()));
219 if (actual_tag == MakePasswordSyncTag(expected_password)) {
220 PasswordsEqual(expected_password, actual_password);
221 EXPECT_EQ(expected_it->change_type(), data.change_type());
222 matched = true;
223 break;
224 }
225 }
226 EXPECT_TRUE(matched) << actual_tag;
227 }
228 EXPECT_EQ(expected_sync_change_list_.size(), change_list.size());
229 return SyncError();
230 }
231
232 // static
233 PasswordStoreChangeList PasswordStoreDataVerifier::VerifyChange(
234 PasswordStoreChange::Type type,
235 const autofill::PasswordForm& password,
236 std::vector<autofill::PasswordForm>* password_list) {
237 std::vector<autofill::PasswordForm>::iterator it =
238 std::find(password_list->begin(), password_list->end(), password);
239 EXPECT_NE(password_list->end(), it);
240 password_list->erase(it);
241 return PasswordStoreChangeList(1, PasswordStoreChange(type, password));
242 }
243
244 class PasswordSyncableServiceTest : public testing::Test {
245 public:
246 PasswordSyncableServiceTest() {}
247 virtual ~PasswordSyncableServiceTest() {}
248
249 virtual void SetUp() OVERRIDE {
250 password_store_ = new MockPasswordStore;
251 service_.reset(new MockPasswordSyncableService(password_store_));
252 }
253
254 virtual void TearDown() OVERRIDE {
255 password_store_->Shutdown();
256 }
257
258 PasswordStoreDataVerifier* verifier() {
259 return &verifier_;
260 }
261
262 scoped_ptr<syncer::SyncChangeProcessor> ReleaseSyncChangeProcessor() {
263 return make_scoped_ptr<syncer::SyncChangeProcessor>(
264 new PasswordStoreDataVerifier::TestSyncChangeProcessor(verifier()));
265 }
266
267 // Sets the data that will be returned to the caller accessing password store.
268 void SetPasswordStoreData(const std::vector<autofill::PasswordForm*>& forms) {
269 EXPECT_CALL(*password_store_, FillAutofillableLogins(_))
270 .WillOnce(DoAll(SetArgPointee<0>(forms), Return(true)));
271 }
272
273 protected:
274 scoped_refptr<MockPasswordStore> password_store_;
275 scoped_ptr<MockPasswordSyncableService> service_;
276 PasswordStoreDataVerifier verifier_;
277 };
278
279
280 // Both sync and password db have data that are not present in the other.
281 TEST_F(PasswordSyncableServiceTest, AdditionsInBoth) {
282 autofill::PasswordForm* form1 = new autofill::PasswordForm;
283 form1->signon_realm = "abc";
284 std::vector<autofill::PasswordForm*> forms;
285 forms.push_back(form1);
286 SetPasswordStoreData(forms);
287
288 SyncData sync_data = CreateSyncData("def");
289 SyncDataList list;
290 list.push_back(sync_data);
291
292 verifier()->SetExpectedDBChanges(list,
293 std::vector<autofill::PasswordForm*>(),
294 password_store_);
295 verifier()->SetExpectedSyncChanges(
296 SyncChangeList(1, CreateSyncChange(*form1, SyncChange::ACTION_ADD)));
297 EXPECT_CALL(*service_, NotifyPasswordStoreOfLoginChanges(_));
298
299 service_->MergeDataAndStartSyncing(syncer::PASSWORDS,
300 list,
301 ReleaseSyncChangeProcessor(),
302 scoped_ptr<syncer::SyncErrorFactory>());
303 }
304
305 // Sync has data that is not present in the password db.
306 TEST_F(PasswordSyncableServiceTest, AdditionOnlyInSync) {
307 SetPasswordStoreData(std::vector<autofill::PasswordForm*>());
308
309 SyncData sync_data = CreateSyncData("def");
310 SyncDataList list;
311 list.push_back(sync_data);
312
313 verifier()->SetExpectedDBChanges(list,
314 std::vector<autofill::PasswordForm*>(),
315 password_store_);
316 verifier()->SetExpectedSyncChanges(SyncChangeList());
317 EXPECT_CALL(*service_, NotifyPasswordStoreOfLoginChanges(_));
318
319 service_->MergeDataAndStartSyncing(syncer::PASSWORDS,
320 list,
321 ReleaseSyncChangeProcessor(),
322 scoped_ptr<syncer::SyncErrorFactory>());
323 }
324
325 // Passwords db has data that is not present in sync.
326 TEST_F(PasswordSyncableServiceTest, AdditionOnlyInPasswordStore) {
327 autofill::PasswordForm* form1 = new autofill::PasswordForm;
328 form1->signon_realm = "abc";
329 std::vector<autofill::PasswordForm*> forms;
330 forms.push_back(form1);
331 SetPasswordStoreData(forms);
332
333 verifier()->SetExpectedDBChanges(SyncDataList(),
334 std::vector<autofill::PasswordForm*>(),
335 password_store_);
336 verifier()->SetExpectedSyncChanges(
337 SyncChangeList(1, CreateSyncChange(*form1, SyncChange::ACTION_ADD)));
338 EXPECT_CALL(*service_,
339 NotifyPasswordStoreOfLoginChanges(PasswordStoreChangeList()));
340
341 service_->MergeDataAndStartSyncing(syncer::PASSWORDS,
342 SyncDataList(),
343 ReleaseSyncChangeProcessor(),
344 scoped_ptr<syncer::SyncErrorFactory>());
345 }
346
347 // Both passwords db and sync contain the same data.
348 TEST_F(PasswordSyncableServiceTest, BothInSync) {
349 autofill::PasswordForm *form1 = new autofill::PasswordForm;
350 form1->signon_realm = "abc";
351 std::vector<autofill::PasswordForm*> forms;
352 forms.push_back(form1);
353 SetPasswordStoreData(forms);
354
355 verifier()->SetExpectedDBChanges(SyncDataList(),
356 std::vector<autofill::PasswordForm*>(),
357 password_store_);
358 verifier()->SetExpectedSyncChanges(SyncChangeList());
359 EXPECT_CALL(*service_,
360 NotifyPasswordStoreOfLoginChanges(PasswordStoreChangeList()));
361
362 service_->MergeDataAndStartSyncing(syncer::PASSWORDS,
363 SyncDataList(1, CreateSyncData("abc")),
364 ReleaseSyncChangeProcessor(),
365 scoped_ptr<syncer::SyncErrorFactory>());
366 }
367
368 // Both passwords db and sync have the same data but they need to be merged
369 // as some fields of the data differ.
370 TEST_F(PasswordSyncableServiceTest, Merge) {
371 autofill::PasswordForm *form1 = new autofill::PasswordForm;
372 form1->signon_realm = "abc";
373 form1->action = GURL("http://pie.com");
374 form1->date_created = base::Time::Now();
375 std::vector<autofill::PasswordForm*> forms;
376 forms.push_back(form1);
377 SetPasswordStoreData(forms);
378
379 verifier()->SetExpectedDBChanges(SyncDataList(),
380 forms,
381 password_store_);
382 verifier()->SetExpectedSyncChanges(
383 SyncChangeList(1, CreateSyncChange(*form1, SyncChange::ACTION_UPDATE)));
384
385 EXPECT_CALL(*service_, NotifyPasswordStoreOfLoginChanges(_));
386
387 service_->MergeDataAndStartSyncing(syncer::PASSWORDS,
388 SyncDataList(1, CreateSyncData("abc")),
389 ReleaseSyncChangeProcessor(),
390 scoped_ptr<syncer::SyncErrorFactory>());
391 }
392
393 // Initiate sync due to local DB changes.
394 TEST_F(PasswordSyncableServiceTest, PasswordStoreChanges) {
395 // Set the sync change processor first.
396 SetPasswordStoreData(std::vector<autofill::PasswordForm*>());
397 verifier()->SetExpectedSyncChanges(SyncChangeList());
398 EXPECT_CALL(*service_,
399 NotifyPasswordStoreOfLoginChanges(PasswordStoreChangeList()));
400 service_->MergeDataAndStartSyncing(syncer::PASSWORDS,
401 SyncDataList(),
402 ReleaseSyncChangeProcessor(),
403 scoped_ptr<syncer::SyncErrorFactory>());
404
405 autofill::PasswordForm form1;
406 form1.signon_realm = "abc";
407 autofill::PasswordForm form2;
408 form2.signon_realm = "def";
409 autofill::PasswordForm form3;
410 form3.signon_realm = "xyz";
411
412 SyncChangeList sync_list;
413 sync_list.push_back(CreateSyncChange(form1, SyncChange::ACTION_ADD));
414 sync_list.push_back(CreateSyncChange(form2, SyncChange::ACTION_UPDATE));
415 sync_list.push_back(CreateSyncChange(form3, SyncChange::ACTION_DELETE));
416
417 verifier()->SetExpectedDBChanges(SyncDataList(),
418 std::vector<autofill::PasswordForm*>(),
419 password_store_);
420 verifier()->SetExpectedSyncChanges(sync_list);
421
422 PasswordStoreChangeList list;
423 list.push_back(PasswordStoreChange(PasswordStoreChange::ADD, form1));
424 list.push_back(PasswordStoreChange(PasswordStoreChange::UPDATE, form2));
425 list.push_back(PasswordStoreChange(PasswordStoreChange::REMOVE, form3));
426 service_->ActOnPasswordStoreChanges(list);
427 }
428
429 } // namespace
OLDNEW
« no previous file with comments | « chrome/browser/password_manager/password_syncable_service.cc ('k') | chrome/chrome_tests_unit.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698