Index: extensions/browser/api/cast_channel/cast_transport_unittest.cc |
diff --git a/extensions/browser/api/cast_channel/cast_transport_unittest.cc b/extensions/browser/api/cast_channel/cast_transport_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..90374d49e7942cc53a430dd6192091f40e7dfeda |
--- /dev/null |
+++ b/extensions/browser/api/cast_channel/cast_transport_unittest.cc |
@@ -0,0 +1,687 @@ |
+// Copyright 2014 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 "extensions/browser/api/cast_channel/cast_transport.h" |
+ |
+#include <stddef.h> |
+#include <stdint.h> |
+ |
+#include <queue> |
+ |
+#include "base/macros.h" |
+#include "base/memory/ptr_util.h" |
+#include "base/message_loop/message_loop.h" |
+#include "base/run_loop.h" |
+#include "base/test/simple_test_clock.h" |
+#include "extensions/browser/api/cast_channel/cast_framer.h" |
+#include "extensions/browser/api/cast_channel/cast_socket.h" |
+#include "extensions/browser/api/cast_channel/cast_test_util.h" |
+#include "extensions/browser/api/cast_channel/logger.h" |
+#include "extensions/common/api/cast_channel/cast_channel.pb.h" |
+#include "net/base/completion_callback.h" |
+#include "net/base/net_errors.h" |
+#include "net/log/test_net_log.h" |
+#include "net/socket/socket.h" |
+#include "testing/gmock/include/gmock/gmock.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+using testing::_; |
+using testing::DoAll; |
+using testing::InSequence; |
+using testing::Invoke; |
+using testing::NotNull; |
+using testing::Return; |
+using testing::WithArg; |
+ |
+namespace extensions { |
+namespace api { |
+namespace cast_channel { |
+namespace { |
+ |
+const int kChannelId = 0; |
+ |
+// Mockable placeholder for write completion events. |
+class CompleteHandler { |
+ public: |
+ CompleteHandler() {} |
+ MOCK_METHOD1(Complete, void(int result)); |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(CompleteHandler); |
+}; |
+ |
+// Creates a CastMessage proto with the bare minimum required fields set. |
+CastMessage CreateCastMessage() { |
+ CastMessage output; |
+ output.set_protocol_version(CastMessage::CASTV2_1_0); |
+ output.set_namespace_("x"); |
+ output.set_source_id("source"); |
+ output.set_destination_id("destination"); |
+ output.set_payload_type(CastMessage::STRING); |
+ output.set_payload_utf8("payload"); |
+ return output; |
+} |
+ |
+// FIFO queue of completion callbacks. Outstanding write operations are |
+// Push()ed into the queue. Callback completion is simulated by invoking |
+// Pop() in the same order as Push(). |
+class CompletionQueue { |
+ public: |
+ CompletionQueue() {} |
+ ~CompletionQueue() { CHECK_EQ(0u, cb_queue_.size()); } |
+ |
+ // Enqueues a pending completion callback. |
+ void Push(const net::CompletionCallback& cb) { cb_queue_.push(cb); } |
+ // Runs the next callback and removes it from the queue. |
+ void Pop(int rv) { |
+ CHECK_GT(cb_queue_.size(), 0u); |
+ cb_queue_.front().Run(rv); |
+ cb_queue_.pop(); |
+ } |
+ |
+ private: |
+ std::queue<net::CompletionCallback> cb_queue_; |
+ DISALLOW_COPY_AND_ASSIGN(CompletionQueue); |
+}; |
+ |
+// GMock action that reads data from an IOBuffer and writes it to a string |
+// variable. |
+// |
+// buf_idx (template parameter 0): 0-based index of the net::IOBuffer |
+// in the function mock arg list. |
+// size_idx (template parameter 1): 0-based index of the byte count arg. |
+// str: pointer to the string which will receive data from the buffer. |
+ACTION_TEMPLATE(ReadBufferToString, |
+ HAS_2_TEMPLATE_PARAMS(int, buf_idx, int, size_idx), |
+ AND_1_VALUE_PARAMS(str)) { |
+ str->assign(testing::get<buf_idx>(args)->data(), |
+ testing::get<size_idx>(args)); |
+} |
+ |
+// GMock action that writes data from a string to an IOBuffer. |
+// |
+// buf_idx (template parameter 0): 0-based index of the IOBuffer arg. |
+// str: the string containing data to be written to the IOBuffer. |
+ACTION_TEMPLATE(FillBufferFromString, |
+ HAS_1_TEMPLATE_PARAMS(int, buf_idx), |
+ AND_1_VALUE_PARAMS(str)) { |
+ memcpy(testing::get<buf_idx>(args)->data(), str.data(), str.size()); |
+} |
+ |
+// GMock action that enqueues a write completion callback in a queue. |
+// |
+// buf_idx (template parameter 0): 0-based index of the CompletionCallback. |
+// completion_queue: a pointer to the CompletionQueue. |
+ACTION_TEMPLATE(EnqueueCallback, |
+ HAS_1_TEMPLATE_PARAMS(int, cb_idx), |
+ AND_1_VALUE_PARAMS(completion_queue)) { |
+ completion_queue->Push(testing::get<cb_idx>(args)); |
+} |
+ |
+} // namespace |
+ |
+class MockSocket : public net::Socket { |
+ public: |
+ MOCK_METHOD3(Read, |
+ int(net::IOBuffer* buf, |
+ int buf_len, |
+ const net::CompletionCallback& callback)); |
+ |
+ MOCK_METHOD3(Write, |
+ int(net::IOBuffer* buf, |
+ int buf_len, |
+ const net::CompletionCallback& callback)); |
+ |
+ virtual int SetReceiveBufferSize(int32_t size) { |
+ NOTREACHED(); |
+ return 0; |
+ } |
+ |
+ virtual int SetSendBufferSize(int32_t size) { |
+ NOTREACHED(); |
+ return 0; |
+ } |
+}; |
+ |
+class CastTransportTest : public testing::Test { |
+ public: |
+ using ChannelError = ::cast_channel::ChannelError; |
+ using ChannelAuthType = ::cast_channel::ChannelAuthType; |
+ |
+ CastTransportTest() : logger_(new Logger()) { |
+ delegate_ = new MockCastTransportDelegate; |
+ transport_.reset(new CastTransportImpl(&mock_socket_, kChannelId, |
+ CreateIPEndPointForTest(), |
+ auth_type_, logger_)); |
+ transport_->SetReadDelegate(base::WrapUnique(delegate_)); |
+ } |
+ ~CastTransportTest() override {} |
+ |
+ protected: |
+ // Runs all pending tasks in the message loop. |
+ void RunPendingTasks() { |
+ base::RunLoop run_loop; |
+ run_loop.RunUntilIdle(); |
+ } |
+ |
+ base::MessageLoop message_loop_; |
+ MockCastTransportDelegate* delegate_; |
+ MockSocket mock_socket_; |
+ ChannelAuthType auth_type_; |
+ Logger* logger_; |
+ std::unique_ptr<CastTransport> transport_; |
+}; |
+ |
+// ---------------------------------------------------------------------------- |
+// Asynchronous write tests |
+TEST_F(CastTransportTest, TestFullWriteAsync) { |
+ CompletionQueue socket_cbs; |
+ CompleteHandler write_handler; |
+ std::string output; |
+ |
+ CastMessage message = CreateCastMessage(); |
+ std::string serialized_message; |
+ EXPECT_TRUE(MessageFramer::Serialize(message, &serialized_message)); |
+ |
+ EXPECT_CALL(mock_socket_, Write(NotNull(), serialized_message.size(), _)) |
+ .WillOnce(DoAll(ReadBufferToString<0, 1>(&output), |
+ EnqueueCallback<2>(&socket_cbs), |
+ Return(net::ERR_IO_PENDING))); |
+ EXPECT_CALL(write_handler, Complete(net::OK)); |
+ transport_->SendMessage( |
+ message, |
+ base::Bind(&CompleteHandler::Complete, base::Unretained(&write_handler))); |
+ RunPendingTasks(); |
+ socket_cbs.Pop(serialized_message.size()); |
+ RunPendingTasks(); |
+ EXPECT_EQ(serialized_message, output); |
+} |
+ |
+TEST_F(CastTransportTest, TestPartialWritesAsync) { |
+ InSequence seq; |
+ CompletionQueue socket_cbs; |
+ CompleteHandler write_handler; |
+ std::string output; |
+ |
+ CastMessage message = CreateCastMessage(); |
+ std::string serialized_message; |
+ EXPECT_TRUE(MessageFramer::Serialize(message, &serialized_message)); |
+ |
+ // Only one byte is written. |
+ EXPECT_CALL(mock_socket_, |
+ Write(NotNull(), static_cast<int>(serialized_message.size()), _)) |
+ .WillOnce(DoAll(ReadBufferToString<0, 1>(&output), |
+ EnqueueCallback<2>(&socket_cbs), |
+ Return(net::ERR_IO_PENDING))); |
+ // Remainder of bytes are written. |
+ EXPECT_CALL( |
+ mock_socket_, |
+ Write(NotNull(), static_cast<int>(serialized_message.size() - 1), _)) |
+ .WillOnce(DoAll(ReadBufferToString<0, 1>(&output), |
+ EnqueueCallback<2>(&socket_cbs), |
+ Return(net::ERR_IO_PENDING))); |
+ |
+ transport_->SendMessage( |
+ message, |
+ base::Bind(&CompleteHandler::Complete, base::Unretained(&write_handler))); |
+ RunPendingTasks(); |
+ EXPECT_EQ(serialized_message, output); |
+ socket_cbs.Pop(1); |
+ RunPendingTasks(); |
+ |
+ EXPECT_CALL(write_handler, Complete(net::OK)); |
+ socket_cbs.Pop(serialized_message.size() - 1); |
+ RunPendingTasks(); |
+ EXPECT_EQ(serialized_message.substr(1, serialized_message.size() - 1), |
+ output); |
+} |
+ |
+TEST_F(CastTransportTest, TestWriteFailureAsync) { |
+ CompletionQueue socket_cbs; |
+ CompleteHandler write_handler; |
+ CastMessage message = CreateCastMessage(); |
+ EXPECT_CALL(mock_socket_, Write(NotNull(), _, _)).WillOnce( |
+ DoAll(EnqueueCallback<2>(&socket_cbs), Return(net::ERR_IO_PENDING))); |
+ EXPECT_CALL(write_handler, Complete(net::ERR_FAILED)); |
+ EXPECT_CALL(*delegate_, OnError(ChannelError::CAST_SOCKET_ERROR)); |
+ transport_->SendMessage( |
+ message, |
+ base::Bind(&CompleteHandler::Complete, base::Unretained(&write_handler))); |
+ RunPendingTasks(); |
+ socket_cbs.Pop(net::ERR_CONNECTION_RESET); |
+ RunPendingTasks(); |
+ EXPECT_EQ(proto::SOCKET_WRITE, logger_->GetLastErrors(kChannelId).event_type); |
+ EXPECT_EQ(net::ERR_CONNECTION_RESET, |
+ logger_->GetLastErrors(kChannelId).net_return_value); |
+} |
+ |
+// ---------------------------------------------------------------------------- |
+// Synchronous write tests |
+TEST_F(CastTransportTest, TestFullWriteSync) { |
+ CompleteHandler write_handler; |
+ std::string output; |
+ CastMessage message = CreateCastMessage(); |
+ std::string serialized_message; |
+ EXPECT_TRUE(MessageFramer::Serialize(message, &serialized_message)); |
+ EXPECT_CALL(mock_socket_, Write(NotNull(), serialized_message.size(), _)) |
+ .WillOnce(DoAll(ReadBufferToString<0, 1>(&output), |
+ Return(serialized_message.size()))); |
+ EXPECT_CALL(write_handler, Complete(net::OK)); |
+ transport_->SendMessage( |
+ message, |
+ base::Bind(&CompleteHandler::Complete, base::Unretained(&write_handler))); |
+ RunPendingTasks(); |
+ EXPECT_EQ(serialized_message, output); |
+} |
+ |
+TEST_F(CastTransportTest, TestPartialWritesSync) { |
+ InSequence seq; |
+ CompleteHandler write_handler; |
+ std::string output; |
+ |
+ CastMessage message = CreateCastMessage(); |
+ std::string serialized_message; |
+ EXPECT_TRUE(MessageFramer::Serialize(message, &serialized_message)); |
+ |
+ // Only one byte is written. |
+ EXPECT_CALL(mock_socket_, Write(NotNull(), serialized_message.size(), _)) |
+ .WillOnce(DoAll(ReadBufferToString<0, 1>(&output), Return(1))); |
+ // Remainder of bytes are written. |
+ EXPECT_CALL(mock_socket_, Write(NotNull(), serialized_message.size() - 1, _)) |
+ .WillOnce(DoAll(ReadBufferToString<0, 1>(&output), |
+ Return(serialized_message.size() - 1))); |
+ |
+ EXPECT_CALL(write_handler, Complete(net::OK)); |
+ transport_->SendMessage( |
+ message, |
+ base::Bind(&CompleteHandler::Complete, base::Unretained(&write_handler))); |
+ RunPendingTasks(); |
+ EXPECT_EQ(serialized_message.substr(1, serialized_message.size() - 1), |
+ output); |
+} |
+ |
+TEST_F(CastTransportTest, TestWriteFailureSync) { |
+ CompleteHandler write_handler; |
+ CastMessage message = CreateCastMessage(); |
+ EXPECT_CALL(mock_socket_, Write(NotNull(), _, _)) |
+ .WillOnce(Return(net::ERR_CONNECTION_RESET)); |
+ EXPECT_CALL(write_handler, Complete(net::ERR_FAILED)); |
+ transport_->SendMessage( |
+ message, |
+ base::Bind(&CompleteHandler::Complete, base::Unretained(&write_handler))); |
+ RunPendingTasks(); |
+ EXPECT_EQ(proto::SOCKET_WRITE, logger_->GetLastErrors(kChannelId).event_type); |
+ EXPECT_EQ(net::ERR_CONNECTION_RESET, |
+ logger_->GetLastErrors(kChannelId).net_return_value); |
+} |
+ |
+// ---------------------------------------------------------------------------- |
+// Asynchronous read tests |
+TEST_F(CastTransportTest, TestFullReadAsync) { |
+ InSequence s; |
+ CompletionQueue socket_cbs; |
+ |
+ CastMessage message = CreateCastMessage(); |
+ std::string serialized_message; |
+ EXPECT_TRUE(MessageFramer::Serialize(message, &serialized_message)); |
+ EXPECT_CALL(*delegate_, Start()); |
+ |
+ // Read bytes [0, 3]. |
+ EXPECT_CALL(mock_socket_, |
+ Read(NotNull(), MessageFramer::MessageHeader::header_size(), _)) |
+ .WillOnce(DoAll(FillBufferFromString<0>(serialized_message), |
+ EnqueueCallback<2>(&socket_cbs), |
+ Return(net::ERR_IO_PENDING))); |
+ |
+ // Read bytes [4, n]. |
+ EXPECT_CALL(mock_socket_, |
+ Read(NotNull(), |
+ serialized_message.size() - |
+ MessageFramer::MessageHeader::header_size(), |
+ _)) |
+ .WillOnce(DoAll(FillBufferFromString<0>(serialized_message.substr( |
+ MessageFramer::MessageHeader::header_size(), |
+ serialized_message.size() - |
+ MessageFramer::MessageHeader::header_size())), |
+ EnqueueCallback<2>(&socket_cbs), |
+ Return(net::ERR_IO_PENDING))) |
+ .RetiresOnSaturation(); |
+ |
+ EXPECT_CALL(*delegate_, OnMessage(EqualsProto(message))); |
+ EXPECT_CALL(mock_socket_, |
+ Read(NotNull(), MessageFramer::MessageHeader::header_size(), _)) |
+ .WillOnce(Return(net::ERR_IO_PENDING)); |
+ transport_->Start(); |
+ RunPendingTasks(); |
+ socket_cbs.Pop(MessageFramer::MessageHeader::header_size()); |
+ socket_cbs.Pop(serialized_message.size() - |
+ MessageFramer::MessageHeader::header_size()); |
+ RunPendingTasks(); |
+} |
+ |
+TEST_F(CastTransportTest, TestPartialReadAsync) { |
+ InSequence s; |
+ CompletionQueue socket_cbs; |
+ |
+ CastMessage message = CreateCastMessage(); |
+ std::string serialized_message; |
+ EXPECT_TRUE(MessageFramer::Serialize(message, &serialized_message)); |
+ |
+ EXPECT_CALL(*delegate_, Start()); |
+ |
+ // Read bytes [0, 3]. |
+ EXPECT_CALL(mock_socket_, |
+ Read(NotNull(), MessageFramer::MessageHeader::header_size(), _)) |
+ .WillOnce(DoAll(FillBufferFromString<0>(serialized_message), |
+ EnqueueCallback<2>(&socket_cbs), |
+ Return(net::ERR_IO_PENDING))) |
+ .RetiresOnSaturation(); |
+ // Read bytes [4, n-1]. |
+ EXPECT_CALL(mock_socket_, |
+ Read(NotNull(), |
+ serialized_message.size() - |
+ MessageFramer::MessageHeader::header_size(), |
+ _)) |
+ .WillOnce(DoAll(FillBufferFromString<0>(serialized_message.substr( |
+ MessageFramer::MessageHeader::header_size(), |
+ serialized_message.size() - |
+ MessageFramer::MessageHeader::header_size() - 1)), |
+ EnqueueCallback<2>(&socket_cbs), |
+ Return(net::ERR_IO_PENDING))) |
+ .RetiresOnSaturation(); |
+ // Read final byte. |
+ EXPECT_CALL(mock_socket_, Read(NotNull(), 1, _)) |
+ .WillOnce(DoAll(FillBufferFromString<0>(serialized_message.substr( |
+ serialized_message.size() - 1, 1)), |
+ EnqueueCallback<2>(&socket_cbs), |
+ Return(net::ERR_IO_PENDING))) |
+ .RetiresOnSaturation(); |
+ EXPECT_CALL(*delegate_, OnMessage(EqualsProto(message))); |
+ transport_->Start(); |
+ socket_cbs.Pop(MessageFramer::MessageHeader::header_size()); |
+ socket_cbs.Pop(serialized_message.size() - |
+ MessageFramer::MessageHeader::header_size() - 1); |
+ EXPECT_CALL(mock_socket_, |
+ Read(NotNull(), MessageFramer::MessageHeader::header_size(), _)) |
+ .WillOnce(Return(net::ERR_IO_PENDING)); |
+ socket_cbs.Pop(1); |
+} |
+ |
+TEST_F(CastTransportTest, TestReadErrorInHeaderAsync) { |
+ CompletionQueue socket_cbs; |
+ |
+ CastMessage message = CreateCastMessage(); |
+ std::string serialized_message; |
+ EXPECT_TRUE(MessageFramer::Serialize(message, &serialized_message)); |
+ |
+ EXPECT_CALL(*delegate_, Start()); |
+ |
+ // Read bytes [0, 3]. |
+ EXPECT_CALL(mock_socket_, |
+ Read(NotNull(), MessageFramer::MessageHeader::header_size(), _)) |
+ .WillOnce(DoAll(FillBufferFromString<0>(serialized_message), |
+ EnqueueCallback<2>(&socket_cbs), |
+ Return(net::ERR_IO_PENDING))) |
+ .RetiresOnSaturation(); |
+ |
+ EXPECT_CALL(*delegate_, OnError(ChannelError::CAST_SOCKET_ERROR)); |
+ transport_->Start(); |
+ // Header read failure. |
+ socket_cbs.Pop(net::ERR_CONNECTION_RESET); |
+ EXPECT_EQ(proto::SOCKET_READ, logger_->GetLastErrors(kChannelId).event_type); |
+ EXPECT_EQ(net::ERR_CONNECTION_RESET, |
+ logger_->GetLastErrors(kChannelId).net_return_value); |
+} |
+ |
+TEST_F(CastTransportTest, TestReadErrorInBodyAsync) { |
+ CompletionQueue socket_cbs; |
+ |
+ CastMessage message = CreateCastMessage(); |
+ std::string serialized_message; |
+ EXPECT_TRUE(MessageFramer::Serialize(message, &serialized_message)); |
+ |
+ EXPECT_CALL(*delegate_, Start()); |
+ |
+ // Read bytes [0, 3]. |
+ EXPECT_CALL(mock_socket_, |
+ Read(NotNull(), MessageFramer::MessageHeader::header_size(), _)) |
+ .WillOnce(DoAll(FillBufferFromString<0>(serialized_message), |
+ EnqueueCallback<2>(&socket_cbs), |
+ Return(net::ERR_IO_PENDING))) |
+ .RetiresOnSaturation(); |
+ // Read bytes [4, n-1]. |
+ EXPECT_CALL(mock_socket_, |
+ Read(NotNull(), |
+ serialized_message.size() - |
+ MessageFramer::MessageHeader::header_size(), |
+ _)) |
+ .WillOnce(DoAll(FillBufferFromString<0>(serialized_message.substr( |
+ MessageFramer::MessageHeader::header_size(), |
+ serialized_message.size() - |
+ MessageFramer::MessageHeader::header_size() - 1)), |
+ EnqueueCallback<2>(&socket_cbs), |
+ Return(net::ERR_IO_PENDING))) |
+ .RetiresOnSaturation(); |
+ EXPECT_CALL(*delegate_, OnError(ChannelError::CAST_SOCKET_ERROR)); |
+ transport_->Start(); |
+ // Header read is OK. |
+ socket_cbs.Pop(MessageFramer::MessageHeader::header_size()); |
+ // Body read fails. |
+ socket_cbs.Pop(net::ERR_CONNECTION_RESET); |
+ EXPECT_EQ(proto::SOCKET_READ, logger_->GetLastErrors(kChannelId).event_type); |
+ EXPECT_EQ(net::ERR_CONNECTION_RESET, |
+ logger_->GetLastErrors(kChannelId).net_return_value); |
+} |
+ |
+TEST_F(CastTransportTest, TestReadCorruptedMessageAsync) { |
+ CompletionQueue socket_cbs; |
+ |
+ CastMessage message = CreateCastMessage(); |
+ std::string serialized_message; |
+ EXPECT_TRUE(MessageFramer::Serialize(message, &serialized_message)); |
+ |
+ // Corrupt the serialized message body(set it to X's). |
+ for (size_t i = MessageFramer::MessageHeader::header_size(); |
+ i < serialized_message.size(); |
+ ++i) { |
+ serialized_message[i] = 'x'; |
+ } |
+ |
+ EXPECT_CALL(*delegate_, Start()); |
+ // Read bytes [0, 3]. |
+ EXPECT_CALL(mock_socket_, |
+ Read(NotNull(), MessageFramer::MessageHeader::header_size(), _)) |
+ .WillOnce(DoAll(FillBufferFromString<0>(serialized_message), |
+ EnqueueCallback<2>(&socket_cbs), |
+ Return(net::ERR_IO_PENDING))) |
+ .RetiresOnSaturation(); |
+ // Read bytes [4, n]. |
+ EXPECT_CALL(mock_socket_, |
+ Read(NotNull(), |
+ serialized_message.size() - |
+ MessageFramer::MessageHeader::header_size(), |
+ _)) |
+ .WillOnce(DoAll(FillBufferFromString<0>(serialized_message.substr( |
+ MessageFramer::MessageHeader::header_size(), |
+ serialized_message.size() - |
+ MessageFramer::MessageHeader::header_size() - 1)), |
+ EnqueueCallback<2>(&socket_cbs), |
+ Return(net::ERR_IO_PENDING))) |
+ .RetiresOnSaturation(); |
+ |
+ EXPECT_CALL(*delegate_, OnError(ChannelError::INVALID_MESSAGE)); |
+ transport_->Start(); |
+ socket_cbs.Pop(MessageFramer::MessageHeader::header_size()); |
+ socket_cbs.Pop(serialized_message.size() - |
+ MessageFramer::MessageHeader::header_size()); |
+} |
+ |
+// ---------------------------------------------------------------------------- |
+// Synchronous read tests |
+TEST_F(CastTransportTest, TestFullReadSync) { |
+ InSequence s; |
+ CastMessage message = CreateCastMessage(); |
+ std::string serialized_message; |
+ EXPECT_TRUE(MessageFramer::Serialize(message, &serialized_message)); |
+ |
+ EXPECT_CALL(*delegate_, Start()); |
+ |
+ // Read bytes [0, 3]. |
+ EXPECT_CALL(mock_socket_, |
+ Read(NotNull(), MessageFramer::MessageHeader::header_size(), _)) |
+ .WillOnce(DoAll(FillBufferFromString<0>(serialized_message), |
+ Return(MessageFramer::MessageHeader::header_size()))) |
+ .RetiresOnSaturation(); |
+ // Read bytes [4, n]. |
+ EXPECT_CALL(mock_socket_, |
+ Read(NotNull(), |
+ serialized_message.size() - |
+ MessageFramer::MessageHeader::header_size(), |
+ _)) |
+ .WillOnce(DoAll(FillBufferFromString<0>(serialized_message.substr( |
+ MessageFramer::MessageHeader::header_size(), |
+ serialized_message.size() - |
+ MessageFramer::MessageHeader::header_size())), |
+ Return(serialized_message.size() - |
+ MessageFramer::MessageHeader::header_size()))) |
+ .RetiresOnSaturation(); |
+ EXPECT_CALL(*delegate_, OnMessage(EqualsProto(message))); |
+ // Async result in order to discontinue the read loop. |
+ EXPECT_CALL(mock_socket_, |
+ Read(NotNull(), MessageFramer::MessageHeader::header_size(), _)) |
+ .WillOnce(Return(net::ERR_IO_PENDING)); |
+ transport_->Start(); |
+} |
+ |
+TEST_F(CastTransportTest, TestPartialReadSync) { |
+ InSequence s; |
+ |
+ CastMessage message = CreateCastMessage(); |
+ std::string serialized_message; |
+ EXPECT_TRUE(MessageFramer::Serialize(message, &serialized_message)); |
+ |
+ EXPECT_CALL(*delegate_, Start()); |
+ |
+ // Read bytes [0, 3]. |
+ EXPECT_CALL(mock_socket_, |
+ Read(NotNull(), MessageFramer::MessageHeader::header_size(), _)) |
+ .WillOnce(DoAll(FillBufferFromString<0>(serialized_message), |
+ Return(MessageFramer::MessageHeader::header_size()))) |
+ .RetiresOnSaturation(); |
+ // Read bytes [4, n-1]. |
+ EXPECT_CALL(mock_socket_, |
+ Read(NotNull(), |
+ serialized_message.size() - |
+ MessageFramer::MessageHeader::header_size(), |
+ _)) |
+ .WillOnce(DoAll(FillBufferFromString<0>(serialized_message.substr( |
+ MessageFramer::MessageHeader::header_size(), |
+ serialized_message.size() - |
+ MessageFramer::MessageHeader::header_size() - 1)), |
+ Return(serialized_message.size() - |
+ MessageFramer::MessageHeader::header_size() - 1))) |
+ .RetiresOnSaturation(); |
+ // Read final byte. |
+ EXPECT_CALL(mock_socket_, Read(NotNull(), 1, _)) |
+ .WillOnce(DoAll(FillBufferFromString<0>(serialized_message.substr( |
+ serialized_message.size() - 1, 1)), |
+ Return(1))) |
+ .RetiresOnSaturation(); |
+ EXPECT_CALL(*delegate_, OnMessage(EqualsProto(message))); |
+ EXPECT_CALL(mock_socket_, |
+ Read(NotNull(), MessageFramer::MessageHeader::header_size(), _)) |
+ .WillOnce(Return(net::ERR_IO_PENDING)); |
+ transport_->Start(); |
+} |
+ |
+TEST_F(CastTransportTest, TestReadErrorInHeaderSync) { |
+ InSequence s; |
+ CastMessage message = CreateCastMessage(); |
+ std::string serialized_message; |
+ EXPECT_TRUE(MessageFramer::Serialize(message, &serialized_message)); |
+ |
+ EXPECT_CALL(*delegate_, Start()); |
+ |
+ // Read bytes [0, 3]. |
+ EXPECT_CALL(mock_socket_, |
+ Read(NotNull(), MessageFramer::MessageHeader::header_size(), _)) |
+ .WillOnce(DoAll(FillBufferFromString<0>(serialized_message), |
+ Return(net::ERR_CONNECTION_RESET))) |
+ .RetiresOnSaturation(); |
+ EXPECT_CALL(*delegate_, OnError(ChannelError::CAST_SOCKET_ERROR)); |
+ transport_->Start(); |
+} |
+ |
+TEST_F(CastTransportTest, TestReadErrorInBodySync) { |
+ CastMessage message = CreateCastMessage(); |
+ std::string serialized_message; |
+ EXPECT_TRUE(MessageFramer::Serialize(message, &serialized_message)); |
+ |
+ EXPECT_CALL(*delegate_, Start()); |
+ |
+ // Read bytes [0, 3]. |
+ EXPECT_CALL(mock_socket_, |
+ Read(NotNull(), MessageFramer::MessageHeader::header_size(), _)) |
+ .WillOnce(DoAll(FillBufferFromString<0>(serialized_message), |
+ Return(MessageFramer::MessageHeader::header_size()))) |
+ .RetiresOnSaturation(); |
+ // Read bytes [4, n-1]. |
+ EXPECT_CALL(mock_socket_, |
+ Read(NotNull(), |
+ serialized_message.size() - |
+ MessageFramer::MessageHeader::header_size(), |
+ _)) |
+ .WillOnce(DoAll(FillBufferFromString<0>(serialized_message.substr( |
+ MessageFramer::MessageHeader::header_size(), |
+ serialized_message.size() - |
+ MessageFramer::MessageHeader::header_size() - 1)), |
+ Return(net::ERR_CONNECTION_RESET))) |
+ .RetiresOnSaturation(); |
+ EXPECT_CALL(*delegate_, OnError(ChannelError::CAST_SOCKET_ERROR)); |
+ transport_->Start(); |
+ EXPECT_EQ(proto::SOCKET_READ, logger_->GetLastErrors(kChannelId).event_type); |
+ EXPECT_EQ(net::ERR_CONNECTION_RESET, |
+ logger_->GetLastErrors(kChannelId).net_return_value); |
+} |
+ |
+TEST_F(CastTransportTest, TestReadCorruptedMessageSync) { |
+ InSequence s; |
+ CastMessage message = CreateCastMessage(); |
+ std::string serialized_message; |
+ EXPECT_TRUE(MessageFramer::Serialize(message, &serialized_message)); |
+ |
+ // Corrupt the serialized message body(set it to X's). |
+ for (size_t i = MessageFramer::MessageHeader::header_size(); |
+ i < serialized_message.size(); |
+ ++i) { |
+ serialized_message[i] = 'x'; |
+ } |
+ |
+ EXPECT_CALL(*delegate_, Start()); |
+ |
+ // Read bytes [0, 3]. |
+ EXPECT_CALL(mock_socket_, |
+ Read(NotNull(), MessageFramer::MessageHeader::header_size(), _)) |
+ .WillOnce(DoAll(FillBufferFromString<0>(serialized_message), |
+ Return(MessageFramer::MessageHeader::header_size()))) |
+ .RetiresOnSaturation(); |
+ // Read bytes [4, n]. |
+ EXPECT_CALL(mock_socket_, |
+ Read(NotNull(), |
+ serialized_message.size() - |
+ MessageFramer::MessageHeader::header_size(), |
+ _)) |
+ .WillOnce(DoAll(FillBufferFromString<0>(serialized_message.substr( |
+ MessageFramer::MessageHeader::header_size(), |
+ serialized_message.size() - |
+ MessageFramer::MessageHeader::header_size() - 1)), |
+ Return(serialized_message.size() - |
+ MessageFramer::MessageHeader::header_size()))) |
+ .RetiresOnSaturation(); |
+ EXPECT_CALL(*delegate_, OnError(ChannelError::INVALID_MESSAGE)); |
+ transport_->Start(); |
+} |
+} // namespace cast_channel |
+} // namespace api |
+} // namespace extensions |