blob: 5bb681e892c33f19057bb0f24cf4ace7d73a17a4 [file] [log] [blame]
// 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 "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/sync/engine/polling_constants.h"
#include "components/sync/service/sync_service_impl.h"
#include "components/sync/test/fake_server_http_post_provider.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/network_connection_change_simulator.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:
SyncExponentialBackoffTest() : SyncTest(SINGLE_CLIENT) {}
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();
}
};
IN_PROC_BROWSER_TEST_F(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));
std::vector<ServerBookmarksEqualityChecker::ExpectedBookmark>
expected_bookmarks = {{kFolderTitle1, GURL()}};
ASSERT_TRUE(ServerBookmarksEqualityChecker(expected_bookmarks,
/*cryptographer=*/nullptr)
.Wait());
fake_server::FakeServerHttpPostProvider::DisableNetwork();
// Add a new item to trigger another sync cycle.
ASSERT_TRUE(AddFolder(0, 0, kFolderTitle2));
// 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.
fake_server::FakeServerHttpPostProvider::EnableNetwork();
content::NetworkConnectionChangeSimulator connection_change_simulator;
connection_change_simulator.SetConnectionType(
network::mojom::ConnectionType::CONNECTION_ETHERNET);
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_F(SyncExponentialBackoffTest, ServerRedirect) {
ASSERT_TRUE(SetupSync());
// Add an item and ensure that sync is successful.
ASSERT_TRUE(AddFolder(0, 0, u"folder1"));
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"));
// 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_F(SyncExponentialBackoffTest, InternalServerError) {
ASSERT_TRUE(SetupSync());
// Add an item and ensure that sync is successful.
ASSERT_TRUE(AddFolder(0, 0, u"folder1"));
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"));
// 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_F(SyncExponentialBackoffTest, TransientErrorTest) {
ASSERT_TRUE(SetupSync());
// Add an item and ensure that sync is successful.
ASSERT_TRUE(AddFolder(0, 0, u"folder1"));
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"));
// 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