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