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