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