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

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

Powered by Google App Engine
This is Rietveld 408576698