Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(73)

Unified Diff: components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service_unittest.cc

Issue 1110833002: [autofill] Sync server card and address metadata. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase on top of https://crrev.com/1125143006 Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service_unittest.cc
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service_unittest.cc b/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..2c851f2fa47afe4a79e69659ccbf405883318ca1
--- /dev/null
+++ b/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service_unittest.cc
@@ -0,0 +1,454 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.h"
+
+#include "base/strings/string_number_conversions.h"
+#include "base/time/time.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/credit_card.h"
+#include "sync/api/sync_change.h"
+#include "sync/api/sync_change_processor_wrapper_for_test.h"
+#include "sync/api/sync_error_factory_mock.h"
+#include "sync/protocol/autofill_specifics.pb.h"
+#include "sync/protocol/sync.pb.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace autofill {
+namespace {
+
+using testing::DoAll;
+using testing::NiceMock;
+using testing::Return;
+using testing::_;
+
+ACTION_P(GetPointersTo, data_list) {
+ for (auto& datum : *data_list)
+ arg0->push_back(&datum);
+}
+
+// A syncable service for Wallet metadata that mocks out disk IO for server
+// profiles and cards.
+class MockAutofillWalletMetadataSyncableService
+ : public AutofillWalletMetadataSyncableService {
+ public:
+ MockAutofillWalletMetadataSyncableService()
+ : AutofillWalletMetadataSyncableService(nullptr, std::string()) {
+ ON_CALL(*this, GetServerProfiles(_))
+ .WillByDefault(DoAll(GetPointersTo(&server_profiles_), Return(true)));
+
+ ON_CALL(*this, GetServerCreditCards(_))
+ .WillByDefault(DoAll(GetPointersTo(&server_cards_), Return(true)));
+
+ ON_CALL(*this, UpdateServerAddressUsageStats(_))
+ .WillByDefault(Return(true));
+
+ ON_CALL(*this, UpdateServerCardUsageStats(_)).WillByDefault(Return(true));
+ }
+
+ ~MockAutofillWalletMetadataSyncableService() override {}
+
+ MOCK_CONST_METHOD1(GetServerProfiles, bool(std::vector<AutofillProfile*>*));
+ MOCK_CONST_METHOD1(GetServerCreditCards, bool(std::vector<CreditCard*>*));
+ MOCK_METHOD1(UpdateServerAddressUsageStats, bool(const AutofillProfile&));
+ MOCK_METHOD1(UpdateServerCardUsageStats, bool(const CreditCard&));
+
+ // "Saves on disk" a server profile with the given |server_id|, |use_count|,
+ // and |use_date|.
+ void SaveServerProfile(const std::string& server_id,
+ int64 use_count,
+ int64 use_date) {
+ AutofillProfile profile(AutofillProfile::SERVER_PROFILE, server_id);
+ profile.set_use_count(use_count);
+ profile.set_use_date(base::Time::FromInternalValue(use_date));
+
+ for (auto it = server_profiles_.begin(); it != server_profiles_.end();
+ ++it) {
+ if (it->server_id() == server_id) {
+ *it = profile;
+ return;
+ }
+ }
+
+ server_profiles_.push_back(profile);
+ }
+
+ // "Saves on disk" a server card with the given |server_id|, |use_count|, and
+ // |use_date|.
+ void SaveServerCard(const std::string& server_id,
+ int64 use_count,
+ int64 use_date) {
+ CreditCard card(CreditCard::MASKED_SERVER_CARD, server_id);
+ card.set_use_count(use_count);
+ card.set_use_date(base::Time::FromInternalValue(use_date));
+
+ for (auto it = server_cards_.begin(); it != server_cards_.end(); ++it) {
+ if (it->server_id() == server_id) {
+ *it = card;
+ return;
+ }
+ }
+
+ server_cards_.push_back(card);
+ }
+
+ private:
+ std::vector<AutofillProfile> server_profiles_;
+ std::vector<CreditCard> server_cards_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockAutofillWalletMetadataSyncableService);
+};
+
+// Verify that nothing is sent to the sync server when there's no metadata on
+// disk.
+TEST(AutofillWalletMetadataSyncableServiceTest, NoMetadataToReturn) {
+ NiceMock<MockAutofillWalletMetadataSyncableService> service;
+ EXPECT_TRUE(service.GetAllSyncData(syncer::AUTOFILL_WALLET_METADATA).empty());
+}
+
+// Verify that all metadata from disk is sent to the sync server.
+TEST(AutofillWalletMetadataSyncableServiceTest, ReturnAllMetadata) {
+ NiceMock<MockAutofillWalletMetadataSyncableService> service;
+ service.SaveServerProfile("data", 1, 2);
+ service.SaveServerCard("data", 1, 2);
+
+ syncer::SyncDataList data_list =
+ service.GetAllSyncData(syncer::AUTOFILL_WALLET_METADATA);
+
+ ASSERT_EQ(2UL, data_list.size());
+ EXPECT_NE(syncer::SyncDataLocal(data_list[0]).GetTag(),
+ syncer::SyncDataLocal(data_list[1]).GetTag());
+
+ for (const syncer::SyncData& datum : data_list) {
+ EXPECT_TRUE(datum.IsValid());
+ EXPECT_TRUE("address-data" == syncer::SyncDataLocal(datum).GetTag() ||
+ "card-data" == syncer::SyncDataLocal(datum).GetTag());
+ EXPECT_EQ(syncer::AUTOFILL_WALLET_METADATA, datum.GetDataType());
+ EXPECT_EQ("data", datum.GetSpecifics().wallet_metadata().id());
+ EXPECT_EQ(1, datum.GetSpecifics().wallet_metadata().use_count());
+ EXPECT_EQ(2, datum.GetSpecifics().wallet_metadata().use_date());
+ }
+}
+
+// Verify that nothing is written to disk for empty sync changes.
+TEST(AutofillWalletMetadataSyncableServiceTest, ProcessEmptyChanges) {
+ NiceMock<MockAutofillWalletMetadataSyncableService> service;
+ service.SaveServerProfile("addr", 1, 2);
+ service.SaveServerCard("card", 3, 4);
+
+ EXPECT_CALL(service, UpdateServerAddressUsageStats(_)).Times(0);
+ EXPECT_CALL(service, UpdateServerCardUsageStats(_)).Times(0);
+
+ EXPECT_FALSE(
+ service.ProcessSyncChanges(FROM_HERE, syncer::SyncChangeList()).IsSet());
+}
+
+syncer::SyncChange BuildChange(
+ syncer::SyncChange::SyncChangeType change_type,
+ sync_pb::WalletMetadataSpecifics::Type metadata_type,
+ const std::string& server_id,
+ int64 use_count,
+ int64 use_date) {
+ sync_pb::EntitySpecifics entity;
+ entity.mutable_wallet_metadata()->set_type(metadata_type);
+ entity.mutable_wallet_metadata()->set_id(server_id);
+ entity.mutable_wallet_metadata()->set_use_count(use_count);
+ entity.mutable_wallet_metadata()->set_use_date(use_date);
+ return syncer::SyncChange(
+ FROM_HERE, change_type,
+ syncer::SyncData::CreateLocalData(server_id, server_id, entity));
+}
+
+MATCHER_P3(Matches,
+ server_id,
+ use_count,
+ use_date,
+ std::string(negation ? "isn't" : "is") + " server_id=" + server_id +
+ " use_count=" +
+ base::IntToString(use_count) +
+ " use_date=" +
+ base::IntToString(use_date)) {
+ *result_listener << "where server_id=" << arg.server_id()
+ << " use_count=" << arg.use_count()
+ << " use_date=" << arg.use_date().ToInternalValue();
+ return arg.server_id() == server_id &&
+ arg.use_count() == static_cast<size_t>(use_count) &&
+ arg.use_date() == base::Time::FromInternalValue(use_date);
+}
+
+// Verify that sync changes are written to disk.
+TEST(AutofillWalletMetadataSyncableServiceTest, ProcessChanges) {
+ syncer::SyncChangeList changes;
+ changes.push_back(BuildChange(syncer::SyncChange::ACTION_ADD,
+ sync_pb::WalletMetadataSpecifics::ADDRESS,
+ "addr1", 1, 2));
+ changes.push_back(BuildChange(syncer::SyncChange::ACTION_UPDATE,
+ sync_pb::WalletMetadataSpecifics::ADDRESS,
+ "addr2", 3, 4));
+ changes.push_back(BuildChange(syncer::SyncChange::ACTION_ADD,
+ sync_pb::WalletMetadataSpecifics::CARD, "card1",
+ 5, 6));
+ changes.push_back(BuildChange(syncer::SyncChange::ACTION_UPDATE,
+ sync_pb::WalletMetadataSpecifics::CARD, "card2",
+ 7, 8));
+
+ NiceMock<MockAutofillWalletMetadataSyncableService> service;
+ service.SaveServerProfile("addr1", 0, 0);
+ service.SaveServerProfile("addr2", 0, 0);
+ service.SaveServerCard("card1", 0, 0);
+ service.SaveServerCard("card2", 0, 0);
+
+ EXPECT_CALL(service, UpdateServerAddressUsageStats(Matches("addr1", 1, 2)));
+ EXPECT_CALL(service, UpdateServerAddressUsageStats(Matches("addr2", 3, 4)));
+ EXPECT_CALL(service, UpdateServerCardUsageStats(Matches("card1", 5, 6)));
+ EXPECT_CALL(service, UpdateServerCardUsageStats(Matches("card2", 7, 8)));
+
+ EXPECT_FALSE(service.ProcessSyncChanges(FROM_HERE, changes).IsSet());
+}
+
+// Verify that local metadata is not changed if the sync server requests
+// deletion. (Metadata life-cycle is tied to the corresponding Wallet data.)
+TEST(AutofillWalletMetadataSyncableServiceTest,
+ IgnoreSyncCommandsToDeleteMetadata) {
+ syncer::SyncChangeList changes;
+ changes.push_back(BuildChange(syncer::SyncChange::ACTION_DELETE,
+ sync_pb::WalletMetadataSpecifics::ADDRESS,
+ "addr", 1, 2));
+ changes.push_back(BuildChange(syncer::SyncChange::ACTION_DELETE,
+ sync_pb::WalletMetadataSpecifics::CARD, "card",
+ 3, 4));
+
+ NiceMock<MockAutofillWalletMetadataSyncableService> service;
+ service.SaveServerProfile("addr", 0, 0);
+ service.SaveServerCard("card", 0, 0);
+
+ EXPECT_CALL(service, UpdateServerAddressUsageStats(_)).Times(0);
+ EXPECT_CALL(service, UpdateServerCardUsageStats(_)).Times(0);
+
+ EXPECT_FALSE(service.ProcessSyncChanges(FROM_HERE, changes).IsSet());
+}
+
+// Verify that incoming sync messages do not write metadata for non-existent
+// data.
+TEST(AutofillWalletMetadataSyncableServiceTest,
+ IgnoreOrphanMetadataInSyncChanges) {
+ syncer::SyncChangeList changes;
+ changes.push_back(BuildChange(syncer::SyncChange::ACTION_ADD,
+ sync_pb::WalletMetadataSpecifics::ADDRESS,
+ "addr", 1, 2));
+ changes.push_back(BuildChange(syncer::SyncChange::ACTION_ADD,
+ sync_pb::WalletMetadataSpecifics::CARD, "card",
+ 3, 4));
+ NiceMock<MockAutofillWalletMetadataSyncableService> service;
+
+ EXPECT_CALL(service, UpdateServerAddressUsageStats(_)).Times(0);
+ EXPECT_CALL(service, UpdateServerCardUsageStats(_)).Times(0);
+
+ EXPECT_FALSE(service.ProcessSyncChanges(FROM_HERE, changes).IsSet());
+}
+
+void MergeMetadata(MockAutofillWalletMetadataSyncableService* local,
+ MockAutofillWalletMetadataSyncableService* remote) {
+ scoped_ptr<syncer::SyncErrorFactoryMock> errors(
+ new syncer::SyncErrorFactoryMock);
+ EXPECT_CALL(*errors, CreateAndUploadError(_, _)).Times(0);
+ EXPECT_FALSE(
+ local->MergeDataAndStartSyncing(
+ syncer::AUTOFILL_WALLET_METADATA,
+ remote->GetAllSyncData(syncer::AUTOFILL_WALLET_METADATA),
+ scoped_ptr<syncer::SyncChangeProcessor>(
+ new syncer::SyncChangeProcessorWrapperForTest(remote)),
+ errors.Pass())
+ .error()
+ .IsSet());
+}
+
+// Verify that no writes happen when sync server sends no metadata.
+TEST(AutofillWalletMetadataSyncableServiceTest, NoDataToMerge) {
+ NiceMock<MockAutofillWalletMetadataSyncableService> local;
+ local.SaveServerProfile("addr", 1, 2);
+ local.SaveServerCard("card", 3, 4);
+ NiceMock<MockAutofillWalletMetadataSyncableService> remote;
+
+ EXPECT_CALL(local, UpdateServerAddressUsageStats(_)).Times(0);
+ EXPECT_CALL(local, UpdateServerCardUsageStats(_)).Times(0);
+
+ MergeMetadata(&local, &remote);
+}
+
+// Verify that no writes happen when sync server sends metadata that is
+// identical to the local metadata.
+TEST(AutofillWalletMetadataSyncableServiceTest, IdenticalDataMerge) {
+ NiceMock<MockAutofillWalletMetadataSyncableService> local;
+ local.SaveServerProfile("addr", 1, 2);
+ local.SaveServerCard("card", 3, 4);
+
+ NiceMock<MockAutofillWalletMetadataSyncableService> remote;
+ remote.SaveServerProfile("addr", 1, 2);
+ remote.SaveServerCard("card", 3, 4);
+
+ EXPECT_CALL(local, UpdateServerAddressUsageStats(_)).Times(0);
+ EXPECT_CALL(local, UpdateServerCardUsageStats(_)).Times(0);
+
+ EXPECT_CALL(remote, UpdateServerAddressUsageStats(_)).Times(0);
+ EXPECT_CALL(remote, UpdateServerCardUsageStats(_)).Times(0);
+
+ MergeMetadata(&local, &remote);
+}
+
+// Verify that the larger use count and later use date overwrite the smaller use
+// count and earlier use date when merging metadata.
+TEST(AutofillWalletMetadataSyncableServiceTest, MergePicksMaxUseCountDate) {
+ NiceMock<MockAutofillWalletMetadataSyncableService> local;
+ local.SaveServerProfile("addr", 50, 100);
+ local.SaveServerCard("card", 100, 50);
+
+ NiceMock<MockAutofillWalletMetadataSyncableService> remote;
+ remote.SaveServerProfile("addr", 100, 50);
+ remote.SaveServerCard("card", 50, 100);
+
+ EXPECT_CALL(local, UpdateServerAddressUsageStats(Matches("addr", 100, 100)));
+ EXPECT_CALL(local, UpdateServerCardUsageStats(Matches("card", 100, 100)));
+
+ EXPECT_CALL(remote, UpdateServerAddressUsageStats(Matches("addr", 100, 100)));
+ EXPECT_CALL(remote, UpdateServerCardUsageStats(Matches("card", 100, 100)));
+
+ MergeMetadata(&local, &remote);
+}
+
+// Verify that initial merge does not write metadata for non-existent data.
+TEST(AutofillWalletMetadataSyncableServiceTest,
+ IgnoreOrphanMetadataInInitialMerge) {
+ NiceMock<MockAutofillWalletMetadataSyncableService> local;
+ NiceMock<MockAutofillWalletMetadataSyncableService> remote;
+ remote.SaveServerProfile("addr", 1, 2);
+ remote.SaveServerCard("card", 3, 4);
+
+ EXPECT_CALL(local, UpdateServerAddressUsageStats(_)).Times(0);
+ EXPECT_CALL(local, UpdateServerCardUsageStats(_)).Times(0);
+
+ MergeMetadata(&local, &remote);
+}
+
+// Verify that updating Wallet data and metadata will send a message to the sync
+// server.
+TEST(AutofillWalletMetadataSyncableServiceTest, WalletDataUpdateSyncsMetadata) {
+ NiceMock<MockAutofillWalletMetadataSyncableService> local;
+ local.SaveServerProfile("addr", 0, 0);
+ local.SaveServerCard("card", 0, 0);
+
+ NiceMock<MockAutofillWalletMetadataSyncableService> remote;
+ remote.SaveServerProfile("addr", 0, 0);
+ remote.SaveServerCard("card", 0, 0);
+
+ MergeMetadata(&local, &remote);
+
+ AutofillProfile profile(AutofillProfile::SERVER_PROFILE, "addr");
+ profile.set_use_count(1);
+ profile.set_use_date(base::Time::FromInternalValue(2));
+
+ CreditCard card(CreditCard::MASKED_SERVER_CARD, "card");
+ card.set_use_count(3);
+ card.set_use_date(base::Time::FromInternalValue(4));
+
+ EXPECT_CALL(remote, UpdateServerAddressUsageStats(Matches("addr", 1, 2)));
+ EXPECT_CALL(remote, UpdateServerCardUsageStats(Matches("card", 3, 4)));
+
+ local.AutofillProfileChanged(AutofillProfileChange(
+ AutofillProfileChange::UPDATE, profile.guid(), &profile));
+ local.CreditCardChanged(
+ CreditCardChange(CreditCardChange::UPDATE, card.guid(), &card));
+}
+
+// Verify that updating a non-Wallet profile or credit card will not send
+// metadata to the sync server.
+TEST(AutofillWalletMetadataSyncableServiceTest, IgnoreNonWalletDataUpdate) {
+ NiceMock<MockAutofillWalletMetadataSyncableService> local;
+ local.SaveServerProfile("addr", 0, 0);
+ local.SaveServerCard("card", 0, 0);
+
+ NiceMock<MockAutofillWalletMetadataSyncableService> remote;
+ remote.SaveServerProfile("addr", 0, 0);
+ remote.SaveServerCard("card", 0, 0);
+
+ MergeMetadata(&local, &remote);
+
+ AutofillProfile profile;
+ profile.set_use_count(1);
+ profile.set_use_date(base::Time::FromInternalValue(2));
+
+ CreditCard card;
+ card.set_use_count(3);
+ card.set_use_date(base::Time::FromInternalValue(4));
+
+ EXPECT_CALL(remote, UpdateServerAddressUsageStats(_)).Times(0);
+ EXPECT_CALL(remote, UpdateServerCardUsageStats(_)).Times(0);
+
+ local.AutofillProfileChanged(AutofillProfileChange(
+ AutofillProfileChange::UPDATE, profile.guid(), &profile));
+ local.CreditCardChanged(
+ CreditCardChange(CreditCardChange::UPDATE, card.guid(), &card));
+}
+
+// Verify that deleting or adding an individual Wallet address or credit card is
+// ignored. (Sync should be notified only of "multiple autofill data changes"
+// sent by the Wallet sync service.)
+TEST(AutofillWalletMetadataSyncableServiceTest, IgnoreIndividualDataAddDelete) {
+ NiceMock<MockAutofillWalletMetadataSyncableService> local;
+ local.SaveServerProfile("addr1", 0, 0);
+ local.SaveServerProfile("addr2", 0, 0);
+ local.SaveServerCard("card1", 0, 0);
+ local.SaveServerCard("card2", 0, 0);
+
+ NiceMock<MockAutofillWalletMetadataSyncableService> remote;
+ remote.SaveServerProfile("addr1", 0, 0);
+ remote.SaveServerProfile("addr2", 0, 0);
+ remote.SaveServerCard("card1", 0, 0);
+ remote.SaveServerCard("card2", 0, 0);
+
+ MergeMetadata(&local, &remote);
+
+ AutofillProfile profile1(AutofillProfile::SERVER_PROFILE, "addr1");
+ AutofillProfile profile2(AutofillProfile::SERVER_PROFILE, "addr2");
+ CreditCard card1(CreditCard::MASKED_SERVER_CARD, "card1");
+ CreditCard card2(CreditCard::FULL_SERVER_CARD, "card2");
+
+ EXPECT_CALL(remote, UpdateServerAddressUsageStats(_)).Times(0);
+ EXPECT_CALL(remote, UpdateServerCardUsageStats(_)).Times(0);
+
+ local.AutofillProfileChanged(AutofillProfileChange(
+ AutofillProfileChange::ADD, profile1.guid(), &profile1));
+ local.AutofillProfileChanged(AutofillProfileChange(
+ AutofillProfileChange::REMOVE, profile2.guid(), nullptr));
+ local.CreditCardChanged(
+ CreditCardChange(CreditCardChange::ADD, card1.guid(), &card1));
+ local.CreditCardChanged(
+ CreditCardChange(CreditCardChange::REMOVE, card2.guid(), nullptr));
+}
+
+// Verify that the sync server is notified of new metadata when Wallet data is
+// added.
+TEST(AutofillWalletMetadataSyncableServiceTest, NotifySyncServerNewMetadata) {
+ NiceMock<MockAutofillWalletMetadataSyncableService> local;
+ local.SaveServerProfile("addr", 0, 0);
+ local.SaveServerCard("card", 0, 0);
+
+ NiceMock<MockAutofillWalletMetadataSyncableService> remote;
+ remote.SaveServerProfile("addr", 0, 0);
+ remote.SaveServerCard("card", 0, 0);
+
+ MergeMetadata(&local, &remote);
+
+ local.SaveServerProfile("addr", 1, 2);
+ local.SaveServerCard("card", 3, 4);
+
+ EXPECT_CALL(remote, UpdateServerAddressUsageStats(Matches("addr", 1, 2)));
+ EXPECT_CALL(remote, UpdateServerCardUsageStats(Matches("card", 3, 4)));
+
+ local.AutofillMultipleChanged();
+}
+
+} // namespace
+} // namespace autofill

Powered by Google App Engine
This is Rietveld 408576698