123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460 |
- // Copyright 2014 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/sync/engine/get_updates_processor.h"
- #include <stdint.h>
- #include <memory>
- #include <set>
- #include <string>
- #include <utility>
- #include "base/memory/raw_ptr.h"
- #include "base/time/time.h"
- #include "components/sync/base/model_type_test_util.h"
- #include "components/sync/engine/cycle/debug_info_getter.h"
- #include "components/sync/engine/cycle/mock_debug_info_getter.h"
- #include "components/sync/engine/cycle/nudge_tracker.h"
- #include "components/sync/engine/cycle/status_controller.h"
- #include "components/sync/engine/get_updates_delegate.h"
- #include "components/sync/engine/update_handler.h"
- #include "components/sync/protocol/data_type_progress_marker.pb.h"
- #include "components/sync/test/mock_invalidation.h"
- #include "components/sync/test/mock_update_handler.h"
- #include "testing/gtest/include/gtest/gtest.h"
- namespace syncer {
- namespace {
- std::unique_ptr<SyncInvalidation> BuildInvalidation(
- int64_t version,
- const std::string& payload) {
- return MockInvalidation::Build(version, payload);
- }
- } // namespace
- // A test fixture for tests exercising download updates functions.
- class GetUpdatesProcessorTest : public ::testing::Test {
- public:
- GetUpdatesProcessorTest() = default;
- GetUpdatesProcessorTest(const GetUpdatesProcessorTest&) = delete;
- GetUpdatesProcessorTest& operator=(const GetUpdatesProcessorTest&) = delete;
- void SetUp() override {
- AddUpdateHandler(AUTOFILL);
- AddUpdateHandler(BOOKMARKS);
- AddUpdateHandler(PREFERENCES);
- }
- ModelTypeSet enabled_types() { return enabled_types_; }
- std::unique_ptr<GetUpdatesProcessor> BuildGetUpdatesProcessor(
- const GetUpdatesDelegate& delegate) {
- return std::make_unique<GetUpdatesProcessor>(&update_handler_map_,
- delegate);
- }
- void InitFakeUpdateResponse(sync_pb::GetUpdatesResponse* response) {
- ModelTypeSet types = enabled_types();
- for (ModelType type : types) {
- sync_pb::DataTypeProgressMarker* marker =
- response->add_new_progress_marker();
- marker->set_data_type_id(GetSpecificsFieldNumberFromModelType(type));
- marker->set_token("foobarbaz");
- sync_pb::DataTypeContext* context = response->add_context_mutations();
- context->set_data_type_id(GetSpecificsFieldNumberFromModelType(type));
- context->set_version(1);
- context->set_context("context");
- }
- response->set_changes_remaining(0);
- }
- MockUpdateHandler* AddUpdateHandler(ModelType type) {
- enabled_types_.Put(type);
- std::unique_ptr<MockUpdateHandler> handler =
- std::make_unique<MockUpdateHandler>(type);
- MockUpdateHandler* handler_ptr = handler.get();
- update_handler_map_.insert(std::make_pair(type, handler_ptr));
- update_handlers_.insert(std::move(handler));
- return handler_ptr;
- }
- const base::TimeTicks kTestStartTime = base::TimeTicks::Now();
- private:
- ModelTypeSet enabled_types_;
- std::set<std::unique_ptr<MockUpdateHandler>> update_handlers_;
- UpdateHandlerMap update_handler_map_;
- std::unique_ptr<GetUpdatesProcessor> get_updates_processor_;
- };
- // Basic test to make sure nudges are expressed properly in the request.
- TEST_F(GetUpdatesProcessorTest, BookmarkNudge) {
- NudgeTracker nudge_tracker;
- nudge_tracker.RecordLocalChange(BOOKMARKS);
- sync_pb::ClientToServerMessage message;
- NormalGetUpdatesDelegate normal_delegate(nudge_tracker);
- std::unique_ptr<GetUpdatesProcessor> processor(
- BuildGetUpdatesProcessor(normal_delegate));
- processor->PrepareGetUpdates(enabled_types(), &message);
- const sync_pb::GetUpdatesMessage& gu_msg = message.get_updates();
- EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::UNKNOWN,
- gu_msg.caller_info().source());
- EXPECT_EQ(sync_pb::SyncEnums::GU_TRIGGER, gu_msg.get_updates_origin());
- for (int i = 0; i < gu_msg.from_progress_marker_size(); ++i) {
- ModelType type = GetModelTypeFromSpecificsFieldNumber(
- gu_msg.from_progress_marker(i).data_type_id());
- const sync_pb::DataTypeProgressMarker& progress_marker =
- gu_msg.from_progress_marker(i);
- const sync_pb::GetUpdateTriggers& gu_trigger =
- progress_marker.get_update_triggers();
- // We perform some basic tests of GU trigger and source fields here. The
- // more complicated scenarios are tested by the NudgeTracker tests.
- if (type == BOOKMARKS) {
- EXPECT_EQ(1, gu_trigger.local_modification_nudges());
- EXPECT_EQ(0, gu_trigger.datatype_refresh_nudges());
- } else {
- EXPECT_EQ(0, gu_trigger.local_modification_nudges());
- EXPECT_EQ(0, gu_trigger.datatype_refresh_nudges());
- }
- }
- }
- // Basic test to ensure invalidation payloads are expressed in the request.
- TEST_F(GetUpdatesProcessorTest, NotifyMany) {
- NudgeTracker nudge_tracker;
- nudge_tracker.RecordRemoteInvalidation(
- AUTOFILL, BuildInvalidation(1, "autofill_payload"));
- nudge_tracker.RecordRemoteInvalidation(
- BOOKMARKS, BuildInvalidation(1, "bookmark_payload"));
- nudge_tracker.RecordRemoteInvalidation(
- PREFERENCES, BuildInvalidation(1, "preferences_payload"));
- ModelTypeSet notified_types;
- notified_types.Put(AUTOFILL);
- notified_types.Put(BOOKMARKS);
- notified_types.Put(PREFERENCES);
- sync_pb::ClientToServerMessage message;
- NormalGetUpdatesDelegate normal_delegate(nudge_tracker);
- std::unique_ptr<GetUpdatesProcessor> processor(
- BuildGetUpdatesProcessor(normal_delegate));
- processor->PrepareGetUpdates(enabled_types(), &message);
- const sync_pb::GetUpdatesMessage& gu_msg = message.get_updates();
- EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::UNKNOWN,
- gu_msg.caller_info().source());
- EXPECT_EQ(sync_pb::SyncEnums::GU_TRIGGER, gu_msg.get_updates_origin());
- for (int i = 0; i < gu_msg.from_progress_marker_size(); ++i) {
- ModelType type = GetModelTypeFromSpecificsFieldNumber(
- gu_msg.from_progress_marker(i).data_type_id());
- const sync_pb::DataTypeProgressMarker& progress_marker =
- gu_msg.from_progress_marker(i);
- const sync_pb::GetUpdateTriggers& gu_trigger =
- progress_marker.get_update_triggers();
- // We perform some basic tests of GU trigger and source fields here. The
- // more complicated scenarios are tested by the NudgeTracker tests.
- if (notified_types.Has(type)) {
- EXPECT_EQ(1, gu_trigger.notification_hint_size());
- } else {
- EXPECT_EQ(0, gu_trigger.notification_hint_size());
- }
- }
- }
- // Basic test to ensure initial sync requests are expressed in the request.
- TEST_F(GetUpdatesProcessorTest, InitialSyncRequest) {
- NudgeTracker nudge_tracker;
- nudge_tracker.RecordInitialSyncRequired(AUTOFILL);
- nudge_tracker.RecordInitialSyncRequired(PREFERENCES);
- ModelTypeSet initial_sync_types = ModelTypeSet(AUTOFILL, PREFERENCES);
- sync_pb::ClientToServerMessage message;
- NormalGetUpdatesDelegate normal_delegate(nudge_tracker);
- std::unique_ptr<GetUpdatesProcessor> processor(
- BuildGetUpdatesProcessor(normal_delegate));
- processor->PrepareGetUpdates(enabled_types(), &message);
- const sync_pb::GetUpdatesMessage& gu_msg = message.get_updates();
- EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::UNKNOWN,
- gu_msg.caller_info().source());
- EXPECT_EQ(sync_pb::SyncEnums::GU_TRIGGER, gu_msg.get_updates_origin());
- for (int i = 0; i < gu_msg.from_progress_marker_size(); ++i) {
- ModelType type = GetModelTypeFromSpecificsFieldNumber(
- gu_msg.from_progress_marker(i).data_type_id());
- const sync_pb::DataTypeProgressMarker& progress_marker =
- gu_msg.from_progress_marker(i);
- const sync_pb::GetUpdateTriggers& gu_trigger =
- progress_marker.get_update_triggers();
- // We perform some basic tests of GU trigger and source fields here. The
- // more complicated scenarios are tested by the NudgeTracker tests.
- if (initial_sync_types.Has(type)) {
- EXPECT_TRUE(gu_trigger.initial_sync_in_progress());
- } else {
- EXPECT_TRUE(gu_trigger.has_initial_sync_in_progress());
- EXPECT_FALSE(gu_trigger.initial_sync_in_progress());
- }
- }
- }
- TEST_F(GetUpdatesProcessorTest, ConfigureTest) {
- sync_pb::ClientToServerMessage message;
- ConfigureGetUpdatesDelegate configure_delegate(
- sync_pb::SyncEnums::RECONFIGURATION);
- std::unique_ptr<GetUpdatesProcessor> processor(
- BuildGetUpdatesProcessor(configure_delegate));
- processor->PrepareGetUpdates(enabled_types(), &message);
- const sync_pb::GetUpdatesMessage& gu_msg = message.get_updates();
- EXPECT_EQ(sync_pb::SyncEnums::RECONFIGURATION, gu_msg.get_updates_origin());
- EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::UNKNOWN,
- gu_msg.caller_info().source());
- ModelTypeSet progress_types;
- for (int i = 0; i < gu_msg.from_progress_marker_size(); ++i) {
- ModelType type = GetModelTypeFromSpecificsFieldNumber(
- gu_msg.from_progress_marker(i).data_type_id());
- progress_types.Put(type);
- }
- EXPECT_EQ(enabled_types(), progress_types);
- }
- TEST_F(GetUpdatesProcessorTest, PollTest) {
- sync_pb::ClientToServerMessage message;
- PollGetUpdatesDelegate poll_delegate;
- std::unique_ptr<GetUpdatesProcessor> processor(
- BuildGetUpdatesProcessor(poll_delegate));
- processor->PrepareGetUpdates(enabled_types(), &message);
- const sync_pb::GetUpdatesMessage& gu_msg = message.get_updates();
- EXPECT_EQ(sync_pb::SyncEnums::PERIODIC, gu_msg.get_updates_origin());
- EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::UNKNOWN,
- gu_msg.caller_info().source());
- ModelTypeSet progress_types;
- for (int i = 0; i < gu_msg.from_progress_marker_size(); ++i) {
- ModelType type = GetModelTypeFromSpecificsFieldNumber(
- gu_msg.from_progress_marker(i).data_type_id());
- progress_types.Put(type);
- }
- EXPECT_EQ(enabled_types(), progress_types);
- }
- TEST_F(GetUpdatesProcessorTest, RetryTest) {
- NudgeTracker nudge_tracker;
- // Schedule a retry.
- base::TimeTicks t1 = kTestStartTime;
- nudge_tracker.SetNextRetryTime(t1);
- // Get the nudge tracker to think the retry is due.
- nudge_tracker.SetSyncCycleStartTime(t1 + base::Seconds(1));
- sync_pb::ClientToServerMessage message;
- NormalGetUpdatesDelegate normal_delegate(nudge_tracker);
- std::unique_ptr<GetUpdatesProcessor> processor(
- BuildGetUpdatesProcessor(normal_delegate));
- processor->PrepareGetUpdates(enabled_types(), &message);
- const sync_pb::GetUpdatesMessage& gu_msg = message.get_updates();
- EXPECT_EQ(sync_pb::SyncEnums::RETRY, gu_msg.get_updates_origin());
- EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::UNKNOWN,
- gu_msg.caller_info().source());
- EXPECT_TRUE(gu_msg.is_retry());
- ModelTypeSet progress_types;
- for (int i = 0; i < gu_msg.from_progress_marker_size(); ++i) {
- ModelType type = GetModelTypeFromSpecificsFieldNumber(
- gu_msg.from_progress_marker(i).data_type_id());
- progress_types.Put(type);
- }
- EXPECT_EQ(enabled_types(), progress_types);
- }
- TEST_F(GetUpdatesProcessorTest, NudgeWithRetryTest) {
- NudgeTracker nudge_tracker;
- // Schedule a retry.
- base::TimeTicks t1 = kTestStartTime;
- nudge_tracker.SetNextRetryTime(t1);
- // Get the nudge tracker to think the retry is due.
- nudge_tracker.SetSyncCycleStartTime(t1 + base::Seconds(1));
- // Record a local change, too.
- nudge_tracker.RecordLocalChange(BOOKMARKS);
- sync_pb::ClientToServerMessage message;
- NormalGetUpdatesDelegate normal_delegate(nudge_tracker);
- std::unique_ptr<GetUpdatesProcessor> processor(
- BuildGetUpdatesProcessor(normal_delegate));
- processor->PrepareGetUpdates(enabled_types(), &message);
- const sync_pb::GetUpdatesMessage& gu_msg = message.get_updates();
- EXPECT_NE(sync_pb::SyncEnums::RETRY, gu_msg.get_updates_origin());
- EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::UNKNOWN,
- gu_msg.caller_info().source());
- EXPECT_TRUE(gu_msg.is_retry());
- }
- // Verify that a bogus response message is detected.
- TEST_F(GetUpdatesProcessorTest, InvalidResponse) {
- sync_pb::GetUpdatesResponse gu_response;
- InitFakeUpdateResponse(&gu_response);
- // This field is essential for making the client stop looping. If it's unset
- // then something is very wrong. The client should detect this.
- gu_response.clear_changes_remaining();
- NudgeTracker nudge_tracker;
- NormalGetUpdatesDelegate normal_delegate(nudge_tracker);
- StatusController status;
- std::unique_ptr<GetUpdatesProcessor> processor(
- BuildGetUpdatesProcessor(normal_delegate));
- SyncerError error =
- processor->ProcessResponse(gu_response, enabled_types(), &status);
- EXPECT_EQ(error.value(), SyncerError::SERVER_RESPONSE_VALIDATION_FAILED);
- }
- // Verify that we correctly detect when there's more work to be done.
- TEST_F(GetUpdatesProcessorTest, MoreToDownloadResponse) {
- sync_pb::GetUpdatesResponse gu_response;
- InitFakeUpdateResponse(&gu_response);
- gu_response.set_changes_remaining(1);
- NudgeTracker nudge_tracker;
- NormalGetUpdatesDelegate normal_delegate(nudge_tracker);
- StatusController status;
- std::unique_ptr<GetUpdatesProcessor> processor(
- BuildGetUpdatesProcessor(normal_delegate));
- SyncerError error =
- processor->ProcessResponse(gu_response, enabled_types(), &status);
- EXPECT_EQ(error.value(), SyncerError::SERVER_MORE_TO_DOWNLOAD);
- }
- // A simple scenario: No updates returned and nothing more to download.
- TEST_F(GetUpdatesProcessorTest, NormalResponseTest) {
- sync_pb::GetUpdatesResponse gu_response;
- InitFakeUpdateResponse(&gu_response);
- gu_response.set_changes_remaining(0);
- NudgeTracker nudge_tracker;
- NormalGetUpdatesDelegate normal_delegate(nudge_tracker);
- StatusController status;
- std::unique_ptr<GetUpdatesProcessor> processor(
- BuildGetUpdatesProcessor(normal_delegate));
- SyncerError error =
- processor->ProcessResponse(gu_response, enabled_types(), &status);
- EXPECT_EQ(error.value(), SyncerError::SYNCER_OK);
- }
- // Variant of GetUpdatesProcessor test designed to test update application.
- //
- // Maintains two enabled types, but requests that updates be applied for only
- // one of them.
- class GetUpdatesProcessorApplyUpdatesTest : public GetUpdatesProcessorTest {
- public:
- GetUpdatesProcessorApplyUpdatesTest() = default;
- ~GetUpdatesProcessorApplyUpdatesTest() override = default;
- void SetUp() override {
- bookmarks_handler_ = AddUpdateHandler(BOOKMARKS);
- autofill_handler_ = AddUpdateHandler(AUTOFILL);
- }
- ModelTypeSet GetGuTypes() { return ModelTypeSet(AUTOFILL); }
- MockUpdateHandler* GetNonAppliedHandler() { return bookmarks_handler_; }
- MockUpdateHandler* GetAppliedHandler() { return autofill_handler_; }
- private:
- raw_ptr<MockUpdateHandler> bookmarks_handler_;
- raw_ptr<MockUpdateHandler> autofill_handler_;
- };
- // Verify that a normal cycle applies updates to the specified types.
- TEST_F(GetUpdatesProcessorApplyUpdatesTest, Normal) {
- NudgeTracker nudge_tracker;
- NormalGetUpdatesDelegate normal_delegate(nudge_tracker);
- std::unique_ptr<GetUpdatesProcessor> processor(
- BuildGetUpdatesProcessor(normal_delegate));
- EXPECT_EQ(0, GetNonAppliedHandler()->GetApplyUpdatesCount());
- EXPECT_EQ(0, GetAppliedHandler()->GetApplyUpdatesCount());
- StatusController status;
- processor->ApplyUpdates(GetGuTypes(), &status);
- EXPECT_EQ(0, GetNonAppliedHandler()->GetApplyUpdatesCount());
- EXPECT_EQ(1, GetAppliedHandler()->GetApplyUpdatesCount());
- }
- // Verify that a configure cycle applies updates to the specified types.
- TEST_F(GetUpdatesProcessorApplyUpdatesTest, Configure) {
- ConfigureGetUpdatesDelegate configure_delegate(
- sync_pb::SyncEnums::RECONFIGURATION);
- std::unique_ptr<GetUpdatesProcessor> processor(
- BuildGetUpdatesProcessor(configure_delegate));
- EXPECT_EQ(0, GetNonAppliedHandler()->GetApplyUpdatesCount());
- EXPECT_EQ(0, GetAppliedHandler()->GetApplyUpdatesCount());
- StatusController status;
- processor->ApplyUpdates(GetGuTypes(), &status);
- EXPECT_EQ(0, GetNonAppliedHandler()->GetApplyUpdatesCount());
- EXPECT_EQ(1, GetAppliedHandler()->GetApplyUpdatesCount());
- }
- // Verify that a poll cycle applies updates to the specified types.
- TEST_F(GetUpdatesProcessorApplyUpdatesTest, Poll) {
- PollGetUpdatesDelegate poll_delegate;
- std::unique_ptr<GetUpdatesProcessor> processor(
- BuildGetUpdatesProcessor(poll_delegate));
- EXPECT_EQ(0, GetNonAppliedHandler()->GetApplyUpdatesCount());
- EXPECT_EQ(0, GetAppliedHandler()->GetApplyUpdatesCount());
- StatusController status;
- processor->ApplyUpdates(GetGuTypes(), &status);
- EXPECT_EQ(0, GetNonAppliedHandler()->GetApplyUpdatesCount());
- EXPECT_EQ(1, GetAppliedHandler()->GetApplyUpdatesCount());
- }
- class DownloadUpdatesDebugInfoTest : public ::testing::Test {
- public:
- DownloadUpdatesDebugInfoTest() = default;
- ~DownloadUpdatesDebugInfoTest() override = default;
- StatusController* status() { return &status_; }
- DebugInfoGetter* debug_info_getter() { return &debug_info_getter_; }
- void AddDebugEvent() { debug_info_getter_.AddDebugEvent(); }
- private:
- StatusController status_;
- MockDebugInfoGetter debug_info_getter_;
- };
- } // namespace syncer
|