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

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: Class comment and one more expectation in test. Created 5 years, 6 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..3ee21e0770d4a39afe204e4d5199e8b47bb303e3
--- /dev/null
+++ b/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service_unittest.cc
@@ -0,0 +1,771 @@
+// 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 <utility>
+#include <vector>
+
+#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::ElementsAre;
+using testing::Invoke;
+using testing::NiceMock;
+using testing::Return;
+using testing::UnorderedElementsAre;
+using testing::Value;
+using testing::_;
+
+ACTION_P2(GetPointersTo, profiles, cards) {
+ for (auto& profile : *profiles)
+ arg0->insert(std::make_pair(profile.server_id(), &profile));
+
+ for (auto& card : *cards)
+ arg1->insert(std::make_pair(card.server_id(), &card));
+}
+
+ACTION_P(SaveDataIn, list) {
+ for (auto it = list->begin(); it != list->end(); ++it) {
+ if (it->server_id() == arg0.server_id()) {
+ *it = arg0;
+ return;
+ }
+ }
+
+ list->push_back(arg0);
+}
+
+// A syncable service for Wallet metadata that mocks out disk IO.
+class MockService : public AutofillWalletMetadataSyncableService {
+ public:
+ MockService()
+ : AutofillWalletMetadataSyncableService(nullptr, std::string()) {
+ ON_CALL(*this, GetLocalData(_, _))
+ .WillByDefault(DoAll(GetPointersTo(&server_profiles_, &server_cards_),
+ Return(true)));
+
+ ON_CALL(*this, UpdateAddressStats(_))
+ .WillByDefault(DoAll(SaveDataIn(&server_profiles_), Return(true)));
+
+ ON_CALL(*this, UpdateCardStats(_))
+ .WillByDefault(DoAll(SaveDataIn(&server_cards_), Return(true)));
+
+ ON_CALL(*this, SendChangesToSyncServer(_))
+ .WillByDefault(
+ Invoke(this, &MockService::SendChangesToSyncServerConcrete));
+ }
+
+ ~MockService() override {}
+
+ MOCK_METHOD1(UpdateAddressStats, bool(const AutofillProfile&));
+ MOCK_METHOD1(UpdateCardStats, bool(const CreditCard&));
+ MOCK_METHOD1(SendChangesToSyncServer,
+ syncer::SyncError(const syncer::SyncChangeList&));
+
+ void ClearServerData() {
+ server_profiles_.clear();
+ server_cards_.clear();
+ }
+
+ private:
+ MOCK_CONST_METHOD2(GetLocalData,
+ bool(std::map<std::string, AutofillProfile*>*,
+ std::map<std::string, CreditCard*>*));
+
+ syncer::SyncError SendChangesToSyncServerConcrete(
+ const syncer::SyncChangeList& changes) {
+ return AutofillWalletMetadataSyncableService::SendChangesToSyncServer(
+ changes);
+ }
+
+ syncer::SyncDataList GetAllSyncDataConcrete(syncer::ModelType type) const {
+ return AutofillWalletMetadataSyncableService::GetAllSyncData(type);
+ }
+
+ std::vector<AutofillProfile> server_profiles_;
+ std::vector<CreditCard> server_cards_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockService);
+};
+
+// Verify that nothing is sent to the sync server when there's no metadata on
+// disk.
+TEST(AutofillWalletMetadataSyncableServiceTest, NoMetadataToReturn) {
+ EXPECT_TRUE(NiceMock<MockService>()
+ .GetAllSyncData(syncer::AUTOFILL_WALLET_METADATA)
+ .empty());
+}
+
+AutofillProfile BuildAddress(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));
+ return profile;
+}
+
+CreditCard BuildCard(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));
+ return card;
+}
+
+MATCHER_P5(SyncDataMatches,
+ sync_tag,
+ metadata_type,
+ server_id,
+ use_count,
+ use_date,
+ "") {
+ return arg.IsValid() &&
+ syncer::AUTOFILL_WALLET_METADATA == arg.GetDataType() &&
+ sync_tag == syncer::SyncDataLocal(arg).GetTag() &&
+ metadata_type == arg.GetSpecifics().wallet_metadata().type() &&
+ server_id == arg.GetSpecifics().wallet_metadata().id() &&
+ use_count == arg.GetSpecifics().wallet_metadata().use_count() &&
+ use_date == arg.GetSpecifics().wallet_metadata().use_date();
+}
+
+// Verify that all metadata from disk is sent to the sync server.
+TEST(AutofillWalletMetadataSyncableServiceTest, ReturnAllMetadata) {
+ NiceMock<MockService> local;
+ local.UpdateAddressStats(BuildAddress("addr", 1, 2));
+ local.UpdateCardStats(BuildCard("card", 3, 4));
+
+ EXPECT_THAT(
+ local.GetAllSyncData(syncer::AUTOFILL_WALLET_METADATA),
+ UnorderedElementsAre(
+ SyncDataMatches("address-addr",
+ sync_pb::WalletMetadataSpecifics::ADDRESS, "addr", 1,
+ 2),
+ SyncDataMatches("card-card", sync_pb::WalletMetadataSpecifics::CARD,
+ "card", 3, 4)));
+}
+
+void MergeMetadata(MockService* local, MockService* remote) {
+ // The wrapper for |remote| gives it a null change processor, so sending
+ // changes is not possible.
+ ON_CALL(*remote, SendChangesToSyncServer(_))
+ .WillByDefault(Return(syncer::SyncError()));
+
+ 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 nothing is written to disk or sent to the sync server when two
+// empty clients are syncing.
+TEST(AutofillWalletMetadataSyncableServiceTest, TwoEmptyClients) {
+ NiceMock<MockService> local;
+ NiceMock<MockService> remote;
+
+ EXPECT_CALL(local, UpdateAddressStats(_)).Times(0);
+ EXPECT_CALL(local, UpdateCardStats(_)).Times(0);
+ EXPECT_CALL(local, SendChangesToSyncServer(_)).Times(0);
+
+ MergeMetadata(&local, &remote);
+}
+
+MATCHER_P2(SyncChangeMatches, change_type, sync_tag, "") {
+ return arg.IsValid() && change_type == arg.change_type() &&
+ sync_tag == syncer::SyncDataLocal(arg.sync_data()).GetTag() &&
+ syncer::AUTOFILL_WALLET_METADATA == arg.sync_data().GetDataType();
+}
+
+// Verify that remote data without local counterpart is deleted during the
+// initial merge.
+TEST(AutofillWalletMetadataSyncableServiceTest, DeleteFromServerOnMerge) {
+ NiceMock<MockService> local;
+ NiceMock<MockService> remote;
+ remote.UpdateAddressStats(BuildAddress("addr", 1, 2));
+ remote.UpdateCardStats(BuildCard("card", 3, 4));
+
+ EXPECT_CALL(local, UpdateAddressStats(_)).Times(0);
+ EXPECT_CALL(local, UpdateCardStats(_)).Times(0);
+ EXPECT_CALL(
+ local,
+ SendChangesToSyncServer(UnorderedElementsAre(
+ SyncChangeMatches(syncer::SyncChange::ACTION_DELETE, "address-addr"),
+ SyncChangeMatches(syncer::SyncChange::ACTION_DELETE, "card-card"))));
+
+ MergeMetadata(&local, &remote);
+}
+
+MATCHER_P6(SyncChangeAndDataMatch,
+ change_type,
+ sync_tag,
+ metadata_type,
+ server_id,
+ use_count,
+ use_date,
+ "") {
+ return Value(arg, SyncChangeMatches(change_type, sync_tag)) &&
+ Value(arg.sync_data(),
+ SyncDataMatches(sync_tag, metadata_type, server_id, use_count,
+ use_date));
+}
+
+// Verify that local data is sent to the sync server during the initial merge,
+// if the server does not have the data already.
+TEST(AutofillWalletMetadataSyncableServiceTest, AddToServerOnMerge) {
+ NiceMock<MockService> local;
+ local.UpdateAddressStats(BuildAddress("addr", 1, 2));
+ local.UpdateCardStats(BuildCard("card", 3, 4));
+ NiceMock<MockService> remote;
+
+ EXPECT_CALL(local, UpdateAddressStats(_)).Times(0);
+ EXPECT_CALL(local, UpdateCardStats(_)).Times(0);
+ EXPECT_CALL(local,
+ SendChangesToSyncServer(UnorderedElementsAre(
+ SyncChangeAndDataMatch(
+ syncer::SyncChange::ACTION_ADD, "address-addr",
+ sync_pb::WalletMetadataSpecifics::ADDRESS, "addr", 1, 2),
+ SyncChangeAndDataMatch(
+ syncer::SyncChange::ACTION_ADD, "card-card",
+ sync_pb::WalletMetadataSpecifics::CARD, "card", 3, 4))));
+
+ MergeMetadata(&local, &remote);
+}
+
+// Verify that no data is written to disk or sent to the sync server if the
+// local and remote data are identical during the initial merge.
+TEST(AutofillWalletMetadataSyncableServiceTest, IgnoreIdenticalValuesOnMerge) {
+ NiceMock<MockService> local;
+ local.UpdateAddressStats(BuildAddress("addr", 1, 2));
+ local.UpdateCardStats(BuildCard("card", 3, 4));
+ NiceMock<MockService> remote;
+ remote.UpdateAddressStats(BuildAddress("addr", 1, 2));
+ remote.UpdateCardStats(BuildCard("card", 3, 4));
+
+ EXPECT_CALL(local, UpdateAddressStats(_)).Times(0);
+ EXPECT_CALL(local, UpdateCardStats(_)).Times(0);
+ EXPECT_CALL(local, SendChangesToSyncServer(_)).Times(0);
+
+ MergeMetadata(&local, &remote);
+}
+
+MATCHER_P3(AutofillMetadataMatches, server_id, use_count, use_date, "") {
+ 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 remote data with higher values of use count and last use date is
+// saved to disk during the initial merge.
+TEST(AutofillWalletMetadataSyncableServiceTest,
+ SaveHigherValuesLocallyOnMerge) {
+ NiceMock<MockService> local;
+ local.UpdateAddressStats(BuildAddress("addr", 1, 2));
+ local.UpdateCardStats(BuildCard("card", 3, 4));
+ NiceMock<MockService> remote;
+ remote.UpdateAddressStats(BuildAddress("addr", 10, 20));
+ remote.UpdateCardStats(BuildCard("card", 30, 40));
+
+ EXPECT_CALL(local,
+ UpdateAddressStats(AutofillMetadataMatches("addr", 10, 20)));
+ EXPECT_CALL(local, UpdateCardStats(AutofillMetadataMatches("card", 30, 40)));
+ EXPECT_CALL(local, SendChangesToSyncServer(_)).Times(0);
+
+ MergeMetadata(&local, &remote);
+}
+
+// Verify that local data with higher values of use count and last use date is
+// sent to the sync server during the initial merge.
+TEST(AutofillWalletMetadataSyncableServiceTest,
+ SendHigherValuesToServerOnMerge) {
+ NiceMock<MockService> local;
+ local.UpdateAddressStats(BuildAddress("addr", 10, 20));
+ local.UpdateCardStats(BuildCard("card", 30, 40));
+ NiceMock<MockService> remote;
+ remote.UpdateAddressStats(BuildAddress("addr", 1, 2));
+ remote.UpdateCardStats(BuildCard("card", 3, 4));
+
+ EXPECT_CALL(local, UpdateAddressStats(_)).Times(0);
+ EXPECT_CALL(local, UpdateCardStats(_)).Times(0);
+ EXPECT_CALL(
+ local, SendChangesToSyncServer(UnorderedElementsAre(
+ SyncChangeAndDataMatch(
+ syncer::SyncChange::ACTION_UPDATE, "address-addr",
+ sync_pb::WalletMetadataSpecifics::ADDRESS, "addr", 10, 20),
+ SyncChangeAndDataMatch(
+ syncer::SyncChange::ACTION_UPDATE, "card-card",
+ sync_pb::WalletMetadataSpecifics::CARD, "card", 30, 40))));
+
+ MergeMetadata(&local, &remote);
+}
+
+// Verify that lower values of metadata are not sent to the sync server when
+// local metadata is updated.
+TEST(AutofillWalletMetadataSyncableServiceTest,
+ DontSendLowerValueToServerOnSingleChange) {
+ NiceMock<MockService> local;
+ local.UpdateAddressStats(BuildAddress("addr", 1, 2));
+ local.UpdateCardStats(BuildCard("card", 3, 4));
+ NiceMock<MockService> remote;
+ remote.UpdateAddressStats(BuildAddress("addr", 1, 2));
+ remote.UpdateCardStats(BuildCard("card", 3, 4));
+ MergeMetadata(&local, &remote);
+ AutofillProfile address = BuildAddress("addr", 0, 0);
+ CreditCard card = BuildCard("card", 0, 0);
+
+ EXPECT_CALL(local, SendChangesToSyncServer(_)).Times(0);
+
+ local.AutofillProfileChanged(AutofillProfileChange(
+ AutofillProfileChange::UPDATE, address.guid(), &address));
+ local.CreditCardChanged(
+ CreditCardChange(CreditCardChange::UPDATE, card.guid(), &card));
+}
+
+// Verify that higher values of metadata are sent to the sync server when local
+// metadata is updated.
+TEST(AutofillWalletMetadataSyncableServiceTest,
+ SendHigherValuesToServerOnLocalSingleChange) {
+ NiceMock<MockService> local;
+ local.UpdateAddressStats(BuildAddress("addr", 1, 2));
+ local.UpdateCardStats(BuildCard("card", 3, 4));
+ NiceMock<MockService> remote;
+ remote.UpdateAddressStats(BuildAddress("addr", 1, 2));
+ remote.UpdateCardStats(BuildCard("card", 3, 4));
+ MergeMetadata(&local, &remote);
+ AutofillProfile address = BuildAddress("addr", 10, 20);
+ CreditCard card = BuildCard("card", 30, 40);
+
+ EXPECT_CALL(local,
+ SendChangesToSyncServer(ElementsAre(SyncChangeAndDataMatch(
+ syncer::SyncChange::ACTION_UPDATE, "address-addr",
+ sync_pb::WalletMetadataSpecifics::ADDRESS, "addr", 10, 20))));
+ EXPECT_CALL(local,
+ SendChangesToSyncServer(ElementsAre(SyncChangeAndDataMatch(
+ syncer::SyncChange::ACTION_UPDATE, "card-card",
+ sync_pb::WalletMetadataSpecifics::CARD, "card", 30, 40))));
+
+ local.AutofillProfileChanged(AutofillProfileChange(
+ AutofillProfileChange::UPDATE, address.guid(), &address));
+ local.CreditCardChanged(
+ CreditCardChange(CreditCardChange::UPDATE, card.guid(), &card));
+}
+
+// Verify that one-off addition of metadata is not sent to the sync
+// server. Metadata add and delete trigger multiple changes notification
+// instead.
+TEST(AutofillWalletMetadataSyncableServiceTest, DontAddToServerOnSingleChange) {
+ NiceMock<MockService> local;
+ local.UpdateAddressStats(BuildAddress("addr", 1, 2));
+ local.UpdateCardStats(BuildCard("card", 3, 4));
+ NiceMock<MockService> remote;
+ remote.UpdateAddressStats(BuildAddress("addr", 1, 2));
+ remote.UpdateCardStats(BuildCard("card", 3, 4));
+ MergeMetadata(&local, &remote);
+ AutofillProfile address = BuildAddress("new-addr", 5, 6);
+ CreditCard card = BuildCard("new-card", 7, 8);
+
+ EXPECT_CALL(local, SendChangesToSyncServer(_)).Times(0);
+
+ local.AutofillProfileChanged(AutofillProfileChange(
+ AutofillProfileChange::UPDATE, address.guid(), &address));
+ local.CreditCardChanged(
+ CreditCardChange(CreditCardChange::UPDATE, card.guid(), &card));
+}
+
+// Verify that new metadata is sent to the sync server when multiple metadata
+// values change at once.
+TEST(AutofillWalletMetadataSyncableServiceTest, AddToServerOnMultiChange) {
+ NiceMock<MockService> local;
+ local.UpdateAddressStats(BuildAddress("addr", 1, 2));
+ local.UpdateCardStats(BuildCard("card", 3, 4));
+ NiceMock<MockService> remote;
+ remote.UpdateAddressStats(BuildAddress("addr", 1, 2));
+ remote.UpdateCardStats(BuildCard("card", 3, 4));
+ MergeMetadata(&local, &remote);
+ // These methods do not trigger notifications or sync:
+ local.UpdateAddressStats(BuildAddress("new-addr", 5, 6));
+ local.UpdateCardStats(BuildCard("new-card", 7, 8));
+
+ EXPECT_CALL(
+ local,
+ SendChangesToSyncServer(UnorderedElementsAre(
+ SyncChangeAndDataMatch(
+ syncer::SyncChange::ACTION_ADD, "address-new-addr",
+ sync_pb::WalletMetadataSpecifics::ADDRESS, "new-addr", 5, 6),
+ SyncChangeAndDataMatch(
+ syncer::SyncChange::ACTION_ADD, "card-new-card",
+ sync_pb::WalletMetadataSpecifics::CARD, "new-card", 7, 8))));
+
+ local.AutofillMultipleChanged();
+}
+
+// Verify that higher values of existing metadata are sent to the sync server
+// when multiple metadata values change at once.
+TEST(AutofillWalletMetadataSyncableServiceTest,
+ UpdateToHigherValueOnServerOnMultiChange) {
+ NiceMock<MockService> local;
+ local.UpdateAddressStats(BuildAddress("addr", 1, 2));
+ local.UpdateCardStats(BuildCard("card", 3, 4));
+ NiceMock<MockService> remote;
+ remote.UpdateAddressStats(BuildAddress("addr", 1, 2));
+ remote.UpdateCardStats(BuildCard("card", 3, 4));
+ MergeMetadata(&local, &remote);
+ // These methods do not trigger notifications or sync:
+ local.UpdateAddressStats(BuildAddress("addr", 5, 6));
+ local.UpdateCardStats(BuildCard("card", 7, 8));
+
+ EXPECT_CALL(local,
+ SendChangesToSyncServer(UnorderedElementsAre(
+ SyncChangeAndDataMatch(
+ syncer::SyncChange::ACTION_UPDATE, "address-addr",
+ sync_pb::WalletMetadataSpecifics::ADDRESS, "addr", 5, 6),
+ SyncChangeAndDataMatch(
+ syncer::SyncChange::ACTION_UPDATE, "card-card",
+ sync_pb::WalletMetadataSpecifics::CARD, "card", 7, 8))));
+
+ local.AutofillMultipleChanged();
+}
+
+// Verify that lower values of existing metadata are not sent to the sync server
+// when multiple metadata values change at once.
+TEST(AutofillWalletMetadataSyncableServiceTest,
+ DontUpdateToLowerValueOnServerOnMultiChange) {
+ NiceMock<MockService> local;
+ local.UpdateAddressStats(BuildAddress("addr", 1, 2));
+ local.UpdateCardStats(BuildCard("card", 3, 4));
+ NiceMock<MockService> remote;
+ remote.UpdateAddressStats(BuildAddress("addr", 1, 2));
+ remote.UpdateCardStats(BuildCard("card", 3, 4));
+ MergeMetadata(&local, &remote);
+ // These methods do not trigger notifications or sync:
+ local.UpdateAddressStats(BuildAddress("addr", 0, 0));
+ local.UpdateCardStats(BuildCard("card", 0, 0));
+
+ EXPECT_CALL(local, SendChangesToSyncServer(_)).Times(0);
+
+ local.AutofillMultipleChanged();
+}
+
+// Verify that erased local metadata is also erased from the sync server when
+// multiple metadata values change at once.
+TEST(AutofillWalletMetadataSyncableServiceTest, DeleteFromServerOnMultiChange) {
+ NiceMock<MockService> local;
+ local.UpdateAddressStats(BuildAddress("addr", 1, 2));
+ local.UpdateCardStats(BuildCard("card", 3, 4));
+ NiceMock<MockService> remote;
+ remote.UpdateAddressStats(BuildAddress("addr", 1, 2));
+ remote.UpdateCardStats(BuildCard("card", 3, 4));
+ MergeMetadata(&local, &remote);
+ // This method dooes not trigger notifications or sync:
+ local.ClearServerData();
+
+ EXPECT_CALL(
+ local,
+ SendChangesToSyncServer(UnorderedElementsAre(
+ SyncChangeMatches(syncer::SyncChange::ACTION_DELETE, "address-addr"),
+ SyncChangeMatches(syncer::SyncChange::ACTION_DELETE, "card-card"))));
+
+ local.AutofillMultipleChanged();
+}
+
+// Verify that empty sync change from the sync server does not trigger writing
+// to disk or sending any data to the sync server.
+TEST(AutofillWalletMetadataSyncableServiceTest, EmptySyncChange) {
+ NiceMock<MockService> local;
+ local.UpdateAddressStats(BuildAddress("addr", 1, 2));
+ local.UpdateCardStats(BuildCard("card", 3, 4));
+ NiceMock<MockService> remote;
+ remote.UpdateAddressStats(BuildAddress("addr", 1, 2));
+ remote.UpdateCardStats(BuildCard("card", 3, 4));
+ MergeMetadata(&local, &remote);
+
+ EXPECT_CALL(local, UpdateAddressStats(_)).Times(0);
+ EXPECT_CALL(local, UpdateCardStats(_)).Times(0);
+ EXPECT_CALL(local, SendChangesToSyncServer(_)).Times(0);
+
+ local.ProcessSyncChanges(FROM_HERE, syncer::SyncChangeList());
+}
+
+syncer::SyncChange BuildChange(
+ syncer::SyncChange::SyncChangeType change_type,
+ const std::string& sync_tag,
+ 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(sync_tag, sync_tag, entity));
+}
+
+// Verify that new metadata from the sync server is ignored when processing
+// on-going sync changes. There should be no disk writes or messages to the sync
+// server.
+TEST(AutofillWalletMetadataSyncableServiceTest,
+ IgnoreNewMetadataFromServerOnSyncChange) {
+ NiceMock<MockService> local;
+ local.UpdateAddressStats(BuildAddress("addr", 1, 2));
+ local.UpdateCardStats(BuildCard("card", 3, 4));
+ NiceMock<MockService> remote;
+ remote.UpdateAddressStats(BuildAddress("addr", 1, 2));
+ remote.UpdateCardStats(BuildCard("card", 3, 4));
+ MergeMetadata(&local, &remote);
+ syncer::SyncChangeList changes;
+ changes.push_back(
+ BuildChange(syncer::SyncChange::ACTION_ADD, "address-new-addr",
+ sync_pb::WalletMetadataSpecifics::ADDRESS, "new-addr", 5, 6));
+ changes.push_back(BuildChange(syncer::SyncChange::ACTION_ADD, "card-new-card",
+ sync_pb::WalletMetadataSpecifics::CARD,
+ "new-card", 7, 8));
+
+ EXPECT_CALL(local, UpdateAddressStats(_)).Times(0);
+ EXPECT_CALL(local, UpdateCardStats(_)).Times(0);
+ EXPECT_CALL(local, SendChangesToSyncServer(_)).Times(0);
+
+ local.ProcessSyncChanges(FROM_HERE, changes);
+}
+
+// Verify that higher values of metadata from the sync server are saved to
+// disk when processing on-going sync changes.
+TEST(AutofillWalletMetadataSyncableServiceTest,
+ SaveHigherValuesFromServerOnSyncChange) {
+ NiceMock<MockService> local;
+ local.UpdateAddressStats(BuildAddress("addr", 1, 2));
+ local.UpdateCardStats(BuildCard("card", 3, 4));
+ NiceMock<MockService> remote;
+ remote.UpdateAddressStats(BuildAddress("addr", 1, 2));
+ remote.UpdateCardStats(BuildCard("card", 3, 4));
+ MergeMetadata(&local, &remote);
+ syncer::SyncChangeList changes;
+ changes.push_back(
+ BuildChange(syncer::SyncChange::ACTION_UPDATE, "address-addr",
+ sync_pb::WalletMetadataSpecifics::ADDRESS, "addr", 10, 20));
+ changes.push_back(BuildChange(syncer::SyncChange::ACTION_UPDATE, "card-card",
+ sync_pb::WalletMetadataSpecifics::CARD, "card",
+ 30, 40));
+
+ EXPECT_CALL(local,
+ UpdateAddressStats(AutofillMetadataMatches("addr", 10, 20)));
+ EXPECT_CALL(local, UpdateCardStats(AutofillMetadataMatches("card", 30, 40)));
+ EXPECT_CALL(local, SendChangesToSyncServer(_)).Times(0);
+
+ local.ProcessSyncChanges(FROM_HERE, changes);
+}
+
+// Verify that higher local values of metadata are sent to the sync server when
+// processing on-going sync changes.
+TEST(AutofillWalletMetadataSyncableServiceTest,
+ SendHigherValuesToServerOnSyncChange) {
+ NiceMock<MockService> local;
+ local.UpdateAddressStats(BuildAddress("addr", 1, 2));
+ local.UpdateCardStats(BuildCard("card", 3, 4));
+ NiceMock<MockService> remote;
+ remote.UpdateAddressStats(BuildAddress("addr", 1, 2));
+ remote.UpdateCardStats(BuildCard("card", 3, 4));
+ MergeMetadata(&local, &remote);
+ syncer::SyncChangeList changes;
+ changes.push_back(
+ BuildChange(syncer::SyncChange::ACTION_UPDATE, "address-addr",
+ sync_pb::WalletMetadataSpecifics::ADDRESS, "addr", 0, 0));
+ changes.push_back(BuildChange(syncer::SyncChange::ACTION_UPDATE, "card-card",
+ sync_pb::WalletMetadataSpecifics::CARD, "card",
+ 0, 0));
+
+ EXPECT_CALL(local, UpdateAddressStats(_)).Times(0);
+ EXPECT_CALL(local, UpdateCardStats(_)).Times(0);
+ EXPECT_CALL(local,
+ SendChangesToSyncServer(UnorderedElementsAre(
+ SyncChangeAndDataMatch(
+ syncer::SyncChange::ACTION_UPDATE, "address-addr",
+ sync_pb::WalletMetadataSpecifics::ADDRESS, "addr", 1, 2),
+ SyncChangeAndDataMatch(
+ syncer::SyncChange::ACTION_UPDATE, "card-card",
+ sync_pb::WalletMetadataSpecifics::CARD, "card", 3, 4))));
+
+ local.ProcessSyncChanges(FROM_HERE, changes);
+}
+
+// Verify that addition of known metadata is treated the same as an update.
+TEST(AutofillWalletMetadataSyncableServiceTest,
+ TreatAdditionOfKnownMetadataAsUpdateOnSyncChange) {
+ NiceMock<MockService> local;
+ local.UpdateAddressStats(BuildAddress("addr", 1, 2));
+ local.UpdateCardStats(BuildCard("card", 3, 4));
+ NiceMock<MockService> remote;
+ remote.UpdateAddressStats(BuildAddress("addr", 1, 2));
+ remote.UpdateCardStats(BuildCard("card", 3, 4));
+ MergeMetadata(&local, &remote);
+ syncer::SyncChangeList changes;
+ changes.push_back(BuildChange(syncer::SyncChange::ACTION_ADD, "address-addr",
+ sync_pb::WalletMetadataSpecifics::ADDRESS,
+ "addr", 0, 0));
+ changes.push_back(BuildChange(syncer::SyncChange::ACTION_ADD, "card-card",
+ sync_pb::WalletMetadataSpecifics::CARD, "card",
+ 0, 0));
+
+ EXPECT_CALL(local, UpdateAddressStats(_)).Times(0);
+ EXPECT_CALL(local, UpdateCardStats(_)).Times(0);
+ EXPECT_CALL(local,
+ SendChangesToSyncServer(UnorderedElementsAre(
+ SyncChangeAndDataMatch(
+ syncer::SyncChange::ACTION_UPDATE, "address-addr",
+ sync_pb::WalletMetadataSpecifics::ADDRESS, "addr", 1, 2),
+ SyncChangeAndDataMatch(
+ syncer::SyncChange::ACTION_UPDATE, "card-card",
+ sync_pb::WalletMetadataSpecifics::CARD, "card", 3, 4))));
+
+ local.ProcessSyncChanges(FROM_HERE, changes);
+}
+
+// Verify that an update of locally unknown metadata is ignored. There should be
+// no disk writes and no messages sent to the server.
+TEST(AutofillWalletMetadataSyncableServiceTest,
+ IgnoreUpdateOfUnknownMetadataOnSyncChange) {
+ NiceMock<MockService> local;
+ local.UpdateAddressStats(BuildAddress("addr", 1, 2));
+ local.UpdateCardStats(BuildCard("card", 3, 4));
+ NiceMock<MockService> remote;
+ remote.UpdateAddressStats(BuildAddress("addr", 1, 2));
+ remote.UpdateCardStats(BuildCard("card", 3, 4));
+ MergeMetadata(&local, &remote);
+ syncer::SyncChangeList changes;
+ changes.push_back(BuildChange(
+ syncer::SyncChange::ACTION_UPDATE, "address-unknown-addr",
+ sync_pb::WalletMetadataSpecifics::ADDRESS, "unknown-addr", 0, 0));
+ changes.push_back(BuildChange(
+ syncer::SyncChange::ACTION_UPDATE, "card-unknown-card",
+ sync_pb::WalletMetadataSpecifics::CARD, "unknown-card", 0, 0));
+
+ EXPECT_CALL(local, UpdateAddressStats(_)).Times(0);
+ EXPECT_CALL(local, UpdateCardStats(_)).Times(0);
+ EXPECT_CALL(local, SendChangesToSyncServer(_)).Times(0);
+
+ local.ProcessSyncChanges(FROM_HERE, changes);
+}
+
+// Verify that deletion from the sync server of locally unknown metadata is
+// ignored. There should be no disk writes and no messages sent to the server.
+TEST(AutofillWalletMetadataSyncableServiceTest,
+ IgnoreDeleteOfUnknownMetadataOnSyncChange) {
+ NiceMock<MockService> local;
+ local.UpdateAddressStats(BuildAddress("addr", 1, 2));
+ local.UpdateCardStats(BuildCard("card", 3, 4));
+ NiceMock<MockService> remote;
+ remote.UpdateAddressStats(BuildAddress("addr", 1, 2));
+ remote.UpdateCardStats(BuildCard("card", 3, 4));
+ MergeMetadata(&local, &remote);
+ syncer::SyncChangeList changes;
+ changes.push_back(BuildChange(
+ syncer::SyncChange::ACTION_DELETE, "address-unknown-addr",
+ sync_pb::WalletMetadataSpecifics::ADDRESS, "unknown-addr", 0, 0));
+ changes.push_back(BuildChange(
+ syncer::SyncChange::ACTION_DELETE, "card-unknown-card",
+ sync_pb::WalletMetadataSpecifics::CARD, "unknown-card", 0, 0));
+
+ EXPECT_CALL(local, UpdateAddressStats(_)).Times(0);
+ EXPECT_CALL(local, UpdateCardStats(_)).Times(0);
+ EXPECT_CALL(local, SendChangesToSyncServer(_)).Times(0);
+
+ local.ProcessSyncChanges(FROM_HERE, changes);
+}
+
+// Verify that deletion from the sync server of locally existing metadata will
+// trigger an undelete message sent to the server.
+TEST(AutofillWalletMetadataSyncableServiceTest,
+ UndeleteExistingMetadataOnSyncChange) {
+ NiceMock<MockService> local;
+ local.UpdateAddressStats(BuildAddress("addr", 1, 2));
+ local.UpdateCardStats(BuildCard("card", 3, 4));
+ NiceMock<MockService> remote;
+ remote.UpdateAddressStats(BuildAddress("addr", 1, 2));
+ remote.UpdateCardStats(BuildCard("card", 3, 4));
+ MergeMetadata(&local, &remote);
+ syncer::SyncChangeList changes;
+ changes.push_back(
+ BuildChange(syncer::SyncChange::ACTION_DELETE, "address-addr",
+ sync_pb::WalletMetadataSpecifics::ADDRESS, "addr", 0, 0));
+ changes.push_back(BuildChange(syncer::SyncChange::ACTION_DELETE, "card-card",
+ sync_pb::WalletMetadataSpecifics::CARD, "card",
+ 0, 0));
+
+ EXPECT_CALL(local, UpdateAddressStats(_)).Times(0);
+ EXPECT_CALL(local, UpdateCardStats(_)).Times(0);
+ EXPECT_CALL(local,
+ SendChangesToSyncServer(UnorderedElementsAre(
+ SyncChangeAndDataMatch(
+ syncer::SyncChange::ACTION_ADD, "address-addr",
+ sync_pb::WalletMetadataSpecifics::ADDRESS, "addr", 1, 2),
+ SyncChangeAndDataMatch(
+ syncer::SyncChange::ACTION_ADD, "card-card",
+ sync_pb::WalletMetadataSpecifics::CARD, "card", 3, 4))));
+
+ local.ProcessSyncChanges(FROM_HERE, changes);
+}
+
+// Verify that processing sync changes maintains the local cache of sync server
+// data, which is used to avoid calling the expensive GetAllSyncData() function.
+TEST(AutofillWalletMetadataSyncableServiceTest,
+ CacheIsUpToDateAfterSyncChange) {
+ NiceMock<MockService> local;
+ local.UpdateAddressStats(BuildAddress("addr1", 1, 2));
+ local.UpdateAddressStats(BuildAddress("addr2", 3, 4));
+ local.UpdateCardStats(BuildCard("card1", 5, 6));
+ local.UpdateCardStats(BuildCard("card2", 7, 8));
+ NiceMock<MockService> remote;
+ remote.UpdateAddressStats(BuildAddress("addr1", 1, 2));
+ remote.UpdateAddressStats(BuildAddress("addr2", 3, 4));
+ remote.UpdateCardStats(BuildCard("card1", 5, 6));
+ remote.UpdateCardStats(BuildCard("card2", 7, 8));
+ MergeMetadata(&local, &remote);
+ syncer::SyncChangeList changes;
+ changes.push_back(
+ BuildChange(syncer::SyncChange::ACTION_UPDATE, "address-addr1",
+ sync_pb::WalletMetadataSpecifics::ADDRESS, "addr1", 10, 20));
+ changes.push_back(BuildChange(syncer::SyncChange::ACTION_UPDATE, "card-card1",
+ sync_pb::WalletMetadataSpecifics::CARD, "card1",
+ 50, 60));
+ local.ProcessSyncChanges(FROM_HERE, changes);
+ // This method dooes not trigger notifications or sync:
+ local.ClearServerData();
+
+ EXPECT_CALL(
+ local,
+ SendChangesToSyncServer(UnorderedElementsAre(
+ SyncChangeMatches(syncer::SyncChange::ACTION_DELETE, "address-addr1"),
+ SyncChangeMatches(syncer::SyncChange::ACTION_DELETE, "address-addr2"),
+ SyncChangeMatches(syncer::SyncChange::ACTION_DELETE, "card-card1"),
+ SyncChangeMatches(syncer::SyncChange::ACTION_DELETE, "card-card2"))));
+
+ local.AutofillMultipleChanged();
+}
+
+} // namespace
+} // namespace autofill

Powered by Google App Engine
This is Rietveld 408576698