Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / google_apis / gcm / engine / heartbeat_manager_unittest.cc
blobb7ee684734f557c40d6371569df61c17f1c2df1f
1 // Copyright 2014 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.
5 #include "google_apis/gcm/engine/heartbeat_manager.h"
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/test/test_simple_task_runner.h"
11 #include "base/thread_task_runner_handle.h"
12 #include "base/time/time.h"
13 #include "base/timer/timer.h"
14 #include "google_apis/gcm/protocol/mcs.pb.h"
15 #include "testing/gtest/include/gtest/gtest.h"
17 namespace gcm {
19 namespace {
21 mcs_proto::HeartbeatConfig BuildHeartbeatConfig(int interval_ms) {
22 mcs_proto::HeartbeatConfig config;
23 config.set_interval_ms(interval_ms);
24 return config;
27 class TestHeartbeatManager : public HeartbeatManager {
28 public:
29 TestHeartbeatManager() {}
30 ~TestHeartbeatManager() override {}
32 // Bypass the heartbeat timer, and send the heartbeat now.
33 void TriggerHearbeat();
35 // Check for a missed heartbeat now.
36 void TriggerMissedHeartbeatCheck();
39 void TestHeartbeatManager::TriggerHearbeat() {
40 OnHeartbeatTriggered();
43 void TestHeartbeatManager::TriggerMissedHeartbeatCheck() {
44 CheckForMissedHeartbeat();
47 class HeartbeatManagerTest : public testing::Test {
48 public:
49 HeartbeatManagerTest();
50 ~HeartbeatManagerTest() override {}
52 TestHeartbeatManager* manager() const { return manager_.get(); }
53 int heartbeats_sent() const { return heartbeats_sent_; }
54 int reconnects_triggered() const { return reconnects_triggered_; }
56 // Starts the heartbeat manager.
57 void StartManager();
59 private:
60 // Helper functions for verifying heartbeat manager effects.
61 void SendHeartbeatClosure();
62 void TriggerReconnectClosure(ConnectionFactory::ConnectionResetReason reason);
64 scoped_ptr<TestHeartbeatManager> manager_;
66 int heartbeats_sent_;
67 int reconnects_triggered_;
69 scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
70 base::ThreadTaskRunnerHandle task_runner_handle_;
73 HeartbeatManagerTest::HeartbeatManagerTest()
74 : manager_(new TestHeartbeatManager()),
75 heartbeats_sent_(0),
76 reconnects_triggered_(0),
77 task_runner_(new base::TestSimpleTaskRunner()),
78 task_runner_handle_(task_runner_) {
81 void HeartbeatManagerTest::StartManager() {
82 manager_->Start(base::Bind(&HeartbeatManagerTest::SendHeartbeatClosure,
83 base::Unretained(this)),
84 base::Bind(&HeartbeatManagerTest::TriggerReconnectClosure,
85 base::Unretained(this)));
88 void HeartbeatManagerTest::SendHeartbeatClosure() {
89 heartbeats_sent_++;
92 void HeartbeatManagerTest::TriggerReconnectClosure(
93 ConnectionFactory::ConnectionResetReason reason) {
94 reconnects_triggered_++;
97 // Basic initialization. No heartbeat should be pending.
98 TEST_F(HeartbeatManagerTest, Init) {
99 EXPECT_TRUE(manager()->GetNextHeartbeatTime().is_null());
102 // Acknowledging a heartbeat before starting the manager should have no effect.
103 TEST_F(HeartbeatManagerTest, AckBeforeStart) {
104 manager()->OnHeartbeatAcked();
105 EXPECT_TRUE(manager()->GetNextHeartbeatTime().is_null());
108 // Starting the manager should start the heartbeat timer.
109 TEST_F(HeartbeatManagerTest, Start) {
110 StartManager();
111 EXPECT_GT(manager()->GetNextHeartbeatTime(), base::TimeTicks::Now());
112 EXPECT_EQ(0, heartbeats_sent());
113 EXPECT_EQ(0, reconnects_triggered());
116 // Acking the heartbeat should trigger a new heartbeat timer.
117 TEST_F(HeartbeatManagerTest, AckedHeartbeat) {
118 StartManager();
119 manager()->TriggerHearbeat();
120 base::TimeTicks heartbeat = manager()->GetNextHeartbeatTime();
121 EXPECT_GT(heartbeat, base::TimeTicks::Now());
122 EXPECT_EQ(1, heartbeats_sent());
123 EXPECT_EQ(0, reconnects_triggered());
125 manager()->OnHeartbeatAcked();
126 EXPECT_LT(heartbeat, manager()->GetNextHeartbeatTime());
127 EXPECT_EQ(1, heartbeats_sent());
128 EXPECT_EQ(0, reconnects_triggered());
130 manager()->TriggerHearbeat();
131 EXPECT_EQ(2, heartbeats_sent());
132 EXPECT_EQ(0, reconnects_triggered());
135 // Trigger a heartbeat when one was outstanding should reset the connection.
136 TEST_F(HeartbeatManagerTest, UnackedHeartbeat) {
137 StartManager();
138 manager()->TriggerHearbeat();
139 EXPECT_EQ(1, heartbeats_sent());
140 EXPECT_EQ(0, reconnects_triggered());
142 manager()->TriggerHearbeat();
143 EXPECT_EQ(1, heartbeats_sent());
144 EXPECT_EQ(1, reconnects_triggered());
147 // Updating the heartbeat interval before starting should result in the new
148 // interval being used at Start time.
149 TEST_F(HeartbeatManagerTest, UpdateIntervalThenStart) {
150 const int kIntervalMs = 60 * 1000; // 60 seconds.
151 manager()->UpdateHeartbeatConfig(BuildHeartbeatConfig(kIntervalMs));
152 EXPECT_TRUE(manager()->GetNextHeartbeatTime().is_null());
153 StartManager();
154 EXPECT_LE(manager()->GetNextHeartbeatTime() - base::TimeTicks::Now(),
155 base::TimeDelta::FromMilliseconds(kIntervalMs));
158 // Updating the heartbeat interval after starting should only use the new
159 // interval on the next heartbeat.
160 TEST_F(HeartbeatManagerTest, StartThenUpdateInterval) {
161 const int kIntervalMs = 60 * 1000; // 60 seconds.
162 StartManager();
163 base::TimeTicks heartbeat = manager()->GetNextHeartbeatTime();
164 EXPECT_GT(heartbeat - base::TimeTicks::Now(),
165 base::TimeDelta::FromMilliseconds(kIntervalMs));
167 // Updating the interval should not affect an outstanding heartbeat.
168 manager()->UpdateHeartbeatConfig(BuildHeartbeatConfig(kIntervalMs));
169 EXPECT_EQ(heartbeat, manager()->GetNextHeartbeatTime());
171 // Triggering and acking the heartbeat should result in a heartbeat being
172 // posted with the new interval.
173 manager()->TriggerHearbeat();
174 manager()->OnHeartbeatAcked();
176 EXPECT_LE(manager()->GetNextHeartbeatTime() - base::TimeTicks::Now(),
177 base::TimeDelta::FromMilliseconds(kIntervalMs));
178 EXPECT_NE(heartbeat, manager()->GetNextHeartbeatTime());
181 // Updating the timer used for heartbeats before starting should not start the
182 // timer.
183 TEST_F(HeartbeatManagerTest, UpdateTimerBeforeStart) {
184 manager()->UpdateHeartbeatTimer(
185 make_scoped_ptr(new base::Timer(true, false)));
186 EXPECT_TRUE(manager()->GetNextHeartbeatTime().is_null());
189 // Updating the timer used for heartbeats after starting should restart the
190 // timer but not increase the heartbeat time by more than a millisecond.
191 TEST_F(HeartbeatManagerTest, UpdateTimerAfterStart) {
192 StartManager();
193 base::TimeTicks heartbeat = manager()->GetNextHeartbeatTime();
195 manager()->UpdateHeartbeatTimer(
196 make_scoped_ptr(new base::Timer(true, false)));
197 EXPECT_LT(manager()->GetNextHeartbeatTime() - heartbeat,
198 base::TimeDelta::FromMilliseconds(5));
201 // Stopping the manager should reset the heartbeat timer.
202 TEST_F(HeartbeatManagerTest, Stop) {
203 StartManager();
204 EXPECT_GT(manager()->GetNextHeartbeatTime(), base::TimeTicks::Now());
206 manager()->Stop();
207 EXPECT_TRUE(manager()->GetNextHeartbeatTime().is_null());
210 // Simulate missing a heartbeat by manually invoking the check method. The
211 // heartbeat should only be triggered once, and only if the heartbeat timer
212 // is running. Because the period is several minutes, none should fire.
213 TEST_F(HeartbeatManagerTest, MissedHeartbeat) {
214 // Do nothing while stopped.
215 manager()->TriggerMissedHeartbeatCheck();
216 StartManager();
217 EXPECT_EQ(0, heartbeats_sent());
219 // Do nothing before the period is reached.
220 manager()->TriggerMissedHeartbeatCheck();
221 EXPECT_EQ(0, heartbeats_sent());
224 // Sets the client hearbeat interval and checks that it is picked up by the
225 // manager.
226 TEST_F(HeartbeatManagerTest, SetClientHeartbeatInterval) {
227 const int kIntervalMs = 180 * 1000; // 180 seconds.
228 StartManager();
229 manager()->TriggerHearbeat();
230 manager()->OnHeartbeatAcked();
232 base::TimeTicks heartbeat = manager()->GetNextHeartbeatTime();
233 EXPECT_GT(heartbeat - base::TimeTicks::Now(),
234 base::TimeDelta::FromMilliseconds(kIntervalMs));
236 manager()->SetClientHeartbeatIntervalMs(kIntervalMs);
237 EXPECT_EQ(1, reconnects_triggered());
239 // Triggering and acking the heartbeat should result in a heartbeat being
240 // posted with the new interval.
241 manager()->TriggerHearbeat();
242 manager()->OnHeartbeatAcked();
244 EXPECT_LE(manager()->GetNextHeartbeatTime() - base::TimeTicks::Now(),
245 base::TimeDelta::FromMilliseconds(kIntervalMs));
246 EXPECT_GT(heartbeat, manager()->GetNextHeartbeatTime());
248 const int kLongerIntervalMs = 2 * kIntervalMs;
249 // Updating the interval should not affect an outstanding heartbeat.
250 manager()->SetClientHeartbeatIntervalMs(kLongerIntervalMs);
251 // No extra reconnects happen here, because the heartbeat is longer.
252 EXPECT_EQ(1, reconnects_triggered());
254 // Triggering and acking the heartbeat should result in a heartbeat being
255 // posted with the old, shorter interval.
256 manager()->TriggerHearbeat();
257 manager()->OnHeartbeatAcked();
259 EXPECT_LE(manager()->GetNextHeartbeatTime() - base::TimeTicks::Now(),
260 base::TimeDelta::FromMilliseconds(kIntervalMs));
263 // Verifies that setting the client interval too low or too high will set it to
264 // a value within a reasonable scope.
265 TEST_F(HeartbeatManagerTest, ClientIntervalInvalid) {
266 // Less than min value.
267 int interval_ms = manager()->GetMinClientHeartbeatIntervalMs() - 60 * 1000;
268 manager()->SetClientHeartbeatIntervalMs(interval_ms);
269 EXPECT_TRUE(manager()->GetNextHeartbeatTime().is_null());
270 StartManager();
271 base::TimeDelta till_heartbeat = manager()->GetNextHeartbeatTime() -
272 base::TimeTicks::Now();
273 EXPECT_GT(till_heartbeat, base::TimeDelta::FromMilliseconds(
274 manager()->GetMinClientHeartbeatIntervalMs()));
275 EXPECT_LE(till_heartbeat, base::TimeDelta::FromMilliseconds(
276 manager()->GetMaxClientHeartbeatIntervalMs()));
278 // More than max value.
279 interval_ms = manager()->GetMaxClientHeartbeatIntervalMs() + 60 * 1000;
280 // Triggering and acking the heartbeat should result in a heartbeat being
281 // posted with the new interval.
282 manager()->TriggerHearbeat();
283 manager()->OnHeartbeatAcked();
285 till_heartbeat = manager()->GetNextHeartbeatTime() - base::TimeTicks::Now();
286 EXPECT_LE(till_heartbeat, base::TimeDelta::FromMilliseconds(
287 manager()->GetMaxClientHeartbeatIntervalMs()));
290 } // namespace
292 } // namespace gcm