1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/bind.h"
6 #include "base/strings/stringprintf.h"
7 #include "chrome/browser/sync/profile_sync_service.h"
8 #include "chrome/browser/sync/test/integration/bookmarks_helper.h"
9 #include "chrome/browser/sync/test/integration/retry_verifier.h"
10 #include "chrome/browser/sync/test/integration/single_client_status_change_checker.h"
11 #include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
12 #include "chrome/browser/sync/test/integration/sync_test.h"
13
14 namespace {
15
16 using bookmarks_helper::AddFolder;
17 using bookmarks_helper::ModelMatchesVerifier;
18 using syncer::sessions::SyncSessionSnapshot;
19 using sync_integration_test_util::AwaitCommitActivityCompletion;
20
21 class SyncExponentialBackoffTest : public SyncTest {
22 public:
23 // TODO(pvalenzuela): Switch to SINGLE_CLIENT once FakeServer
24 // supports this scenario.
SyncExponentialBackoffTest()25 SyncExponentialBackoffTest() : SyncTest(SINGLE_CLIENT_LEGACY) {}
~SyncExponentialBackoffTest()26 virtual ~SyncExponentialBackoffTest() {}
27
28 private:
29 DISALLOW_COPY_AND_ASSIGN(SyncExponentialBackoffTest);
30 };
31
32 // Helper class that checks if a sync client has successfully gone through
33 // exponential backoff after it encounters an error.
34 class ExponentialBackoffChecker : public SingleClientStatusChangeChecker {
35 public:
ExponentialBackoffChecker(ProfileSyncService * pss)36 explicit ExponentialBackoffChecker(ProfileSyncService* pss)
37 : SingleClientStatusChangeChecker(pss) {
38 const SyncSessionSnapshot& snap = service()->GetLastSessionSnapshot();
39 retry_verifier_.Initialize(snap);
40 }
41
~ExponentialBackoffChecker()42 virtual ~ExponentialBackoffChecker() {}
43
44 // Checks if backoff is complete. Called repeatedly each time PSS notifies
45 // observers of a state change.
IsExitConditionSatisfied()46 virtual bool IsExitConditionSatisfied() OVERRIDE {
47 const SyncSessionSnapshot& snap = service()->GetLastSessionSnapshot();
48 retry_verifier_.VerifyRetryInterval(snap);
49 return (retry_verifier_.done() && retry_verifier_.Succeeded());
50 }
51
GetDebugMessage() const52 virtual std::string GetDebugMessage() const OVERRIDE {
53 return base::StringPrintf("Verifying backoff intervals (%d/%d)",
54 retry_verifier_.retry_count(),
55 RetryVerifier::kMaxRetry);
56 }
57
58 private:
59 // Keeps track of the number of attempts at exponential backoff and its
60 // related bookkeeping information for verification.
61 RetryVerifier retry_verifier_;
62
63 DISALLOW_COPY_AND_ASSIGN(ExponentialBackoffChecker);
64 };
65
IN_PROC_BROWSER_TEST_F(SyncExponentialBackoffTest,OfflineToOnline)66 IN_PROC_BROWSER_TEST_F(SyncExponentialBackoffTest, OfflineToOnline) {
67 ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
68
69 // Add an item and ensure that sync is successful.
70 ASSERT_TRUE(AddFolder(0, 0, "folder1"));
71 ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0))));
72
73 // Trigger a network error at the client side.
74 DisableNetwork(GetProfile(0));
75
76 // Add a new item to trigger another sync cycle.
77 ASSERT_TRUE(AddFolder(0, 0, "folder2"));
78
79 // Verify that the client goes into exponential backoff while it is unable to
80 // reach the sync server.
81 ExponentialBackoffChecker exponential_backoff_checker(
82 GetSyncService((0)));
83 exponential_backoff_checker.Wait();
84 ASSERT_FALSE(exponential_backoff_checker.TimedOut());
85
86 // Recover from the network error.
87 EnableNetwork(GetProfile(0));
88
89 // Verify that sync was able to recover.
90 ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0))));
91 ASSERT_TRUE(ModelMatchesVerifier(0));
92 }
93
IN_PROC_BROWSER_TEST_F(SyncExponentialBackoffTest,TransientErrorTest)94 IN_PROC_BROWSER_TEST_F(SyncExponentialBackoffTest, TransientErrorTest) {
95 ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
96
97 // Add an item and ensure that sync is successful.
98 ASSERT_TRUE(AddFolder(0, 0, "folder1"));
99 ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0))));
100
101 // Trigger a transient error on the server.
102 TriggerTransientError();
103
104 // Add a new item to trigger another sync cycle.
105 ASSERT_TRUE(AddFolder(0, 0, "folder2"));
106
107 // Verify that the client goes into exponential backoff while it is unable to
108 // reach the sync server.
109 ExponentialBackoffChecker exponential_backoff_checker(
110 GetSyncService((0)));
111 exponential_backoff_checker.Wait();
112 ASSERT_FALSE(exponential_backoff_checker.TimedOut());
113 }
114
115 } // namespace
116