1 // Copyright 2015 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 "components/cast_channel/keep_alive_delegate.h"
9 #include "base/json/json_writer.h"
10 #include "base/macros.h"
11 #include "base/memory/ptr_util.h"
12 #include "base/run_loop.h"
13 #include "base/test/scoped_task_environment.h"
14 #include "base/test/test_mock_time_task_runner.h"
15 #include "base/time/tick_clock.h"
16 #include "base/timer/mock_timer.h"
17 #include "base/values.h"
18 #include "components/cast_channel/cast_test_util.h"
19 #include "net/base/net_errors.h"
20 #include "testing/gmock/include/gmock/gmock.h"
21 #include "testing/gtest/include/gtest/gtest.h"
24 using testing::Sequence;
26 namespace cast_channel {
29 const int64_t kTestPingTimeoutMillis = 1000;
30 const int64_t kTestLivenessTimeoutMillis = 10000;
32 CastMessage CreateNonKeepAliveMessage(const std::string& message_type) {
34 output.set_protocol_version(CastMessage::CASTV2_1_0);
35 output.set_source_id("source");
36 output.set_destination_id("receiver");
37 output.set_namespace_("some.namespace");
38 output.set_payload_type(
39 CastMessage::PayloadType::CastMessage_PayloadType_STRING);
41 base::DictionaryValue type_dict;
42 type_dict.SetString("type", message_type);
43 CHECK(base::JSONWriter::Write(type_dict, output.mutable_payload_utf8()));
47 // Extends MockTimer with a mockable method ResetTriggered() which permits
48 // test code to set GMock expectations for Timer::Reset().
49 class MockTimerWithMonitoredReset : public base::MockRetainingOneShotTimer {
51 MockTimerWithMonitoredReset() {}
52 ~MockTimerWithMonitoredReset() override {}
54 // Instrumentation point for determining how many times Reset() was called.
55 MOCK_METHOD0(ResetTriggered, void(void));
56 MOCK_METHOD0(StopTriggered, void(void));
58 // Passes through the Reset call to the base MockTimer and visits the mock
59 // ResetTriggered method.
60 void Reset() override {
61 base::MockRetainingOneShotTimer::Reset();
65 void Stop() override {
66 base::MockRetainingOneShotTimer::Stop();
71 class KeepAliveDelegateTest : public testing::Test {
73 using ChannelError = ::cast_channel::ChannelError;
75 KeepAliveDelegateTest() {}
76 ~KeepAliveDelegateTest() override {}
79 void SetUp() override {
80 inner_delegate_ = new MockCastTransportDelegate;
81 logger_ = new Logger();
82 keep_alive_.reset(new KeepAliveDelegate(
83 &socket_, logger_, base::WrapUnique(inner_delegate_),
84 base::TimeDelta::FromMilliseconds(kTestPingTimeoutMillis),
85 base::TimeDelta::FromMilliseconds(kTestLivenessTimeoutMillis)));
86 liveness_timer_ = new MockTimerWithMonitoredReset;
87 ping_timer_ = new MockTimerWithMonitoredReset;
88 EXPECT_CALL(*liveness_timer_, StopTriggered()).Times(0);
89 EXPECT_CALL(*ping_timer_, StopTriggered()).Times(0);
90 keep_alive_->SetTimersForTest(base::WrapUnique(ping_timer_),
91 base::WrapUnique(liveness_timer_));
94 // Runs all pending tasks in the message loop.
95 void RunPendingTasks() {
96 base::RunLoop run_loop;
97 run_loop.RunUntilIdle();
100 base::test::ScopedTaskEnvironment task_environment_;
101 MockCastSocket socket_;
102 std::unique_ptr<KeepAliveDelegate> keep_alive_;
103 scoped_refptr<Logger> logger_;
104 MockCastTransportDelegate* inner_delegate_;
105 MockTimerWithMonitoredReset* liveness_timer_;
106 MockTimerWithMonitoredReset* ping_timer_;
109 DISALLOW_COPY_AND_ASSIGN(KeepAliveDelegateTest);
112 TEST_F(KeepAliveDelegateTest, TestErrorHandledBeforeStarting) {
113 EXPECT_CALL(*inner_delegate_, OnError(ChannelError::CONNECT_ERROR));
114 keep_alive_->OnError(ChannelError::CONNECT_ERROR);
117 TEST_F(KeepAliveDelegateTest, TestPing) {
118 EXPECT_CALL(*socket_.mock_transport(),
119 SendMessage(EqualsProto(CreateKeepAlivePingMessage()), _))
120 .WillOnce(PostCompletionCallbackTask<1>(net::OK));
121 EXPECT_CALL(*inner_delegate_, Start());
122 EXPECT_CALL(*ping_timer_, ResetTriggered()).Times(2);
123 EXPECT_CALL(*liveness_timer_, ResetTriggered()).Times(3);
124 EXPECT_CALL(*ping_timer_, StopTriggered());
126 keep_alive_->Start();
128 EXPECT_FALSE(ping_timer_->IsRunning());
130 keep_alive_->OnMessage(CreateKeepAlivePongMessage());
132 EXPECT_TRUE(ping_timer_->IsRunning());
135 TEST_F(KeepAliveDelegateTest, TestPingFailed) {
136 EXPECT_CALL(*socket_.mock_transport(),
137 SendMessage(EqualsProto(CreateKeepAlivePingMessage()), _))
138 .WillOnce(PostCompletionCallbackTask<1>(net::ERR_CONNECTION_RESET));
139 EXPECT_CALL(*inner_delegate_, Start());
140 EXPECT_CALL(*inner_delegate_, OnError(ChannelError::CAST_SOCKET_ERROR));
141 EXPECT_CALL(*ping_timer_, ResetTriggered()).Times(1);
142 EXPECT_CALL(*liveness_timer_, ResetTriggered()).Times(1);
143 EXPECT_CALL(*liveness_timer_, StopTriggered());
144 EXPECT_CALL(*ping_timer_, StopTriggered()).Times(2);
146 keep_alive_->Start();
149 EXPECT_EQ(ChannelEvent::PING_WRITE_ERROR,
150 logger_->GetLastError(socket_.id()).channel_event);
151 EXPECT_EQ(net::ERR_CONNECTION_RESET,
152 logger_->GetLastError(socket_.id()).net_return_value);
155 TEST_F(KeepAliveDelegateTest, TestPingAndLivenessTimeout) {
156 EXPECT_CALL(*socket_.mock_transport(),
157 SendMessage(EqualsProto(CreateKeepAlivePingMessage()), _))
158 .WillOnce(PostCompletionCallbackTask<1>(net::OK));
159 EXPECT_CALL(*inner_delegate_, OnError(ChannelError::PING_TIMEOUT));
160 EXPECT_CALL(*inner_delegate_, Start());
161 EXPECT_CALL(*ping_timer_, ResetTriggered()).Times(1);
162 EXPECT_CALL(*liveness_timer_, ResetTriggered()).Times(2);
163 EXPECT_CALL(*liveness_timer_, StopTriggered()).Times(2);
164 EXPECT_CALL(*ping_timer_, StopTriggered()).Times(2);
166 keep_alive_->Start();
168 liveness_timer_->Fire();
172 TEST_F(KeepAliveDelegateTest, TestResetTimersAndPassthroughAllOtherTraffic) {
173 CastMessage other_message = CreateNonKeepAliveMessage("someMessageType");
175 EXPECT_CALL(*inner_delegate_, OnMessage(EqualsProto(other_message)));
176 EXPECT_CALL(*inner_delegate_, Start());
177 EXPECT_CALL(*ping_timer_, ResetTriggered()).Times(2);
178 EXPECT_CALL(*liveness_timer_, ResetTriggered()).Times(2);
180 keep_alive_->Start();
181 keep_alive_->OnMessage(other_message);
185 TEST_F(KeepAliveDelegateTest, TestPassthroughMessagesAfterError) {
186 CastMessage message = CreateNonKeepAliveMessage("someMessageType");
187 CastMessage message_after_error =
188 CreateNonKeepAliveMessage("someMessageType2");
189 CastMessage late_ping_message = CreateKeepAlivePingMessage();
191 EXPECT_CALL(*inner_delegate_, Start()).Times(1);
192 EXPECT_CALL(*ping_timer_, ResetTriggered()).Times(2);
193 EXPECT_CALL(*liveness_timer_, ResetTriggered()).Times(2);
194 EXPECT_CALL(*liveness_timer_, StopTriggered()).Times(1);
195 EXPECT_CALL(*ping_timer_, StopTriggered()).Times(1);
197 Sequence message_and_error_sequence;
198 EXPECT_CALL(*inner_delegate_, OnMessage(EqualsProto(message)))
200 .InSequence(message_and_error_sequence)
201 .RetiresOnSaturation();
202 EXPECT_CALL(*inner_delegate_, OnError(ChannelError::INVALID_MESSAGE))
204 .InSequence(message_and_error_sequence);
205 EXPECT_CALL(*inner_delegate_, OnMessage(EqualsProto(message_after_error)))
207 .InSequence(message_and_error_sequence)
208 .RetiresOnSaturation();
209 EXPECT_CALL(*inner_delegate_, OnMessage(EqualsProto(late_ping_message)))
211 .InSequence(message_and_error_sequence)
212 .RetiresOnSaturation();
214 // Start, process one message, then error-out. KeepAliveDelegate will
215 // automatically stop itself.
216 keep_alive_->Start();
217 keep_alive_->OnMessage(message);
219 keep_alive_->OnError(ChannelError::INVALID_MESSAGE);
222 // Process a non-PING/PONG message and expect it to pass through.
223 keep_alive_->OnMessage(message_after_error);
226 // Process a late-arriving PING/PONG message, which should have no effect.
227 keep_alive_->OnMessage(late_ping_message);
231 TEST_F(KeepAliveDelegateTest, TestLivenessTimerResetAfterSendingMessage) {
232 scoped_refptr<base::TestMockTimeTaskRunner> mock_time_task_runner(
233 new base::TestMockTimeTaskRunner());
234 auto liveness_timer = std::make_unique<base::RetainingOneShotTimer>(
235 mock_time_task_runner->GetMockTickClock());
236 auto ping_timer = std::make_unique<base::RetainingOneShotTimer>(
237 mock_time_task_runner->GetMockTickClock());
238 ping_timer->SetTaskRunner(mock_time_task_runner);
239 liveness_timer->SetTaskRunner(mock_time_task_runner);
240 keep_alive_->SetTimersForTest(std::move(ping_timer),
241 std::move(liveness_timer));
244 EXPECT_CALL(*inner_delegate_, Start());
245 keep_alive_->Start();
247 EXPECT_CALL(*socket_.mock_transport(),
248 SendMessage(EqualsProto(CreateKeepAlivePingMessage()), _))
249 .WillOnce(PostCompletionCallbackTask<1>(net::OK));
250 // Forward 1s, at time 1, fire ping timer.
251 mock_time_task_runner->FastForwardBy(
252 base::TimeDelta::FromMilliseconds(kTestPingTimeoutMillis));
254 // Forward 9s, at Time 10, do not fire liveness timer.
255 EXPECT_CALL(*inner_delegate_, OnError(_)).Times(0);
256 mock_time_task_runner->FastForwardBy(base::TimeDelta::FromMilliseconds(
257 kTestLivenessTimeoutMillis - kTestPingTimeoutMillis));
259 // Forward 1s, at time 11s, fire liveness timer.
260 EXPECT_CALL(*inner_delegate_, OnError(_));
261 mock_time_task_runner->FastForwardBy(
262 base::TimeDelta::FromMilliseconds(kTestPingTimeoutMillis));
266 } // namespace cast_channel