1 // Copyright (c) 2012 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. 4 5 #include "base/memory/ref_counted.h" 6 #include "base/memory/scoped_ptr.h" 7 #include "base/message_loop/message_loop.h" 8 #include "jingle/glue/channel_socket_adapter.h" 9 #include "net/base/io_buffer.h" 10 #include "net/base/net_errors.h" 11 #include "net/socket/socket.h" 12 #include "testing/gmock/include/gmock/gmock.h" 13 #include "testing/gtest/include/gtest/gtest.h" 14 #include "third_party/libjingle/source/talk/p2p/base/transportchannel.h" 15 16 using net::IOBuffer; 17 18 using testing::_; 19 using testing::Return; 20 21 namespace jingle_glue { 22 23 namespace { 24 const int kBufferSize = 4096; 25 const char kTestData[] = "data"; 26 const int kTestDataSize = 4; 27 const int kTestError = -32123; 28 } // namespace 29 30 class MockTransportChannel : public cricket::TransportChannel { 31 public: 32 MockTransportChannel() : cricket::TransportChannel(std::string(), 0) { 33 set_writable(true); 34 set_readable(true); 35 } 36 37 MOCK_METHOD4(SendPacket, int(const char* data, 38 size_t len, 39 talk_base::DiffServCodePoint dscp, 40 int flags)); 41 MOCK_METHOD2(SetOption, int(talk_base::Socket::Option opt, int value)); 42 MOCK_METHOD0(GetError, int()); 43 MOCK_CONST_METHOD0(GetIceRole, cricket::IceRole()); 44 MOCK_METHOD1(GetStats, bool(cricket::ConnectionInfos* infos)); 45 MOCK_CONST_METHOD0(IsDtlsActive, bool()); 46 MOCK_CONST_METHOD1(GetSslRole, bool(talk_base::SSLRole* role)); 47 MOCK_METHOD1(SetSrtpCiphers, bool(const std::vector<std::string>& ciphers)); 48 MOCK_METHOD1(GetSrtpCipher, bool(std::string* cipher)); 49 MOCK_CONST_METHOD1(GetLocalIdentity, bool(talk_base::SSLIdentity** identity)); 50 MOCK_CONST_METHOD1(GetRemoteCertificate, 51 bool(talk_base::SSLCertificate** cert)); 52 MOCK_METHOD6(ExportKeyingMaterial, bool(const std::string& label, 53 const uint8* context, 54 size_t context_len, 55 bool use_context, 56 uint8* result, 57 size_t result_len)); 58 }; 59 60 class TransportChannelSocketAdapterTest : public testing::Test { 61 public: 62 TransportChannelSocketAdapterTest() 63 : callback_(base::Bind(&TransportChannelSocketAdapterTest::Callback, 64 base::Unretained(this))), 65 callback_result_(0) { 66 } 67 68 protected: 69 virtual void SetUp() { 70 target_.reset(new TransportChannelSocketAdapter(&channel_)); 71 } 72 73 void Callback(int result) { 74 callback_result_ = result; 75 } 76 77 MockTransportChannel channel_; 78 scoped_ptr<TransportChannelSocketAdapter> target_; 79 net::CompletionCallback callback_; 80 int callback_result_; 81 base::MessageLoopForIO message_loop_; 82 }; 83 84 // Verify that Read() returns net::ERR_IO_PENDING. 85 TEST_F(TransportChannelSocketAdapterTest, Read) { 86 scoped_refptr<IOBuffer> buffer(new IOBuffer(kBufferSize)); 87 88 int result = target_->Read(buffer.get(), kBufferSize, callback_); 89 ASSERT_EQ(net::ERR_IO_PENDING, result); 90 91 channel_.SignalReadPacket(&channel_, kTestData, kTestDataSize, 92 talk_base::CreatePacketTime(0), 0); 93 EXPECT_EQ(kTestDataSize, callback_result_); 94 } 95 96 // Verify that Read() after Close() returns error. 97 TEST_F(TransportChannelSocketAdapterTest, ReadClose) { 98 scoped_refptr<IOBuffer> buffer(new IOBuffer(kBufferSize)); 99 100 int result = target_->Read(buffer.get(), kBufferSize, callback_); 101 ASSERT_EQ(net::ERR_IO_PENDING, result); 102 103 target_->Close(kTestError); 104 EXPECT_EQ(kTestError, callback_result_); 105 106 // All Read() calls after Close() should return the error. 107 EXPECT_EQ(kTestError, target_->Read(buffer.get(), kBufferSize, callback_)); 108 } 109 110 // Verify that Write sends the packet and returns correct result. 111 TEST_F(TransportChannelSocketAdapterTest, Write) { 112 scoped_refptr<IOBuffer> buffer(new IOBuffer(kTestDataSize)); 113 114 EXPECT_CALL(channel_, SendPacket(buffer->data(), kTestDataSize, 115 talk_base::DSCP_NO_CHANGE, 0)) 116 .WillOnce(Return(kTestDataSize)); 117 118 int result = target_->Write(buffer.get(), kTestDataSize, callback_); 119 EXPECT_EQ(kTestDataSize, result); 120 } 121 122 // Verify that the message is still sent if Write() is called while 123 // socket is not open yet. The result is the packet is lost. 124 TEST_F(TransportChannelSocketAdapterTest, WritePending) { 125 scoped_refptr<IOBuffer> buffer(new IOBuffer(kTestDataSize)); 126 127 EXPECT_CALL(channel_, SendPacket(buffer->data(), kTestDataSize, 128 talk_base::DSCP_NO_CHANGE, 0)) 129 .Times(1) 130 .WillOnce(Return(SOCKET_ERROR)); 131 132 EXPECT_CALL(channel_, GetError()) 133 .WillOnce(Return(EWOULDBLOCK)); 134 135 int result = target_->Write(buffer.get(), kTestDataSize, callback_); 136 ASSERT_EQ(net::OK, result); 137 } 138 139 } // namespace jingle_glue 140