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

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