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

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

Issue 27233003: [Sync] Implementation of model association for passwords using sync API (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: For review.\ Created 7 years, 2 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 (c) 2013 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 <string>
6 #include <vector>
7
8 #include "base/location.h"
9 #include "base/memory/ref_counted.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/memory/scoped_vector.h"
12 #include "chrome/browser/password_manager/mock_password_store.h"
13 #include "chrome/browser/password_manager/password_store_factory.h"
14 #include "chrome/browser/password_manager/password_syncable_service.h"
15 #include "chrome/browser/profiles/profile.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 "sync/protocol/password_specifics.pb.h"
20 #include "sync/protocol/sync.pb.h"
21 #include "testing/gmock/include/gmock/gmock.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23
24 using syncer::SyncChange;
25 using syncer::SyncData;
26 using syncer::SyncDataList;
27 using syncer::SyncError;
28 using testing::Invoke;
29 using testing::Return;
30 using testing::SetArgumentPointee;
31
32 typedef std::vector<SyncChange> SyncChangeList;
Nicolas Zea 2013/10/21 23:55:14 put this and the rest of the file in an anonymous
lipalani1 2013/10/24 00:13:58 Done.
33
34 // This class will be instantiated by the tests rather than the
35 // |PasswordSyncableService| as this class will mock away any calls
36 // that touch the password db.
37 class MockPasswordSyncableService : public PasswordSyncableService {
Nicolas Zea 2013/10/21 23:55:14 It's generally cleaner to use fakes when overridin
lipalani1 2013/10/24 00:13:58 I tried this approach. it ended up with the boiler
38 public:
39 explicit MockPasswordSyncableService(PasswordStore* password_store):
40 PasswordSyncableService(password_store) {}
41 virtual ~MockPasswordSyncableService() {}
42 MOCK_METHOD0(NotifyPasswordStore, void());
43 };
44
45 // Concrete implementation of SyncChangeprocessor. The methods will
46 // verify that the |PasswordSyncableService| is calling the
47 // |SyncChangeProcessor| with right arguments.
48 class MockSyncChangeProcessor : public syncer::SyncChangeProcessor {
Nicolas Zea 2013/10/21 23:55:14 naming nit: This isn't a mock, so maybe just call
lipalani1 2013/10/24 00:13:58 Done.
49 public:
50 MockSyncChangeProcessor() {}
51 ~MockSyncChangeProcessor() {}
52 virtual SyncError ProcessSyncChanges(
53 const tracked_objects::Location& from_here,
54 const SyncChangeList& change_list) {
55 // Loop through the |change_list| and verify they are present in the
56 // |expected_changes_| list.
57 for (SyncChangeList::const_iterator it = change_list.begin();
58 it != change_list.end();
59 ++it) {
60 SyncChange data = *it;
61 const sync_pb::EntitySpecifics& specifics =
62 data.sync_data().GetSpecifics();
63 const sync_pb::PasswordSpecificsData& password_specifics(
64 specifics.password().client_only_encrypted_data());
65 std::string actual_tag = PasswordSyncableService::MakeTag(
66 password_specifics);
67
68 bool matched = false;
69 for (SyncChangeList::iterator expected_it = expected_changes_.begin();
70 expected_it != expected_changes_.end();
71 ++expected_it) {
72 SyncChange expected_data = *expected_it;
73 const sync_pb::EntitySpecifics& specifics =
74 expected_data.sync_data().GetSpecifics();
75 const sync_pb::PasswordSpecificsData& password_specifics(
76 specifics.password().client_only_encrypted_data());
77 std::string expected_tag = PasswordSyncableService::MakeTag(
78 password_specifics);
79 if (expected_tag == actual_tag) {
80 if (data.change_type() == expected_data.change_type()) {
81 matched = true;
82 }
83 break;
84 }
85 }
86 EXPECT_TRUE(matched);
87 }
88 EXPECT_EQ(change_list.size(), expected_changes_.size());
89 return SyncError();
90 }
91
92 virtual SyncDataList GetAllSyncData(syncer::ModelType type) const {
93 return SyncDataList();
94 }
95
96 // Adds a password entry to the |expected_changes_| list.
97 void AddExpectedChange(const autofill::PasswordForm& password,
98 SyncChange::SyncChangeType type) {
99 SyncData data = PasswordSyncableService::CreateSyncData(password);
100 SyncChange change(FROM_HERE, type, data);
101 expected_changes_.push_back(change);
102 }
103 private:
104 SyncChangeList expected_changes_;
105 };
106
107 // Class to verify the arguments passed to |PasswordStore|.
108 class PasswordStoreDataVerifier {
109 public:
110 // Adds an expected add change.
111 void AddExpectedAddChange(const SyncData& data) {
112 const sync_pb::EntitySpecifics& specifics = data.GetSpecifics();
113 const sync_pb::PasswordSpecificsData& password_specifics(
114 specifics.password().client_only_encrypted_data());
115
116 autofill::PasswordForm form;
117 PasswordSyncableService::ExtractPasswordFromSpecifics(password_specifics,
118 &form);
119 add_changes.push_back(form);
120 }
121
122 // Adds an expected update change.
123 void AddExpectedUpdateChange(const autofill::PasswordForm& form) {
124 update_changes.push_back(form);
125 }
126
127 // Verifies that the |password| is present in the |add_changes_| list.
128 void VerifyAdd(const autofill::PasswordForm& password) {
129 VerifyChange(password, &add_changes);
130 }
131
132 // Verifies that the |password| is present in the |update_changes_| list.
133 void VerifyUpdate(const autofill::PasswordForm& password) {
134 VerifyChange(password, &update_changes);
135 }
136
137 int AddChangeCount() const {
138 return add_changes.size();
139 }
140
141 int UpdateChangeCount() const {
142 return update_changes.size();
143 }
144
145 private:
146 void VerifyChange(const autofill::PasswordForm& password,
147 std::vector<autofill::PasswordForm>* password_list) {
148 bool matched = false;
149 for (std::vector<autofill::PasswordForm>::iterator it
150 = password_list->begin();
151 it != password_list->end();
152 ++it) {
153 if (password == *it) {
154 password_list->erase(it);
155 matched = true;
156 break;
157 }
158 }
159 EXPECT_TRUE(matched);
160 }
161 std::vector<autofill::PasswordForm> add_changes;
162 std::vector<autofill::PasswordForm> update_changes;
163 };
164
165 SyncData CreateSyncData(std::string signon_realm) {
166 sync_pb::EntitySpecifics password_data;
167 sync_pb::PasswordSpecificsData* password_specifics =
168 password_data.mutable_password()->mutable_client_only_encrypted_data();
169 password_specifics->set_signon_realm(signon_realm);
170
171 std::string tag = PasswordSyncableService::MakeTag(*password_specifics);
172 return syncer::SyncData::CreateLocalData(tag, tag, password_data);
173 }
174
175 class PasswordSyncableServiceTest : public testing::Test {
176 public:
177 PasswordSyncableServiceTest() {}
178 ~PasswordSyncableServiceTest() {}
179
180 virtual void SetUp() OVERRIDE {
181 TestingProfile::Builder builder;
182 scoped_ptr<Profile> profile = builder.Build().Pass();
183 password_store_ = static_cast<MockPasswordStore*>(
184 PasswordStoreFactory::GetInstance()->SetTestingFactoryAndUse(
185 profile.get(), MockPasswordStore::Build).get());
186 }
187
188 protected:
189 scoped_refptr<MockPasswordStore> password_store_;
190 };
191
192 // Both sync and password db have data that are not present in the other.
193 TEST_F(PasswordSyncableServiceTest, AdditionsInBoth) {
194 autofill::PasswordForm *form1 = new autofill::PasswordForm;
195 form1->signon_realm = "abc";
196
197 std::vector<autofill::PasswordForm*> forms;
198 forms.push_back(form1);
199
200 MockPasswordSyncableService service(password_store_.get());
201
202 SyncData sync_data = CreateSyncData("def");
203 SyncDataList list;
204 list.push_back(sync_data);
205
206 scoped_ptr<MockSyncChangeProcessor> sync_change_processor(
207 new MockSyncChangeProcessor);
208 sync_change_processor->AddExpectedChange(*form1,
209 SyncChange::ACTION_ADD);
210
211 PasswordStoreDataVerifier verifier;
212 verifier.AddExpectedAddChange(sync_data);
213
214 EXPECT_CALL(*(password_store_.get()), FillAutofillableLogins(_))
215 .WillOnce(DoAll(SetArgumentPointee<0>(forms), Return(true)));
216 EXPECT_CALL(*(password_store_.get()), FillBlacklistLogins(_))
217 .WillOnce(Return(true));
218
219 EXPECT_CALL(*(password_store_.get()), AddLoginImpl(_))
220 .WillRepeatedly(Invoke(
221 &verifier, &PasswordStoreDataVerifier::VerifyAdd));
222
223 EXPECT_CALL(service, NotifyPasswordStore());
224
225 service.MergeDataAndStartSyncing(syncer::PASSWORDS,
226 list,
227 sync_change_processor.Pass(),
228 scoped_ptr<syncer::SyncErrorFactory>()
229 .Pass());
230
231 EXPECT_EQ(0, verifier.AddChangeCount());
232 }
233
234 // Sync has data that is not present in the password db.
235 TEST_F(PasswordSyncableServiceTest, AdditionOnlyInSync) {
236 std::vector<autofill::PasswordForm*> forms;
237
238 MockPasswordSyncableService service(password_store_.get());
239
240 SyncData sync_data = CreateSyncData("def");
241 SyncDataList list;
242 list.push_back(sync_data);
243
244 scoped_ptr<MockSyncChangeProcessor> sync_change_processor(
245 new MockSyncChangeProcessor);
246
247 PasswordStoreDataVerifier verifier;
248 verifier.AddExpectedAddChange(sync_data);
249
250 EXPECT_CALL(*(password_store_.get()), FillAutofillableLogins(_))
251 .WillOnce(DoAll(SetArgumentPointee<0>(forms), Return(true)));
252 EXPECT_CALL(*password_store_.get(), FillBlacklistLogins(_))
253 .WillOnce(Return(true));
254
255 EXPECT_CALL(*(password_store_.get()), AddLoginImpl(_))
256 .WillRepeatedly(Invoke(
257 &verifier, &PasswordStoreDataVerifier::VerifyAdd));
258
259 EXPECT_CALL(service, NotifyPasswordStore());
260
261 service.MergeDataAndStartSyncing(syncer::PASSWORDS,
262 list,
263 sync_change_processor.Pass(),
264 scoped_ptr<syncer::SyncErrorFactory>()
265 .Pass());
266
267 EXPECT_EQ(0, verifier.AddChangeCount());
268 }
269
270 // Passwords db has data that is not present in sync.
271 TEST_F(PasswordSyncableServiceTest, AdditionOnlyInPasswordStore) {
272 autofill::PasswordForm *form1 = new autofill::PasswordForm;
273 form1->signon_realm = "abc";
274
275 std::vector<autofill::PasswordForm*> forms;
276 forms.push_back(form1);
277
278 MockPasswordSyncableService service(password_store_.get());
279
280 SyncDataList list;
281
282 scoped_ptr<MockSyncChangeProcessor> sync_change_processor(
283 new MockSyncChangeProcessor);
284 sync_change_processor->AddExpectedChange(*form1,
285 SyncChange::ACTION_ADD);
286
287 PasswordStoreDataVerifier verifier;
288
289 EXPECT_CALL(*(password_store_.get()), FillAutofillableLogins(_))
290 .WillOnce(DoAll(SetArgumentPointee<0>(forms), Return(true)));
291 EXPECT_CALL(*password_store_.get(), FillBlacklistLogins(_))
292 .WillOnce(Return(true));
293
294 service.MergeDataAndStartSyncing(syncer::PASSWORDS,
295 list,
296 sync_change_processor.Pass(),
297 scoped_ptr<syncer::SyncErrorFactory>()
298 .Pass());
299
300 EXPECT_EQ(0, verifier.AddChangeCount());
301 }
302
303 // Both passwords db and sync contain the same data.
304 TEST_F(PasswordSyncableServiceTest, BothInSync) {
305 autofill::PasswordForm *form1 = new autofill::PasswordForm;
306 form1->signon_realm = "abc";
307
308 std::vector<autofill::PasswordForm*> forms;
309 forms.push_back(form1);
310
311 MockPasswordSyncableService service(password_store_.get());
312
313 SyncData sync_data = CreateSyncData("abc");
314 SyncDataList list;
315 list.push_back(sync_data);
316
317 scoped_ptr<MockSyncChangeProcessor> sync_change_processor(
318 new MockSyncChangeProcessor);
319
320 EXPECT_CALL(*(password_store_.get()), FillAutofillableLogins(_))
321 .WillOnce(DoAll(SetArgumentPointee<0>(forms), Return(true)));
322 EXPECT_CALL(*password_store_.get(), FillBlacklistLogins(_))
323 .WillOnce(Return(true));
324
325 service.MergeDataAndStartSyncing(syncer::PASSWORDS,
326 list,
327 sync_change_processor.Pass(),
328 scoped_ptr<syncer::SyncErrorFactory>()
329 .Pass());
330 }
331
332 // Both passwords db and sync have the same data but they need to be merged
333 // as some fields of the data differ.
334 TEST_F(PasswordSyncableServiceTest, Merge) {
335 autofill::PasswordForm *form1 = new autofill::PasswordForm;
336 form1->signon_realm = "abc";
337 form1->action = GURL("http://pie.com");
338
339 std::vector<autofill::PasswordForm*> forms;
340 forms.push_back(form1);
341
342 MockPasswordSyncableService service(password_store_.get());
343
344 SyncData sync_data = CreateSyncData("abc");
345 SyncDataList list;
346 list.push_back(sync_data);
347
348 scoped_ptr<MockSyncChangeProcessor> sync_change_processor(
349 new MockSyncChangeProcessor);
350 sync_change_processor->AddExpectedChange(*form1,
351 SyncChange::ACTION_UPDATE);
352
353 PasswordStoreDataVerifier verifier;
354 verifier.AddExpectedUpdateChange(*form1);
355
356 EXPECT_CALL(*(password_store_.get()), FillAutofillableLogins(_))
357 .WillOnce(DoAll(SetArgumentPointee<0>(forms), Return(true)));
358 EXPECT_CALL(*password_store_.get(), FillBlacklistLogins(_))
359 .WillOnce(Return(true));
360
361 EXPECT_CALL(*(password_store_.get()), UpdateLoginImpl(_))
362 .WillRepeatedly(Invoke(&verifier,
363 &PasswordStoreDataVerifier::VerifyUpdate));
364
365 EXPECT_CALL(service, NotifyPasswordStore());
366
367 service.MergeDataAndStartSyncing(syncer::PASSWORDS,
368 list,
369 sync_change_processor.Pass(),
370 scoped_ptr<syncer::SyncErrorFactory>()
371 .Pass());
372
373 EXPECT_EQ(0, verifier.UpdateChangeCount());
374 }
375
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698