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

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