123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270 |
- // Copyright 2015 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 "components/cast_channel/keep_alive_delegate.h"
- #include <stdint.h>
- #include <memory>
- #include "base/json/json_writer.h"
- #include "base/memory/ptr_util.h"
- #include "base/memory/raw_ptr.h"
- #include "base/run_loop.h"
- #include "base/test/task_environment.h"
- #include "base/test/test_mock_time_task_runner.h"
- #include "base/time/tick_clock.h"
- #include "base/timer/mock_timer.h"
- #include "base/timer/timer.h"
- #include "base/values.h"
- #include "components/cast_channel/cast_test_util.h"
- #include "net/base/net_errors.h"
- #include "testing/gmock/include/gmock/gmock.h"
- #include "testing/gtest/include/gtest/gtest.h"
- using testing::_;
- using testing::Sequence;
- namespace cast_channel {
- namespace {
- const int64_t kTestPingTimeoutMillis = 1000;
- const int64_t kTestLivenessTimeoutMillis = 10000;
- CastMessage CreateNonKeepAliveMessage(const std::string& message_type) {
- CastMessage output;
- output.set_protocol_version(CastMessage::CASTV2_1_0);
- output.set_source_id("source");
- output.set_destination_id("receiver");
- output.set_namespace_("some.namespace");
- output.set_payload_type(
- CastMessage::PayloadType::CastMessage_PayloadType_STRING);
- base::DictionaryValue type_dict;
- type_dict.SetString("type", message_type);
- CHECK(base::JSONWriter::Write(type_dict, output.mutable_payload_utf8()));
- return output;
- }
- // Extends MockTimer with a mockable method ResetTriggered() which permits
- // test code to set GMock expectations for Timer::Reset().
- class MockTimerWithMonitoredReset : public base::MockRetainingOneShotTimer {
- public:
- MockTimerWithMonitoredReset() {}
- ~MockTimerWithMonitoredReset() override {}
- // Instrumentation point for determining how many times Reset() was called.
- MOCK_METHOD0(ResetTriggered, void(void));
- MOCK_METHOD0(StopTriggered, void(void));
- // Passes through the Reset call to the base MockTimer and visits the mock
- // ResetTriggered method.
- void Reset() override {
- base::MockRetainingOneShotTimer::Reset();
- ResetTriggered();
- }
- void Stop() override {
- base::MockRetainingOneShotTimer::Stop();
- StopTriggered();
- }
- };
- class KeepAliveDelegateTest : public testing::Test {
- public:
- using ChannelError = ::cast_channel::ChannelError;
- KeepAliveDelegateTest() {}
- KeepAliveDelegateTest(const KeepAliveDelegateTest&) = delete;
- KeepAliveDelegateTest& operator=(const KeepAliveDelegateTest&) = delete;
- ~KeepAliveDelegateTest() override {}
- protected:
- void SetUp() override {
- inner_delegate_ = new MockCastTransportDelegate;
- logger_ = new Logger();
- keep_alive_ = std::make_unique<KeepAliveDelegate>(
- &socket_, logger_, base::WrapUnique(inner_delegate_.get()),
- base::Milliseconds(kTestPingTimeoutMillis),
- base::Milliseconds(kTestLivenessTimeoutMillis));
- liveness_timer_ = new MockTimerWithMonitoredReset;
- ping_timer_ = new MockTimerWithMonitoredReset;
- EXPECT_CALL(*liveness_timer_, StopTriggered()).Times(0);
- EXPECT_CALL(*ping_timer_, StopTriggered()).Times(0);
- keep_alive_->SetTimersForTest(base::WrapUnique(ping_timer_.get()),
- base::WrapUnique(liveness_timer_.get()));
- }
- // Runs all pending tasks in the message loop.
- void RunPendingTasks() {
- base::RunLoop run_loop;
- run_loop.RunUntilIdle();
- }
- base::test::SingleThreadTaskEnvironment task_environment_;
- MockCastSocket socket_;
- std::unique_ptr<KeepAliveDelegate> keep_alive_;
- scoped_refptr<Logger> logger_;
- raw_ptr<MockCastTransportDelegate> inner_delegate_;
- raw_ptr<MockTimerWithMonitoredReset> liveness_timer_;
- raw_ptr<MockTimerWithMonitoredReset> ping_timer_;
- };
- TEST_F(KeepAliveDelegateTest, TestErrorHandledBeforeStarting) {
- EXPECT_CALL(*inner_delegate_, OnError(ChannelError::CONNECT_ERROR));
- keep_alive_->OnError(ChannelError::CONNECT_ERROR);
- }
- TEST_F(KeepAliveDelegateTest, TestPing) {
- EXPECT_CALL(*socket_.mock_transport(),
- SendMessage_(EqualsProto(CreateKeepAlivePingMessage()), _))
- .WillOnce(PostCompletionCallbackTask<1>(net::OK));
- EXPECT_CALL(*inner_delegate_, Start());
- EXPECT_CALL(*ping_timer_, ResetTriggered()).Times(2);
- EXPECT_CALL(*liveness_timer_, ResetTriggered()).Times(3);
- EXPECT_CALL(*ping_timer_, StopTriggered());
- keep_alive_->Start();
- ping_timer_->Fire();
- EXPECT_FALSE(ping_timer_->IsRunning());
- keep_alive_->OnMessage(CreateKeepAlivePongMessage());
- RunPendingTasks();
- EXPECT_TRUE(ping_timer_->IsRunning());
- }
- TEST_F(KeepAliveDelegateTest, TestPingFailed) {
- EXPECT_CALL(*socket_.mock_transport(),
- SendMessage_(EqualsProto(CreateKeepAlivePingMessage()), _))
- .WillOnce(PostCompletionCallbackTask<1>(net::ERR_CONNECTION_RESET));
- EXPECT_CALL(*inner_delegate_, Start());
- EXPECT_CALL(*inner_delegate_, OnError(ChannelError::CAST_SOCKET_ERROR));
- EXPECT_CALL(*ping_timer_, ResetTriggered()).Times(1);
- EXPECT_CALL(*liveness_timer_, ResetTriggered()).Times(1);
- EXPECT_CALL(*liveness_timer_, StopTriggered());
- EXPECT_CALL(*ping_timer_, StopTriggered()).Times(2);
- keep_alive_->Start();
- ping_timer_->Fire();
- RunPendingTasks();
- EXPECT_EQ(ChannelEvent::PING_WRITE_ERROR,
- logger_->GetLastError(socket_.id()).channel_event);
- EXPECT_EQ(net::ERR_CONNECTION_RESET,
- logger_->GetLastError(socket_.id()).net_return_value);
- }
- TEST_F(KeepAliveDelegateTest, TestPingAndLivenessTimeout) {
- EXPECT_CALL(*socket_.mock_transport(),
- SendMessage_(EqualsProto(CreateKeepAlivePingMessage()), _))
- .WillOnce(PostCompletionCallbackTask<1>(net::OK));
- EXPECT_CALL(*inner_delegate_, OnError(ChannelError::PING_TIMEOUT));
- EXPECT_CALL(*inner_delegate_, Start());
- EXPECT_CALL(*ping_timer_, ResetTriggered()).Times(1);
- EXPECT_CALL(*liveness_timer_, ResetTriggered()).Times(2);
- EXPECT_CALL(*liveness_timer_, StopTriggered()).Times(2);
- EXPECT_CALL(*ping_timer_, StopTriggered()).Times(2);
- keep_alive_->Start();
- ping_timer_->Fire();
- liveness_timer_->Fire();
- RunPendingTasks();
- }
- TEST_F(KeepAliveDelegateTest, TestResetTimersAndPassthroughAllOtherTraffic) {
- CastMessage other_message = CreateNonKeepAliveMessage("someMessageType");
- EXPECT_CALL(*inner_delegate_, OnMessage(EqualsProto(other_message)));
- EXPECT_CALL(*inner_delegate_, Start());
- EXPECT_CALL(*ping_timer_, ResetTriggered()).Times(2);
- EXPECT_CALL(*liveness_timer_, ResetTriggered()).Times(2);
- keep_alive_->Start();
- keep_alive_->OnMessage(other_message);
- RunPendingTasks();
- }
- TEST_F(KeepAliveDelegateTest, TestPassthroughMessagesAfterError) {
- CastMessage message = CreateNonKeepAliveMessage("someMessageType");
- CastMessage message_after_error =
- CreateNonKeepAliveMessage("someMessageType2");
- CastMessage late_ping_message = CreateKeepAlivePingMessage();
- EXPECT_CALL(*inner_delegate_, Start()).Times(1);
- EXPECT_CALL(*ping_timer_, ResetTriggered()).Times(2);
- EXPECT_CALL(*liveness_timer_, ResetTriggered()).Times(2);
- EXPECT_CALL(*liveness_timer_, StopTriggered()).Times(1);
- EXPECT_CALL(*ping_timer_, StopTriggered()).Times(1);
- Sequence message_and_error_sequence;
- EXPECT_CALL(*inner_delegate_, OnMessage(EqualsProto(message)))
- .Times(1)
- .InSequence(message_and_error_sequence)
- .RetiresOnSaturation();
- EXPECT_CALL(*inner_delegate_, OnError(ChannelError::INVALID_MESSAGE))
- .Times(1)
- .InSequence(message_and_error_sequence);
- EXPECT_CALL(*inner_delegate_, OnMessage(EqualsProto(message_after_error)))
- .Times(1)
- .InSequence(message_and_error_sequence)
- .RetiresOnSaturation();
- EXPECT_CALL(*inner_delegate_, OnMessage(EqualsProto(late_ping_message)))
- .Times(0)
- .InSequence(message_and_error_sequence)
- .RetiresOnSaturation();
- // Start, process one message, then error-out. KeepAliveDelegate will
- // automatically stop itself.
- keep_alive_->Start();
- keep_alive_->OnMessage(message);
- RunPendingTasks();
- keep_alive_->OnError(ChannelError::INVALID_MESSAGE);
- RunPendingTasks();
- // Process a non-PING/PONG message and expect it to pass through.
- keep_alive_->OnMessage(message_after_error);
- RunPendingTasks();
- // Process a late-arriving PING/PONG message, which should have no effect.
- keep_alive_->OnMessage(late_ping_message);
- RunPendingTasks();
- }
- TEST_F(KeepAliveDelegateTest, TestLivenessTimerResetAfterSendingMessage) {
- scoped_refptr<base::TestMockTimeTaskRunner> mock_time_task_runner(
- new base::TestMockTimeTaskRunner());
- auto liveness_timer = std::make_unique<base::RetainingOneShotTimer>(
- mock_time_task_runner->GetMockTickClock());
- auto ping_timer = std::make_unique<base::RetainingOneShotTimer>(
- mock_time_task_runner->GetMockTickClock());
- ping_timer->SetTaskRunner(mock_time_task_runner);
- liveness_timer->SetTaskRunner(mock_time_task_runner);
- keep_alive_->SetTimersForTest(std::move(ping_timer),
- std::move(liveness_timer));
- // At time 0, start.
- EXPECT_CALL(*inner_delegate_, Start());
- keep_alive_->Start();
- EXPECT_CALL(*socket_.mock_transport(),
- SendMessage_(EqualsProto(CreateKeepAlivePingMessage()), _))
- .WillOnce(PostCompletionCallbackTask<1>(net::OK));
- // Forward 1s, at time 1, fire ping timer.
- mock_time_task_runner->FastForwardBy(
- base::Milliseconds(kTestPingTimeoutMillis));
- // Forward 9s, at Time 10, do not fire liveness timer.
- EXPECT_CALL(*inner_delegate_, OnError(_)).Times(0);
- mock_time_task_runner->FastForwardBy(
- base::Milliseconds(kTestLivenessTimeoutMillis - kTestPingTimeoutMillis));
- // Forward 1s, at time 11s, fire liveness timer.
- EXPECT_CALL(*inner_delegate_, OnError(_));
- mock_time_task_runner->FastForwardBy(
- base::Milliseconds(kTestPingTimeoutMillis));
- }
- } // namespace
- } // namespace cast_channel
|