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