1 // Copyright 2013 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 <string> 6 #include <vector> 7 8 #include "base/basictypes.h" 9 #include "base/files/scoped_temp_dir.h" 10 #include "base/memory/ref_counted.h" 11 #include "base/memory/scoped_ptr.h" 12 #include "base/memory/scoped_vector.h" 13 #include "base/message_loop/message_loop.h" 14 #include "base/stl_util.h" 15 #include "base/strings/string16.h" 16 #include "base/strings/string_util.h" 17 #include "base/strings/utf_string_conversions.h" 18 #include "base/synchronization/waitable_event.h" 19 #include "base/time/time.h" 20 #include "chrome/browser/webdata/web_data_service.h" 21 #include "components/autofill/core/browser/autofill_country.h" 22 #include "components/autofill/core/browser/autofill_profile.h" 23 #include "components/autofill/core/browser/credit_card.h" 24 #include "components/autofill/core/browser/webdata/autofill_change.h" 25 #include "components/autofill/core/browser/webdata/autofill_entry.h" 26 #include "components/autofill/core/browser/webdata/autofill_table.h" 27 #include "components/autofill/core/browser/webdata/autofill_webdata_service.h" 28 #include "components/autofill/core/browser/webdata/autofill_webdata_service_observer.h" 29 #include "components/autofill/core/common/form_field_data.h" 30 #include "components/webdata/common/web_data_results.h" 31 #include "components/webdata/common/web_data_service_base.h" 32 #include "components/webdata/common/web_data_service_consumer.h" 33 #include "components/webdata/common/web_database_service.h" 34 #include "content/public/test/test_browser_thread.h" 35 #include "testing/gmock/include/gmock/gmock.h" 36 #include "testing/gtest/include/gtest/gtest.h" 37 38 using base::Time; 39 using base::TimeDelta; 40 using base::WaitableEvent; 41 using content::BrowserThread; 42 using testing::_; 43 using testing::DoDefault; 44 using testing::ElementsAreArray; 45 using testing::Pointee; 46 using testing::Property; 47 48 namespace { 49 50 template <class T> 51 class AutofillWebDataServiceConsumer: public WebDataServiceConsumer { 52 public: 53 AutofillWebDataServiceConsumer() : handle_(0) {} 54 virtual ~AutofillWebDataServiceConsumer() {} 55 56 virtual void OnWebDataServiceRequestDone(WebDataService::Handle handle, 57 const WDTypedResult* result) { 58 using content::BrowserThread; 59 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 60 handle_ = handle; 61 const WDResult<T>* wrapped_result = 62 static_cast<const WDResult<T>*>(result); 63 result_ = wrapped_result->GetValue(); 64 65 base::MessageLoop::current()->Quit(); 66 } 67 68 WebDataService::Handle handle() { return handle_; } 69 T& result() { return result_; } 70 71 private: 72 WebDataService::Handle handle_; 73 T result_; 74 DISALLOW_COPY_AND_ASSIGN(AutofillWebDataServiceConsumer); 75 }; 76 77 } // namespace 78 79 namespace autofill { 80 81 static const int kWebDataServiceTimeoutSeconds = 8; 82 83 ACTION_P(SignalEvent, event) { 84 event->Signal(); 85 } 86 87 class MockAutofillWebDataServiceObserver 88 : public AutofillWebDataServiceObserverOnDBThread { 89 public: 90 MOCK_METHOD1(AutofillEntriesChanged, 91 void(const AutofillChangeList& changes)); 92 MOCK_METHOD1(AutofillProfileChanged, 93 void(const AutofillProfileChange& change)); 94 }; 95 96 class WebDataServiceTest : public testing::Test { 97 public: 98 WebDataServiceTest() 99 : ui_thread_(BrowserThread::UI, &message_loop_), 100 db_thread_(BrowserThread::DB) {} 101 102 protected: 103 virtual void SetUp() { 104 db_thread_.Start(); 105 106 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 107 base::FilePath path = temp_dir_.path().AppendASCII("TestWebDB"); 108 109 wdbs_ = new WebDatabaseService( 110 path, 111 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), 112 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB)); 113 wdbs_->AddTable(scoped_ptr<WebDatabaseTable>(new AutofillTable("en-US"))); 114 wdbs_->LoadDatabase(); 115 116 wds_ = new AutofillWebDataService( 117 wdbs_, WebDataServiceBase::ProfileErrorCallback()); 118 wds_->Init(); 119 } 120 121 virtual void TearDown() { 122 wds_->ShutdownOnUIThread(); 123 wdbs_->ShutdownDatabase(); 124 wds_ = NULL; 125 wdbs_ = NULL; 126 WaitForDatabaseThread(); 127 128 base::MessageLoop::current()->PostTask(FROM_HERE, 129 base::MessageLoop::QuitClosure()); 130 base::MessageLoop::current()->Run(); 131 db_thread_.Stop(); 132 } 133 134 void WaitForDatabaseThread() { 135 base::WaitableEvent done(false, false); 136 BrowserThread::PostTask( 137 BrowserThread::DB, 138 FROM_HERE, 139 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&done))); 140 done.Wait(); 141 } 142 143 base::MessageLoopForUI message_loop_; 144 content::TestBrowserThread ui_thread_; 145 content::TestBrowserThread db_thread_; 146 base::FilePath profile_dir_; 147 scoped_refptr<AutofillWebDataService> wds_; 148 scoped_refptr<WebDatabaseService> wdbs_; 149 base::ScopedTempDir temp_dir_; 150 }; 151 152 class WebDataServiceAutofillTest : public WebDataServiceTest { 153 public: 154 WebDataServiceAutofillTest() 155 : WebDataServiceTest(), 156 unique_id1_(1), 157 unique_id2_(2), 158 test_timeout_(TimeDelta::FromSeconds(kWebDataServiceTimeoutSeconds)), 159 done_event_(false, false) {} 160 161 protected: 162 virtual void SetUp() { 163 WebDataServiceTest::SetUp(); 164 name1_ = ASCIIToUTF16("name1"); 165 name2_ = ASCIIToUTF16("name2"); 166 value1_ = ASCIIToUTF16("value1"); 167 value2_ = ASCIIToUTF16("value2"); 168 169 void(AutofillWebDataService::*add_observer_func)( 170 AutofillWebDataServiceObserverOnDBThread*) = 171 &AutofillWebDataService::AddObserver; 172 BrowserThread::PostTask( 173 BrowserThread::DB, 174 FROM_HERE, 175 base::Bind(add_observer_func, wds_, &observer_)); 176 WaitForDatabaseThread(); 177 } 178 179 virtual void TearDown() { 180 void(AutofillWebDataService::*remove_observer_func)( 181 AutofillWebDataServiceObserverOnDBThread*) = 182 &AutofillWebDataService::RemoveObserver; 183 BrowserThread::PostTask( 184 BrowserThread::DB, 185 FROM_HERE, 186 base::Bind(remove_observer_func, wds_, &observer_)); 187 WaitForDatabaseThread(); 188 189 WebDataServiceTest::TearDown(); 190 } 191 192 void AppendFormField(const base::string16& name, 193 const base::string16& value, 194 std::vector<FormFieldData>* form_fields) { 195 FormFieldData field; 196 field.name = name; 197 field.value = value; 198 form_fields->push_back(field); 199 } 200 201 base::string16 name1_; 202 base::string16 name2_; 203 base::string16 value1_; 204 base::string16 value2_; 205 int unique_id1_, unique_id2_; 206 const TimeDelta test_timeout_; 207 testing::NiceMock<MockAutofillWebDataServiceObserver> observer_; 208 WaitableEvent done_event_; 209 }; 210 211 // Simple consumer for Keywords data. Stores the result data and quits UI 212 // message loop when callback is invoked. 213 class KeywordsConsumer : public WebDataServiceConsumer { 214 public: 215 KeywordsConsumer() : load_succeeded(false) {} 216 217 virtual void OnWebDataServiceRequestDone( 218 WebDataService::Handle h, 219 const WDTypedResult* result) OVERRIDE { 220 if (result) { 221 load_succeeded = true; 222 DCHECK(result->GetType() == KEYWORDS_RESULT); 223 keywords_result = 224 reinterpret_cast<const WDResult<WDKeywordsResult>*>( 225 result)->GetValue(); 226 } 227 228 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 229 base::MessageLoop::current()->Quit(); 230 } 231 232 // True if keywords data was loaded successfully. 233 bool load_succeeded; 234 // Result data from completion callback. 235 WDKeywordsResult keywords_result; 236 }; 237 238 TEST_F(WebDataServiceAutofillTest, FormFillAdd) { 239 const AutofillChange expected_changes[] = { 240 AutofillChange(AutofillChange::ADD, AutofillKey(name1_, value1_)), 241 AutofillChange(AutofillChange::ADD, AutofillKey(name2_, value2_)) 242 }; 243 244 // This will verify that the correct notification is triggered, 245 // passing the correct list of autofill keys in the details. 246 EXPECT_CALL(observer_, 247 AutofillEntriesChanged(ElementsAreArray(expected_changes))) 248 .WillOnce(SignalEvent(&done_event_)); 249 250 std::vector<FormFieldData> form_fields; 251 AppendFormField(name1_, value1_, &form_fields); 252 AppendFormField(name2_, value2_, &form_fields); 253 wds_->AddFormFields(form_fields); 254 255 // The event will be signaled when the mock observer is notified. 256 done_event_.TimedWait(test_timeout_); 257 258 AutofillWebDataServiceConsumer<std::vector<base::string16> > consumer; 259 WebDataService::Handle handle; 260 static const int limit = 10; 261 handle = wds_->GetFormValuesForElementName( 262 name1_, base::string16(), limit, &consumer); 263 264 // The message loop will exit when the consumer is called. 265 base::MessageLoop::current()->Run(); 266 267 EXPECT_EQ(handle, consumer.handle()); 268 ASSERT_EQ(1U, consumer.result().size()); 269 EXPECT_EQ(value1_, consumer.result()[0]); 270 } 271 272 TEST_F(WebDataServiceAutofillTest, FormFillRemoveOne) { 273 // First add some values to autofill. 274 EXPECT_CALL(observer_, AutofillEntriesChanged(_)) 275 .WillOnce(SignalEvent(&done_event_)); 276 std::vector<FormFieldData> form_fields; 277 AppendFormField(name1_, value1_, &form_fields); 278 wds_->AddFormFields(form_fields); 279 280 // The event will be signaled when the mock observer is notified. 281 done_event_.TimedWait(test_timeout_); 282 283 // This will verify that the correct notification is triggered, 284 // passing the correct list of autofill keys in the details. 285 const AutofillChange expected_changes[] = { 286 AutofillChange(AutofillChange::REMOVE, AutofillKey(name1_, value1_)) 287 }; 288 EXPECT_CALL(observer_, 289 AutofillEntriesChanged(ElementsAreArray(expected_changes))) 290 .WillOnce(SignalEvent(&done_event_)); 291 wds_->RemoveFormValueForElementName(name1_, value1_); 292 293 // The event will be signaled when the mock observer is notified. 294 done_event_.TimedWait(test_timeout_); 295 } 296 297 TEST_F(WebDataServiceAutofillTest, FormFillRemoveMany) { 298 TimeDelta one_day(TimeDelta::FromDays(1)); 299 Time t = Time::Now(); 300 301 EXPECT_CALL(observer_, AutofillEntriesChanged(_)) 302 .WillOnce(SignalEvent(&done_event_)); 303 304 std::vector<FormFieldData> form_fields; 305 AppendFormField(name1_, value1_, &form_fields); 306 AppendFormField(name2_, value2_, &form_fields); 307 wds_->AddFormFields(form_fields); 308 309 // The event will be signaled when the mock observer is notified. 310 done_event_.TimedWait(test_timeout_); 311 312 // This will verify that the correct notification is triggered, 313 // passing the correct list of autofill keys in the details. 314 const AutofillChange expected_changes[] = { 315 AutofillChange(AutofillChange::REMOVE, AutofillKey(name1_, value1_)), 316 AutofillChange(AutofillChange::REMOVE, AutofillKey(name2_, value2_)) 317 }; 318 EXPECT_CALL(observer_, 319 AutofillEntriesChanged(ElementsAreArray(expected_changes))) 320 .WillOnce(SignalEvent(&done_event_)); 321 wds_->RemoveFormElementsAddedBetween(t, t + one_day); 322 323 // The event will be signaled when the mock observer is notified. 324 done_event_.TimedWait(test_timeout_); 325 } 326 327 TEST_F(WebDataServiceAutofillTest, ProfileAdd) { 328 AutofillProfile profile; 329 330 // Check that GUID-based notification was sent. 331 const AutofillProfileChange expected_change( 332 AutofillProfileChange::ADD, profile.guid(), &profile); 333 EXPECT_CALL(observer_, AutofillProfileChanged(expected_change)) 334 .WillOnce(SignalEvent(&done_event_)); 335 336 wds_->AddAutofillProfile(profile); 337 done_event_.TimedWait(test_timeout_); 338 339 // Check that it was added. 340 AutofillWebDataServiceConsumer<std::vector<AutofillProfile*> > consumer; 341 WebDataService::Handle handle = wds_->GetAutofillProfiles(&consumer); 342 base::MessageLoop::current()->Run(); 343 EXPECT_EQ(handle, consumer.handle()); 344 ASSERT_EQ(1U, consumer.result().size()); 345 EXPECT_EQ(profile, *consumer.result()[0]); 346 STLDeleteElements(&consumer.result()); 347 } 348 349 TEST_F(WebDataServiceAutofillTest, ProfileRemove) { 350 AutofillProfile profile; 351 352 // Add a profile. 353 EXPECT_CALL(observer_, AutofillProfileChanged(_)) 354 .WillOnce(SignalEvent(&done_event_)); 355 wds_->AddAutofillProfile(profile); 356 done_event_.TimedWait(test_timeout_); 357 358 // Check that it was added. 359 AutofillWebDataServiceConsumer<std::vector<AutofillProfile*> > consumer; 360 WebDataService::Handle handle = wds_->GetAutofillProfiles(&consumer); 361 base::MessageLoop::current()->Run(); 362 EXPECT_EQ(handle, consumer.handle()); 363 ASSERT_EQ(1U, consumer.result().size()); 364 EXPECT_EQ(profile, *consumer.result()[0]); 365 STLDeleteElements(&consumer.result()); 366 367 // Check that GUID-based notification was sent. 368 const AutofillProfileChange expected_change( 369 AutofillProfileChange::REMOVE, profile.guid(), NULL); 370 EXPECT_CALL(observer_, AutofillProfileChanged(expected_change)) 371 .WillOnce(SignalEvent(&done_event_)); 372 373 // Remove the profile. 374 wds_->RemoveAutofillProfile(profile.guid()); 375 done_event_.TimedWait(test_timeout_); 376 377 // Check that it was removed. 378 AutofillWebDataServiceConsumer<std::vector<AutofillProfile*> > consumer2; 379 WebDataService::Handle handle2 = wds_->GetAutofillProfiles(&consumer2); 380 base::MessageLoop::current()->Run(); 381 EXPECT_EQ(handle2, consumer2.handle()); 382 ASSERT_EQ(0U, consumer2.result().size()); 383 } 384 385 TEST_F(WebDataServiceAutofillTest, ProfileUpdate) { 386 AutofillProfile profile1; 387 profile1.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Abe")); 388 AutofillProfile profile2; 389 profile2.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Alice")); 390 391 EXPECT_CALL(observer_, AutofillProfileChanged(_)) 392 .WillOnce(DoDefault()) 393 .WillOnce(SignalEvent(&done_event_)); 394 395 wds_->AddAutofillProfile(profile1); 396 wds_->AddAutofillProfile(profile2); 397 done_event_.TimedWait(test_timeout_); 398 399 // Check that they were added. 400 AutofillWebDataServiceConsumer<std::vector<AutofillProfile*> > consumer; 401 WebDataService::Handle handle = wds_->GetAutofillProfiles(&consumer); 402 base::MessageLoop::current()->Run(); 403 EXPECT_EQ(handle, consumer.handle()); 404 ASSERT_EQ(2U, consumer.result().size()); 405 EXPECT_EQ(profile1, *consumer.result()[0]); 406 EXPECT_EQ(profile2, *consumer.result()[1]); 407 STLDeleteElements(&consumer.result()); 408 409 AutofillProfile profile1_changed(profile1); 410 profile1_changed.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Bill")); 411 const AutofillProfileChange expected_change( 412 AutofillProfileChange::UPDATE, profile1.guid(), &profile1_changed); 413 414 EXPECT_CALL(observer_, AutofillProfileChanged(expected_change)) 415 .WillOnce(SignalEvent(&done_event_)); 416 417 // Update the profile. 418 wds_->UpdateAutofillProfile(profile1_changed); 419 done_event_.TimedWait(test_timeout_); 420 421 // Check that the updates were made. 422 AutofillWebDataServiceConsumer<std::vector<AutofillProfile*> > consumer2; 423 WebDataService::Handle handle2 = wds_->GetAutofillProfiles(&consumer2); 424 base::MessageLoop::current()->Run(); 425 EXPECT_EQ(handle2, consumer2.handle()); 426 ASSERT_EQ(2U, consumer2.result().size()); 427 EXPECT_NE(profile1, *consumer2.result()[0]); 428 EXPECT_EQ(profile1_changed, *consumer2.result()[0]); 429 EXPECT_EQ(profile2, *consumer2.result()[1]); 430 STLDeleteElements(&consumer2.result()); 431 } 432 433 TEST_F(WebDataServiceAutofillTest, CreditAdd) { 434 CreditCard card; 435 wds_->AddCreditCard(card); 436 WaitForDatabaseThread(); 437 438 // Check that it was added. 439 AutofillWebDataServiceConsumer<std::vector<CreditCard*> > consumer; 440 WebDataService::Handle handle = wds_->GetCreditCards(&consumer); 441 base::MessageLoop::current()->Run(); 442 EXPECT_EQ(handle, consumer.handle()); 443 ASSERT_EQ(1U, consumer.result().size()); 444 EXPECT_EQ(card, *consumer.result()[0]); 445 STLDeleteElements(&consumer.result()); 446 } 447 448 TEST_F(WebDataServiceAutofillTest, CreditCardRemove) { 449 CreditCard credit_card; 450 451 // Add a credit card. 452 wds_->AddCreditCard(credit_card); 453 WaitForDatabaseThread(); 454 455 // Check that it was added. 456 AutofillWebDataServiceConsumer<std::vector<CreditCard*> > consumer; 457 WebDataService::Handle handle = wds_->GetCreditCards(&consumer); 458 base::MessageLoop::current()->Run(); 459 EXPECT_EQ(handle, consumer.handle()); 460 ASSERT_EQ(1U, consumer.result().size()); 461 EXPECT_EQ(credit_card, *consumer.result()[0]); 462 STLDeleteElements(&consumer.result()); 463 464 // Remove the credit card. 465 wds_->RemoveCreditCard(credit_card.guid()); 466 WaitForDatabaseThread(); 467 468 // Check that it was removed. 469 AutofillWebDataServiceConsumer<std::vector<CreditCard*> > consumer2; 470 WebDataService::Handle handle2 = wds_->GetCreditCards(&consumer2); 471 base::MessageLoop::current()->Run(); 472 EXPECT_EQ(handle2, consumer2.handle()); 473 ASSERT_EQ(0U, consumer2.result().size()); 474 } 475 476 TEST_F(WebDataServiceAutofillTest, CreditUpdate) { 477 CreditCard card1; 478 card1.SetRawInfo(CREDIT_CARD_NAME, ASCIIToUTF16("Abe")); 479 CreditCard card2; 480 card2.SetRawInfo(CREDIT_CARD_NAME, ASCIIToUTF16("Alice")); 481 482 wds_->AddCreditCard(card1); 483 wds_->AddCreditCard(card2); 484 WaitForDatabaseThread(); 485 486 // Check that they got added. 487 AutofillWebDataServiceConsumer<std::vector<CreditCard*> > consumer; 488 WebDataService::Handle handle = wds_->GetCreditCards(&consumer); 489 base::MessageLoop::current()->Run(); 490 EXPECT_EQ(handle, consumer.handle()); 491 ASSERT_EQ(2U, consumer.result().size()); 492 EXPECT_EQ(card1, *consumer.result()[0]); 493 EXPECT_EQ(card2, *consumer.result()[1]); 494 STLDeleteElements(&consumer.result()); 495 496 CreditCard card1_changed(card1); 497 card1_changed.SetRawInfo(CREDIT_CARD_NAME, ASCIIToUTF16("Bill")); 498 499 wds_->UpdateCreditCard(card1_changed); 500 WaitForDatabaseThread(); 501 502 // Check that the updates were made. 503 AutofillWebDataServiceConsumer<std::vector<CreditCard*> > consumer2; 504 WebDataService::Handle handle2 = wds_->GetCreditCards(&consumer2); 505 base::MessageLoop::current()->Run(); 506 EXPECT_EQ(handle2, consumer2.handle()); 507 ASSERT_EQ(2U, consumer2.result().size()); 508 EXPECT_NE(card1, *consumer2.result()[0]); 509 EXPECT_EQ(card1_changed, *consumer2.result()[0]); 510 EXPECT_EQ(card2, *consumer2.result()[1]); 511 STLDeleteElements(&consumer2.result()); 512 } 513 514 TEST_F(WebDataServiceAutofillTest, AutofillRemoveModifiedBetween) { 515 // Add a profile. 516 EXPECT_CALL(observer_, AutofillProfileChanged(_)) 517 .WillOnce(SignalEvent(&done_event_)); 518 AutofillProfile profile; 519 wds_->AddAutofillProfile(profile); 520 done_event_.TimedWait(test_timeout_); 521 522 // Check that it was added. 523 AutofillWebDataServiceConsumer<std::vector<AutofillProfile*> > 524 profile_consumer; 525 WebDataService::Handle handle = wds_->GetAutofillProfiles(&profile_consumer); 526 base::MessageLoop::current()->Run(); 527 EXPECT_EQ(handle, profile_consumer.handle()); 528 ASSERT_EQ(1U, profile_consumer.result().size()); 529 EXPECT_EQ(profile, *profile_consumer.result()[0]); 530 STLDeleteElements(&profile_consumer.result()); 531 532 // Add a credit card. 533 CreditCard credit_card; 534 wds_->AddCreditCard(credit_card); 535 WaitForDatabaseThread(); 536 537 // Check that it was added. 538 AutofillWebDataServiceConsumer<std::vector<CreditCard*> > card_consumer; 539 handle = wds_->GetCreditCards(&card_consumer); 540 base::MessageLoop::current()->Run(); 541 EXPECT_EQ(handle, card_consumer.handle()); 542 ASSERT_EQ(1U, card_consumer.result().size()); 543 EXPECT_EQ(credit_card, *card_consumer.result()[0]); 544 STLDeleteElements(&card_consumer.result()); 545 546 // Check that GUID-based notification was sent for the profile. 547 const AutofillProfileChange expected_profile_change( 548 AutofillProfileChange::REMOVE, profile.guid(), NULL); 549 EXPECT_CALL(observer_, AutofillProfileChanged(expected_profile_change)) 550 .WillOnce(SignalEvent(&done_event_)); 551 552 // Remove the profile using time range of "all time". 553 wds_->RemoveAutofillDataModifiedBetween(Time(), Time()); 554 done_event_.TimedWait(test_timeout_); 555 WaitForDatabaseThread(); 556 557 // Check that the profile was removed. 558 AutofillWebDataServiceConsumer<std::vector<AutofillProfile*> > 559 profile_consumer2; 560 WebDataService::Handle handle2 = 561 wds_->GetAutofillProfiles(&profile_consumer2); 562 base::MessageLoop::current()->Run(); 563 EXPECT_EQ(handle2, profile_consumer2.handle()); 564 ASSERT_EQ(0U, profile_consumer2.result().size()); 565 566 // Check that the credit card was removed. 567 AutofillWebDataServiceConsumer<std::vector<CreditCard*> > card_consumer2; 568 handle2 = wds_->GetCreditCards(&card_consumer2); 569 base::MessageLoop::current()->Run(); 570 EXPECT_EQ(handle2, card_consumer2.handle()); 571 ASSERT_EQ(0U, card_consumer2.result().size()); 572 } 573 574 } // namespace autofill 575