Index: google_apis/gcm/engine/heartbeat_manager_unittest.cc |
diff --git a/google_apis/gcm/engine/heartbeat_manager_unittest.cc b/google_apis/gcm/engine/heartbeat_manager_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..e17e1b7154f3d0fe1fc1791f4a23ac2712a0631f |
--- /dev/null |
+++ b/google_apis/gcm/engine/heartbeat_manager_unittest.cc |
@@ -0,0 +1,176 @@ |
+// Copyright 2013 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 "google_apis/gcm/engine/heartbeat_manager.h" |
+ |
+#include "base/message_loop/message_loop.h" |
+#include "base/time/time.h" |
+#include "google_apis/gcm/protocol/mcs.pb.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+namespace gcm { |
+ |
+namespace { |
+ |
+mcs_proto::HeartbeatConfig BuildHeartbeatConfig(int interval_ms) { |
+ mcs_proto::HeartbeatConfig config; |
+ config.set_interval_ms(interval_ms); |
+ return config; |
+} |
+ |
+class TestHeartbeatManager : public HeartbeatManager { |
+ public: |
+ TestHeartbeatManager() {} |
+ virtual ~TestHeartbeatManager() {} |
+ |
+ // Bypass the heartbeat timer, and send the heartbeat now. |
+ void TriggerHearbeat(); |
+}; |
+ |
+void TestHeartbeatManager::TriggerHearbeat() { |
+ OnHeartbeatTriggered(); |
+} |
+ |
+class HeartbeatManagerTest : public testing::Test { |
+ public: |
+ HeartbeatManagerTest(); |
+ virtual ~HeartbeatManagerTest() {} |
+ |
+ TestHeartbeatManager* manager() { return manager_.get(); } |
jianli
2013/12/20 23:10:03
nit: const modifier
Nicolas Zea
2013/12/26 22:55:02
Done.
|
+ int heartbeats_sent() { return heartbeats_sent_; } |
+ int reconnects_triggered() { return reconnects_triggered_; } |
+ |
+ // Starts the heartbeat manager. |
+ void StartManager(); |
+ |
+ private: |
+ // Helper functions for verifying heartbeat manager effects. |
+ void SendHeartbeatClosure(); |
+ void TriggerReconnectClosure(); |
+ |
+ scoped_ptr<TestHeartbeatManager> manager_; |
+ |
+ int heartbeats_sent_; |
+ int reconnects_triggered_; |
+ |
+ base::MessageLoop message_loop_; |
+}; |
+ |
+HeartbeatManagerTest::HeartbeatManagerTest() |
+ : manager_(new TestHeartbeatManager()), |
+ heartbeats_sent_(0), |
+ reconnects_triggered_(0) { |
+} |
+ |
+void HeartbeatManagerTest::StartManager() { |
+ manager_->Start(base::Bind(&HeartbeatManagerTest::SendHeartbeatClosure, |
+ base::Unretained(this)), |
+ base::Bind(&HeartbeatManagerTest::TriggerReconnectClosure, |
+ base::Unretained(this))); |
+} |
+ |
+void HeartbeatManagerTest::SendHeartbeatClosure() { |
+ heartbeats_sent_++; |
+} |
+ |
+void HeartbeatManagerTest::TriggerReconnectClosure() { |
+ reconnects_triggered_++; |
+} |
+ |
+// Basic initialization. No heartbeat should be pending. |
+TEST_F(HeartbeatManagerTest, Init) { |
+ EXPECT_TRUE(manager()->GetNextHeartbeatTime().is_null()); |
+} |
+ |
+// Acknowledging a heartbeat before starting the manager should have no effect. |
+TEST_F(HeartbeatManagerTest, AckBeforeStart) { |
+ manager()->OnHeartbeatAcked(); |
+ EXPECT_TRUE(manager()->GetNextHeartbeatTime().is_null()); |
+} |
+ |
+// Starting the manager should start the heartbeat timer. |
+TEST_F(HeartbeatManagerTest, Start) { |
+ StartManager(); |
+ EXPECT_GT(manager()->GetNextHeartbeatTime(), base::TimeTicks::Now()); |
+ EXPECT_EQ(0, heartbeats_sent()); |
+ EXPECT_EQ(0, reconnects_triggered()); |
+} |
+ |
+// Acking the heartbeat should trigger a new heartbeat timer. |
+TEST_F(HeartbeatManagerTest, AckedHeartbeat) { |
+ StartManager(); |
+ manager()->TriggerHearbeat(); |
+ base::TimeTicks heartbeat = manager()->GetNextHeartbeatTime(); |
+ EXPECT_GT(heartbeat, base::TimeTicks::Now()); |
+ EXPECT_EQ(1, heartbeats_sent()); |
+ EXPECT_EQ(0, reconnects_triggered()); |
+ |
+ manager()->OnHeartbeatAcked(); |
+ EXPECT_LT(heartbeat, manager()->GetNextHeartbeatTime()); |
+ EXPECT_EQ(1, heartbeats_sent()); |
+ EXPECT_EQ(0, reconnects_triggered()); |
+ |
+ manager()->TriggerHearbeat(); |
+ EXPECT_EQ(2, heartbeats_sent()); |
+ EXPECT_EQ(0, reconnects_triggered()); |
+} |
+ |
+// Trigger a heartbeat when one was outstanding should reset the connection. |
+TEST_F(HeartbeatManagerTest, UnackedHeartbeat) { |
+ StartManager(); |
+ manager()->TriggerHearbeat(); |
+ EXPECT_EQ(1, heartbeats_sent()); |
+ EXPECT_EQ(0, reconnects_triggered()); |
+ |
+ manager()->TriggerHearbeat(); |
+ EXPECT_EQ(1, heartbeats_sent()); |
+ EXPECT_EQ(1, reconnects_triggered()); |
+} |
+ |
+// Updating the heartbeat interval before starting should result in the new |
+// interval being used at Start time. |
+TEST_F(HeartbeatManagerTest, UpdateIntervalThenStart) { |
+ const int kIntervalMs = 60 * 1000; // 60 seconds. |
+ manager()->UpdateHeartbeatConfig(BuildHeartbeatConfig(kIntervalMs)); |
+ EXPECT_TRUE(manager()->GetNextHeartbeatTime().is_null()); |
+ StartManager(); |
+ EXPECT_LE(manager()->GetNextHeartbeatTime() - base::TimeTicks::Now(), |
+ base::TimeDelta::FromMilliseconds(kIntervalMs)); |
+} |
+ |
+// Updating the heartbeat interval after starting should only use the new |
+// interval on the next heartbeat. |
+TEST_F(HeartbeatManagerTest, StartThenUpdateInterval) { |
+ const int kIntervalMs = 60 * 1000; // 60 seconds. |
+ StartManager(); |
+ base::TimeTicks heartbeat = manager()->GetNextHeartbeatTime(); |
+ EXPECT_GT(heartbeat - base::TimeTicks::Now(), |
+ base::TimeDelta::FromMilliseconds(kIntervalMs)); |
+ |
+ // Updating the interval should not affect an outstanding heartbeat. |
+ manager()->UpdateHeartbeatConfig(BuildHeartbeatConfig(kIntervalMs)); |
+ EXPECT_EQ(heartbeat, manager()->GetNextHeartbeatTime()); |
+ |
+ // Triggering and acking the heartbeat should result in a heartbeat being |
+ // posted with the new interval. |
+ manager()->TriggerHearbeat(); |
+ manager()->OnHeartbeatAcked(); |
+ |
+ EXPECT_LE(manager()->GetNextHeartbeatTime() - base::TimeTicks::Now(), |
+ base::TimeDelta::FromMilliseconds(kIntervalMs)); |
+ EXPECT_NE(heartbeat, manager()->GetNextHeartbeatTime()); |
+} |
+ |
+// Stopping the manager should reset the heartbeat timer. |
+TEST_F(HeartbeatManagerTest, Stop) { |
+ StartManager(); |
+ EXPECT_GT(manager()->GetNextHeartbeatTime(), base::TimeTicks::Now()); |
+ |
+ manager()->Stop(); |
+ EXPECT_TRUE(manager()->GetNextHeartbeatTime().is_null()); |
+} |
+ |
+} // namespace |
+ |
+} // namespace gcm |