blob: 50fb5029015434bcf4e48f9143fa7e9ba3050b30 [file]
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/functional/bind.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "chrome/browser/sync/test/integration/bookmarks_helper.h"
#include "chrome/browser/sync/test/integration/exponential_backoff_helper.h"
#include "chrome/browser/sync/test/integration/sync_test.h"
#include "chrome/browser/sync/test/integration/updated_progress_marker_checker.h"
#include "components/browser_sync/browser_sync_switches.h"
#include "components/signin/public/base/signin_switches.h"
#include "components/sync/base/features.h"
#include "components/sync/engine/polling_constants.h"
#include "components/sync/service/sync_service_impl.h"
#include "content/public/test/browser_test.h"
#include "net/base/network_change_notifier.h"
namespace {
using bookmarks_helper::AddFolder;
using bookmarks_helper::ServerBookmarksEqualityChecker;
using exponential_backoff_helper::ExponentialBackoffChecker;
class SyncExponentialBackoffTest
: public SyncTest,
public testing::WithParamInterface<SyncTest::SetupSyncMode> {
public:
SyncExponentialBackoffTest() : SyncTest(SINGLE_CLIENT) {
if (GetSetupSyncMode() == SetupSyncMode::kSyncTransportOnly) {
scoped_feature_list_.InitWithFeatures(
{syncer::kReplaceSyncPromosWithSignInPromos,
switches::kSyncEnableBookmarksInTransportMode},
{});
}
}
SyncExponentialBackoffTest(const SyncExponentialBackoffTest&) = delete;
SyncExponentialBackoffTest& operator=(const SyncExponentialBackoffTest&) =
delete;
~SyncExponentialBackoffTest() override = default;
void SetUp() override {
// This is needed to avoid spurious notifications initiated by the platform.
net::NetworkChangeNotifier::SetTestNotificationsOnly(true);
SyncTest::SetUp();
}
SyncTest::SetupSyncMode GetSetupSyncMode() const override {
return GetParam();
}
bookmarks_helper::StoreType GetBookmarksStoreType() const {
return GetSetupSyncMode() == SyncTest::SetupSyncMode::kSyncTransportOnly
? bookmarks_helper::StoreType::kAccountStore
: bookmarks_helper::StoreType::kLocalOrSyncableStore;
}
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
INSTANTIATE_TEST_SUITE_P(,
SyncExponentialBackoffTest,
GetSyncTestModes(),
testing::PrintToStringParamName());
IN_PROC_BROWSER_TEST_P(SyncExponentialBackoffTest, OfflineToOnline) {
const std::u16string kFolderTitle1 = u"folder1";
const std::u16string kFolderTitle2 = u"folder2";
ASSERT_TRUE(SetupSync());
// Add an item and ensure that sync is successful.
ASSERT_TRUE(AddFolder(0, 0, kFolderTitle1, GetBookmarksStoreType()));
std::vector<ServerBookmarksEqualityChecker::ExpectedBookmark>
expected_bookmarks = {{kFolderTitle1, GURL()}};
ASSERT_TRUE(ServerBookmarksEqualityChecker(expected_bookmarks,
/*cryptographer=*/nullptr)
.Wait());
DisableNetwork();
// Add a new item to trigger another sync cycle.
ASSERT_TRUE(AddFolder(0, 0, kFolderTitle2, GetBookmarksStoreType()));
// Verify that the client goes into exponential backoff while it is unable to
// reach the sync server.
ASSERT_TRUE(ExponentialBackoffChecker(
GetSyncService(0), syncer::kInitialBackoffImmediateRetryTime)
.Wait());
// Double check that the folder hasn't been committed.
ASSERT_EQ(
1u, GetFakeServer()->GetSyncEntitiesByDataType(syncer::BOOKMARKS).size());
// Trigger network change notification and remember time when it happened.
// Ensure that scheduler runs canary job immediately.
EnableNetwork();
base::Time network_notification_time = base::Time::Now();
// Verify that sync was able to recover.
expected_bookmarks.push_back({kFolderTitle2, GURL()});
EXPECT_TRUE(ServerBookmarksEqualityChecker(expected_bookmarks,
/*cryptographer=*/nullptr)
.Wait());
// Verify that recovery time is short. Without canary job recovery time would
// be more than 5 seconds.
base::TimeDelta recovery_time =
GetSyncService(0)->GetLastCycleSnapshotForDebugging().sync_start_time() -
network_notification_time;
EXPECT_LE(recovery_time, base::Seconds(2));
}
IN_PROC_BROWSER_TEST_P(SyncExponentialBackoffTest, ServerRedirect) {
ASSERT_TRUE(SetupSync());
// Add an item and ensure that sync is successful.
ASSERT_TRUE(AddFolder(0, 0, u"folder1", GetBookmarksStoreType()));
ASSERT_TRUE(UpdatedProgressMarkerChecker(GetSyncService(0)).Wait());
GetFakeServer()->SetHttpError(net::HTTP_USE_PROXY);
// Add a new item to trigger another sync cycle.
ASSERT_TRUE(AddFolder(0, 0, u"folder2", GetBookmarksStoreType()));
// Verify that the client goes into exponential backoff while it is unable to
// reach the sync server.
ASSERT_TRUE(ExponentialBackoffChecker(GetSyncService(0),
syncer::kInitialBackoffShortRetryTime)
.Wait());
}
IN_PROC_BROWSER_TEST_P(SyncExponentialBackoffTest, InternalServerError) {
ASSERT_TRUE(SetupSync());
// Add an item and ensure that sync is successful.
ASSERT_TRUE(AddFolder(0, 0, u"folder1", GetBookmarksStoreType()));
ASSERT_TRUE(UpdatedProgressMarkerChecker(GetSyncService(0)).Wait());
GetFakeServer()->SetHttpError(net::HTTP_INTERNAL_SERVER_ERROR);
// Add a new item to trigger another sync cycle.
ASSERT_TRUE(AddFolder(0, 0, u"folder2", GetBookmarksStoreType()));
// Verify that the client goes into exponential backoff while it is unable to
// reach the sync server.
ASSERT_TRUE(ExponentialBackoffChecker(GetSyncService(0),
syncer::kInitialBackoffShortRetryTime)
.Wait());
}
IN_PROC_BROWSER_TEST_P(SyncExponentialBackoffTest, TransientErrorTest) {
ASSERT_TRUE(SetupSync());
// Add an item and ensure that sync is successful.
ASSERT_TRUE(AddFolder(0, 0, u"folder1", GetBookmarksStoreType()));
ASSERT_TRUE(UpdatedProgressMarkerChecker(GetSyncService(0)).Wait());
GetFakeServer()->TriggerError(sync_pb::SyncEnums::TRANSIENT_ERROR);
// Add a new item to trigger another sync cycle.
ASSERT_TRUE(AddFolder(0, 0, u"folder2", GetBookmarksStoreType()));
// Verify that the client goes into exponential backoff while it is unable to
// reach the sync server.
ASSERT_TRUE(ExponentialBackoffChecker(GetSyncService(0),
syncer::kInitialBackoffShortRetryTime)
.Wait());
}
} // namespace