password_syncable_service_unittest.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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 "components/password_manager/core/browser/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 "components/password_manager/core/browser/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
22using syncer::SyncChange;
23using syncer::SyncData;
24using syncer::SyncDataList;
25using syncer::SyncError;
26using testing::Invoke;
27using testing::Return;
28using testing::SetArgPointee;
29using testing::_;
30
31namespace {
32
33typedef std::vector<SyncChange> SyncChangeList;
34
35const sync_pb::PasswordSpecificsData& GetPasswordSpecifics(
36    const syncer::SyncData& sync_data) {
37  const sync_pb::EntitySpecifics& specifics = sync_data.GetSpecifics();
38  return specifics.password().client_only_encrypted_data();
39}
40
41void 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|.
63SyncData 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
73SyncChange 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.
81class 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|.
92class PasswordStoreDataVerifier {
93 public:
94  PasswordStoreDataVerifier() {}
95  ~PasswordStoreDataVerifier() {
96    EXPECT_TRUE(expected_db_add_changes_.empty());
97    EXPECT_TRUE(expected_db_update_changes_.empty());
98    EXPECT_TRUE(expected_db_delete_changes_.empty());
99  }
100
101  class TestSyncChangeProcessor;
102
103  // Sets expected changes to the password database.
104  void SetExpectedDBChanges(
105      const SyncDataList& add_forms,
106      const std::vector<autofill::PasswordForm*>& update_forms,
107      const std::vector<autofill::PasswordForm*>& delete_forms,
108      MockPasswordStore* password_store);
109  // Sets expected changes to TestSyncChangeProcessor.
110  void SetExpectedSyncChanges(SyncChangeList list);
111
112 private:
113  // Checks that |change_list| matches |expected_sync_change_list_|.
114  SyncError TestSyncChanges(const SyncChangeList& change_list);
115
116  // Verifies that the |password| is present in the |expected_db_add_changes_|
117  // list. If found, |password| would be removed from
118  // |expected_db_add_changes_| list.
119  PasswordStoreChangeList VerifyAdd(const autofill::PasswordForm& password) {
120    return VerifyChange(PasswordStoreChange::ADD, password,
121                        &expected_db_add_changes_);
122  }
123
124  // Verifies that the |password| is present in the
125  // |expected_db_update_changes_| list. If found, |password| would be removed
126  // from |expected_db_update_changes_| list.
127  PasswordStoreChangeList VerifyUpdate(const autofill::PasswordForm& password) {
128    return VerifyChange(PasswordStoreChange::UPDATE, password,
129                        &expected_db_update_changes_);
130  }
131
132  // Verifies that the |password| is present in the
133  // |expected_db_delete_changes_| list. If found, |password| would be removed
134  // from |expected_db_delete_changes_| list.
135  PasswordStoreChangeList VerifyDelete(const autofill::PasswordForm& password) {
136    return VerifyChange(PasswordStoreChange::REMOVE, password,
137                        &expected_db_delete_changes_);
138  }
139
140  static PasswordStoreChangeList VerifyChange(
141      PasswordStoreChange::Type type,
142      const autofill::PasswordForm& password,
143      std::vector<autofill::PasswordForm>* password_list);
144
145  std::vector<autofill::PasswordForm> expected_db_add_changes_;
146  std::vector<autofill::PasswordForm> expected_db_update_changes_;
147  std::vector<autofill::PasswordForm> expected_db_delete_changes_;
148  SyncChangeList expected_sync_change_list_;
149
150  DISALLOW_COPY_AND_ASSIGN(PasswordStoreDataVerifier);
151};
152
153class PasswordStoreDataVerifier::TestSyncChangeProcessor
154    : public syncer::SyncChangeProcessor {
155 public:
156  explicit TestSyncChangeProcessor(PasswordStoreDataVerifier* verifier)
157      : verifier_(verifier) {
158  }
159  virtual ~TestSyncChangeProcessor() {}
160
161  virtual SyncError ProcessSyncChanges(const tracked_objects::Location&,
162                                       const SyncChangeList& list) OVERRIDE {
163    return verifier_->TestSyncChanges(list);
164  }
165
166  virtual SyncDataList GetAllSyncData(syncer::ModelType type) const OVERRIDE {
167    return SyncDataList();
168  }
169 private:
170  PasswordStoreDataVerifier* verifier_;
171
172  DISALLOW_COPY_AND_ASSIGN(TestSyncChangeProcessor);
173};
174
175void PasswordStoreDataVerifier::SetExpectedDBChanges(
176    const SyncDataList& add_forms,
177    const std::vector<autofill::PasswordForm*>& update_forms,
178    const std::vector<autofill::PasswordForm*>& delete_forms,
179    MockPasswordStore* password_store) {
180  DCHECK(expected_db_add_changes_.empty());
181  DCHECK(expected_db_update_changes_.empty());
182  DCHECK(password_store);
183
184  for (SyncDataList::const_iterator it = add_forms.begin();
185       it != add_forms.end(); ++it) {
186    autofill::PasswordForm form;
187    PasswordFromSpecifics(GetPasswordSpecifics(*it), &form);
188    expected_db_add_changes_.push_back(form);
189  }
190  if (expected_db_add_changes_.empty()) {
191    EXPECT_CALL(*password_store, AddLoginImpl(_)).Times(0);
192  } else {
193    EXPECT_CALL(*password_store, AddLoginImpl(_))
194        .Times(expected_db_add_changes_.size())
195        .WillRepeatedly(Invoke(this, &PasswordStoreDataVerifier::VerifyAdd));
196  }
197
198  for (std::vector<autofill::PasswordForm*>::const_iterator it =
199           update_forms.begin();
200       it != update_forms.end(); ++it) {
201    expected_db_update_changes_.push_back(**it);
202  }
203  if (expected_db_update_changes_.empty()) {
204    EXPECT_CALL(*password_store, UpdateLoginImpl(_)).Times(0);
205  } else {
206    EXPECT_CALL(*password_store, UpdateLoginImpl(_))
207        .Times(expected_db_update_changes_.size())
208        .WillRepeatedly(Invoke(this, &PasswordStoreDataVerifier::VerifyUpdate));
209  }
210
211  for (std::vector<autofill::PasswordForm*>::const_iterator it =
212           delete_forms.begin();
213       it != delete_forms.end(); ++it) {
214    expected_db_delete_changes_.push_back(**it);
215  }
216  if (expected_db_delete_changes_.empty()) {
217    EXPECT_CALL(*password_store, RemoveLoginImpl(_)).Times(0);
218  } else {
219    EXPECT_CALL(*password_store, RemoveLoginImpl(_))
220        .Times(expected_db_delete_changes_.size())
221        .WillRepeatedly(Invoke(this, &PasswordStoreDataVerifier::VerifyDelete));
222  }
223}
224
225void PasswordStoreDataVerifier::SetExpectedSyncChanges(SyncChangeList list) {
226  expected_sync_change_list_.swap(list);
227}
228
229SyncError PasswordStoreDataVerifier::TestSyncChanges(
230    const SyncChangeList& change_list) {
231  for (SyncChangeList::const_iterator it = change_list.begin();
232      it != change_list.end(); ++it) {
233    const SyncChange& data = *it;
234    const sync_pb::PasswordSpecificsData& actual_password(
235        GetPasswordSpecifics(data.sync_data()));
236    std::string actual_tag = MakePasswordSyncTag(actual_password);
237
238    bool matched = false;
239    for (SyncChangeList::iterator expected_it =
240             expected_sync_change_list_.begin();
241         expected_it != expected_sync_change_list_.end();
242         ++expected_it) {
243      const sync_pb::PasswordSpecificsData& expected_password(
244          GetPasswordSpecifics(expected_it->sync_data()));
245      if (actual_tag == MakePasswordSyncTag(expected_password)) {
246        PasswordsEqual(expected_password, actual_password);
247        EXPECT_EQ(expected_it->change_type(), data.change_type());
248        matched = true;
249        break;
250      }
251    }
252    EXPECT_TRUE(matched) << actual_tag;
253  }
254  EXPECT_EQ(expected_sync_change_list_.size(), change_list.size());
255  return SyncError();
256}
257
258// static
259PasswordStoreChangeList PasswordStoreDataVerifier::VerifyChange(
260    PasswordStoreChange::Type type,
261    const autofill::PasswordForm& password,
262    std::vector<autofill::PasswordForm>* password_list) {
263  std::vector<autofill::PasswordForm>::iterator it =
264      std::find(password_list->begin(), password_list->end(), password);
265  EXPECT_NE(password_list->end(), it);
266  password_list->erase(it);
267  return PasswordStoreChangeList(1, PasswordStoreChange(type, password));
268}
269
270class PasswordSyncableServiceWrapper {
271 public:
272  PasswordSyncableServiceWrapper() {
273    password_store_ = new MockPasswordStore;
274    service_.reset(new MockPasswordSyncableService(password_store_));
275  }
276
277  ~PasswordSyncableServiceWrapper() {
278    password_store_->Shutdown();
279  }
280
281  MockPasswordStore* password_store() {
282    return password_store_;
283  }
284
285  MockPasswordSyncableService* service() {
286    return service_.get();
287  }
288
289  // Returnes the scoped_ptr to |service_| thus NULLing out it.
290  scoped_ptr<syncer::SyncChangeProcessor> ReleaseSyncableService() {
291    return service_.PassAs<syncer::SyncChangeProcessor>();
292  }
293
294  PasswordStoreDataVerifier* verifier() {
295    return &verifier_;
296  }
297
298  scoped_ptr<syncer::SyncChangeProcessor> CreateSyncChangeProcessor() {
299    return make_scoped_ptr<syncer::SyncChangeProcessor>(
300        new PasswordStoreDataVerifier::TestSyncChangeProcessor(verifier()));
301  }
302
303  // Sets the data that will be returned to the caller accessing password store.
304  void SetPasswordStoreData(
305      const std::vector<autofill::PasswordForm*>& forms,
306      const std::vector<autofill::PasswordForm*>& blacklist_forms) {
307    EXPECT_CALL(*password_store_, FillAutofillableLogins(_))
308        .WillOnce(Invoke(AppendVector(forms)))
309        .RetiresOnSaturation();
310    EXPECT_CALL(*password_store_, FillBlacklistLogins(_))
311        .WillOnce(Invoke(AppendVector(blacklist_forms)))
312        .RetiresOnSaturation();
313  }
314
315 protected:
316  scoped_refptr<MockPasswordStore> password_store_;
317  scoped_ptr<MockPasswordSyncableService> service_;
318  PasswordStoreDataVerifier verifier_;
319
320 private:
321  struct AppendVector {
322    explicit AppendVector(
323        const std::vector<autofill::PasswordForm*>& append_forms)
324        : append_forms_(append_forms) {
325    }
326
327    ~AppendVector() {}
328
329    bool operator()(std::vector<autofill::PasswordForm*>* forms) const {
330      forms->insert(forms->end(), append_forms_.begin(), append_forms_.end());
331      return true;
332    }
333
334    std::vector<autofill::PasswordForm*> append_forms_;
335  };
336
337  DISALLOW_COPY_AND_ASSIGN(PasswordSyncableServiceWrapper);
338};
339
340class PasswordSyncableServiceTest : public testing::Test,
341                                    public PasswordSyncableServiceWrapper {
342 public:
343  PasswordSyncableServiceTest() {}
344  virtual ~PasswordSyncableServiceTest() {}
345};
346
347
348// Both sync and password db have data that are not present in the other.
349TEST_F(PasswordSyncableServiceTest, AdditionsInBoth) {
350  scoped_ptr<autofill::PasswordForm> form1(new autofill::PasswordForm);
351  form1->signon_realm = "abc";
352  std::vector<autofill::PasswordForm*> forms;
353  forms.push_back(form1.release());
354  SetPasswordStoreData(forms, std::vector<autofill::PasswordForm*>());
355
356  SyncData sync_data = CreateSyncData("def");
357  SyncDataList list;
358  list.push_back(sync_data);
359
360  verifier()->SetExpectedDBChanges(list,
361                                   std::vector<autofill::PasswordForm*>(),
362                                   std::vector<autofill::PasswordForm*>(),
363                                   password_store());
364  verifier()->SetExpectedSyncChanges(
365      SyncChangeList(1, CreateSyncChange(*forms[0], SyncChange::ACTION_ADD)));
366  EXPECT_CALL(*service(), NotifyPasswordStoreOfLoginChanges(_));
367
368  service()->MergeDataAndStartSyncing(syncer::PASSWORDS,
369                                      list,
370                                      CreateSyncChangeProcessor(),
371                                      scoped_ptr<syncer::SyncErrorFactory>());
372}
373
374// Sync has data that is not present in the password db.
375TEST_F(PasswordSyncableServiceTest, AdditionOnlyInSync) {
376  SetPasswordStoreData(std::vector<autofill::PasswordForm*>(),
377                       std::vector<autofill::PasswordForm*>());
378
379  SyncData sync_data = CreateSyncData("def");
380  SyncDataList list;
381  list.push_back(sync_data);
382
383  verifier()->SetExpectedDBChanges(list,
384                                   std::vector<autofill::PasswordForm*>(),
385                                   std::vector<autofill::PasswordForm*>(),
386                                   password_store());
387  verifier()->SetExpectedSyncChanges(SyncChangeList());
388  EXPECT_CALL(*service(), NotifyPasswordStoreOfLoginChanges(_));
389
390  service()->MergeDataAndStartSyncing(syncer::PASSWORDS,
391                                      list,
392                                      CreateSyncChangeProcessor(),
393                                      scoped_ptr<syncer::SyncErrorFactory>());
394}
395
396// Passwords db has data that is not present in sync.
397TEST_F(PasswordSyncableServiceTest, AdditionOnlyInPasswordStore) {
398  scoped_ptr<autofill::PasswordForm> form1(new autofill::PasswordForm);
399  form1->signon_realm = "abc";
400  std::vector<autofill::PasswordForm*> forms;
401  forms.push_back(form1.release());
402  SetPasswordStoreData(forms, std::vector<autofill::PasswordForm*>());
403
404  verifier()->SetExpectedDBChanges(SyncDataList(),
405                                   std::vector<autofill::PasswordForm*>(),
406                                   std::vector<autofill::PasswordForm*>(),
407                                   password_store());
408  verifier()->SetExpectedSyncChanges(
409      SyncChangeList(1, CreateSyncChange(*forms[0], SyncChange::ACTION_ADD)));
410  EXPECT_CALL(*service_,
411              NotifyPasswordStoreOfLoginChanges(PasswordStoreChangeList()));
412
413  service()->MergeDataAndStartSyncing(syncer::PASSWORDS,
414                                      SyncDataList(),
415                                      CreateSyncChangeProcessor(),
416                                      scoped_ptr<syncer::SyncErrorFactory>());
417}
418
419// Both passwords db and sync contain the same data.
420TEST_F(PasswordSyncableServiceTest, BothInSync) {
421  scoped_ptr<autofill::PasswordForm> form1(new autofill::PasswordForm);
422  form1->signon_realm = "abc";
423  std::vector<autofill::PasswordForm*> forms;
424  forms.push_back(form1.release());
425  SetPasswordStoreData(forms, std::vector<autofill::PasswordForm*>());
426
427  verifier()->SetExpectedDBChanges(SyncDataList(),
428                                   std::vector<autofill::PasswordForm*>(),
429                                   std::vector<autofill::PasswordForm*>(),
430                                   password_store());
431  verifier()->SetExpectedSyncChanges(SyncChangeList());
432  EXPECT_CALL(*service_,
433              NotifyPasswordStoreOfLoginChanges(PasswordStoreChangeList()));
434
435  service()->MergeDataAndStartSyncing(syncer::PASSWORDS,
436                                      SyncDataList(1, CreateSyncData("abc")),
437                                      CreateSyncChangeProcessor(),
438                                      scoped_ptr<syncer::SyncErrorFactory>());
439}
440
441// Both passwords db and sync have the same data but they need to be merged
442// as some fields of the data differ.
443TEST_F(PasswordSyncableServiceTest, Merge) {
444  scoped_ptr<autofill::PasswordForm> form1(new autofill::PasswordForm);
445  form1->signon_realm = "abc";
446  form1->action = GURL("http://pie.com");
447  form1->date_created = base::Time::Now();
448  std::vector<autofill::PasswordForm*> forms;
449  forms.push_back(form1.release());
450  SetPasswordStoreData(forms, std::vector<autofill::PasswordForm*>());
451
452  verifier()->SetExpectedDBChanges(SyncDataList(),
453                                   std::vector<autofill::PasswordForm*>(),
454                                   std::vector<autofill::PasswordForm*>(),
455                                   password_store());
456  verifier()->SetExpectedSyncChanges(
457      SyncChangeList(1, CreateSyncChange(*forms[0],
458                                         SyncChange::ACTION_UPDATE)));
459
460  EXPECT_CALL(*service(), NotifyPasswordStoreOfLoginChanges(_));
461
462  service()->MergeDataAndStartSyncing(syncer::PASSWORDS,
463                                      SyncDataList(1, CreateSyncData("abc")),
464                                      CreateSyncChangeProcessor(),
465                                      scoped_ptr<syncer::SyncErrorFactory>());
466}
467
468// Initiate sync due to local DB changes.
469TEST_F(PasswordSyncableServiceTest, PasswordStoreChanges) {
470  // Set the sync change processor first.
471  SetPasswordStoreData(std::vector<autofill::PasswordForm*>(),
472                       std::vector<autofill::PasswordForm*>());
473  verifier()->SetExpectedSyncChanges(SyncChangeList());
474  EXPECT_CALL(*service_,
475              NotifyPasswordStoreOfLoginChanges(PasswordStoreChangeList()));
476  service_->MergeDataAndStartSyncing(syncer::PASSWORDS,
477                                     SyncDataList(),
478                                     CreateSyncChangeProcessor(),
479                                     scoped_ptr<syncer::SyncErrorFactory>());
480
481  autofill::PasswordForm form1;
482  form1.signon_realm = "abc";
483  autofill::PasswordForm form2;
484  form2.signon_realm = "def";
485  autofill::PasswordForm form3;
486  form3.signon_realm = "xyz";
487
488  SyncChangeList sync_list;
489  sync_list.push_back(CreateSyncChange(form1, SyncChange::ACTION_ADD));
490  sync_list.push_back(CreateSyncChange(form2, SyncChange::ACTION_UPDATE));
491  sync_list.push_back(CreateSyncChange(form3, SyncChange::ACTION_DELETE));
492
493  verifier()->SetExpectedDBChanges(SyncDataList(),
494                                   std::vector<autofill::PasswordForm*>(),
495                                   std::vector<autofill::PasswordForm*>(),
496                                   password_store());
497  verifier()->SetExpectedSyncChanges(sync_list);
498
499  PasswordStoreChangeList list;
500  list.push_back(PasswordStoreChange(PasswordStoreChange::ADD, form1));
501  list.push_back(PasswordStoreChange(PasswordStoreChange::UPDATE, form2));
502  list.push_back(PasswordStoreChange(PasswordStoreChange::REMOVE, form3));
503  service()->ActOnPasswordStoreChanges(list);
504}
505
506// Process all types of changes from sync.
507TEST_F(PasswordSyncableServiceTest, ProcessSyncChanges) {
508  scoped_ptr<autofill::PasswordForm> form1(new autofill::PasswordForm);
509  form1->signon_realm = "abc";
510  form1->action = GURL("http://foo.com");
511  scoped_ptr<autofill::PasswordForm> form2(new autofill::PasswordForm);
512  form2->signon_realm = "xyz";
513  form2->action = GURL("http://bar.com");
514  form2->date_created = base::Time::Now();
515  form2->blacklisted_by_user = true;
516  std::vector<autofill::PasswordForm*> forms(1, form1.release());
517  std::vector<autofill::PasswordForm*> blacklist_forms(1, form2.release());
518  SetPasswordStoreData(forms, blacklist_forms);
519
520  SyncData add_data = CreateSyncData("def");
521  autofill::PasswordForm updated_form = *forms[0];
522  updated_form.date_created = base::Time::Now();
523  std::vector<autofill::PasswordForm*> updated_passwords(1, &updated_form);
524  std::vector<autofill::PasswordForm*> deleted_passwords(1, blacklist_forms[0]);
525  verifier()->SetExpectedDBChanges(SyncDataList(1, add_data),
526                                   updated_passwords,
527                                   deleted_passwords,
528                                   password_store());
529
530  SyncChangeList list;
531  list.push_back(SyncChange(FROM_HERE,
532                            syncer::SyncChange::ACTION_ADD,
533                            add_data));
534  list.push_back(SyncChange(FROM_HERE,
535                            syncer::SyncChange::ACTION_UPDATE,
536                            SyncDataFromPassword(updated_form)));
537  list.push_back(CreateSyncChange(*blacklist_forms[0],
538                                  syncer::SyncChange::ACTION_DELETE));
539  EXPECT_CALL(*service(), NotifyPasswordStoreOfLoginChanges(_));
540  service()->ProcessSyncChanges(FROM_HERE, list);
541}
542
543// Retrives sync data from the model.
544TEST_F(PasswordSyncableServiceTest, GetAllSyncData) {
545  scoped_ptr<autofill::PasswordForm> form1(new autofill::PasswordForm);
546  form1->signon_realm = "abc";
547  form1->action = GURL("http://foo.com");
548  scoped_ptr<autofill::PasswordForm> form2(new autofill::PasswordForm);
549  form2->signon_realm = "xyz";
550  form2->action = GURL("http://bar.com");
551  form2->blacklisted_by_user = true;
552  std::vector<autofill::PasswordForm*> forms(1, form1.release());
553  std::vector<autofill::PasswordForm*> blacklist_forms(1, form2.release());
554  SetPasswordStoreData(forms, blacklist_forms);
555
556  SyncDataList expected_list;
557  expected_list.push_back(SyncDataFromPassword(*forms[0]));
558  expected_list.push_back(SyncDataFromPassword(*blacklist_forms[0]));
559
560  verifier()->SetExpectedDBChanges(SyncDataList(),
561                                   std::vector<autofill::PasswordForm*>(),
562                                   std::vector<autofill::PasswordForm*>(),
563                                   password_store());
564
565  SyncDataList actual_list = service()->GetAllSyncData(syncer::PASSWORDS);
566  EXPECT_EQ(expected_list.size(), actual_list.size());
567  for (SyncDataList::iterator i(actual_list.begin()), j(expected_list.begin());
568       i != actual_list.end() && j != expected_list.end(); ++i, ++j) {
569    PasswordsEqual(GetPasswordSpecifics(*j), GetPasswordSpecifics(*i));
570  }
571}
572
573// Creates 2 PasswordSyncableService instances, merges the content of the first
574// one to the second one and back.
575TEST_F(PasswordSyncableServiceTest, MergeDataAndPushBack) {
576  scoped_ptr<autofill::PasswordForm> form1(new autofill::PasswordForm);
577  form1->signon_realm = "abc";
578  form1->action = GURL("http://foo.com");
579  std::vector<autofill::PasswordForm*> forms(1, form1.release());
580  SetPasswordStoreData(forms, std::vector<autofill::PasswordForm*>());
581
582  PasswordSyncableServiceWrapper other_service_wrapper;
583  scoped_ptr<autofill::PasswordForm> form2(new autofill::PasswordForm);
584  form2->signon_realm = "xyz";
585  form2->action = GURL("http://bar.com");
586  syncer::SyncData form2_sync_data = SyncDataFromPassword(*form2);
587  other_service_wrapper.SetPasswordStoreData(
588      std::vector<autofill::PasswordForm*>(1, form2.release()),
589      std::vector<autofill::PasswordForm*>());
590
591  verifier()->SetExpectedDBChanges(SyncDataList(1, form2_sync_data),
592                                   std::vector<autofill::PasswordForm*>(),
593                                   std::vector<autofill::PasswordForm*>(),
594                                   password_store());
595  other_service_wrapper.verifier()->SetExpectedDBChanges(
596      SyncDataList(1, SyncDataFromPassword(*forms[0])),
597      std::vector<autofill::PasswordForm*>(),
598      std::vector<autofill::PasswordForm*>(),
599      other_service_wrapper.password_store());
600  EXPECT_CALL(*service(), NotifyPasswordStoreOfLoginChanges(_));
601  EXPECT_CALL(*other_service_wrapper.service(),
602              NotifyPasswordStoreOfLoginChanges(_));
603
604  syncer::SyncDataList other_service_data =
605      other_service_wrapper.service()->GetAllSyncData(syncer::PASSWORDS);
606  service()->MergeDataAndStartSyncing(
607      syncer::PASSWORDS,
608      other_service_data,
609      other_service_wrapper.ReleaseSyncableService(),
610      scoped_ptr<syncer::SyncErrorFactory>());
611}
612
613}  // namespace
614