| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/ref_counted.h" | 5 #include "base/ref_counted.h" |
| 6 #include "base/waitable_event.h" |
| 6 #include "media/base/data_buffer.h" | 7 #include "media/base/data_buffer.h" |
| 7 #include "remoting/jingle_glue/jingle_channel.h" | 8 #include "remoting/jingle_glue/jingle_channel.h" |
| 8 #include "remoting/jingle_glue/jingle_thread.h" | 9 #include "remoting/jingle_glue/jingle_thread.h" |
| 9 #include "testing/gmock/include/gmock/gmock.h" | 10 #include "testing/gmock/include/gmock/gmock.h" |
| 10 #include "testing/gtest/include/gtest/gtest.h" | 11 #include "testing/gtest/include/gtest/gtest.h" |
| 11 #include "third_party/libjingle/source/talk/base/stream.h" | 12 #include "third_party/libjingle/source/talk/base/stream.h" |
| 12 | 13 |
| 13 using testing::_; | 14 using testing::_; |
| 14 using testing::Return; | 15 using testing::Return; |
| 15 using testing::Mock; | 16 using testing::Mock; |
| 16 using testing::SetArgumentPointee; | 17 using testing::SetArgumentPointee; |
| 17 | 18 |
| 18 namespace remoting { | 19 namespace remoting { |
| 19 | 20 |
| 20 namespace { | 21 namespace { |
| 21 // Size of test buffer in bytes. | 22 // Size of test buffer in bytes. |
| 22 const size_t kBufferSize = 100; | 23 const size_t kBufferSize = 100; |
| 23 } // namespace | 24 } // namespace |
| 24 | 25 |
| 25 class MockCallback : public JingleChannel::Callback { | 26 class MockJingleChannelCallback : public JingleChannel::Callback { |
| 26 public: | 27 public: |
| 27 MOCK_METHOD2(OnStateChange, void(JingleChannel*, JingleChannel::State)); | 28 MOCK_METHOD2(OnStateChange, void(JingleChannel*, JingleChannel::State)); |
| 28 MOCK_METHOD2(OnPacketReceived, void(JingleChannel*, | 29 MOCK_METHOD2(OnPacketReceived, void(JingleChannel*, |
| 29 scoped_refptr<media::DataBuffer>)); | 30 scoped_refptr<media::DataBuffer>)); |
| 30 }; | 31 }; |
| 31 | 32 |
| 32 class MockStream : public talk_base::StreamInterface { | 33 class MockStream : public talk_base::StreamInterface { |
| 33 public: | 34 public: |
| 34 virtual ~MockStream() {} | 35 virtual ~MockStream() {} |
| 35 MOCK_CONST_METHOD0(GetState, talk_base::StreamState()); | 36 MOCK_CONST_METHOD0(GetState, talk_base::StreamState()); |
| 36 | 37 |
| 37 MOCK_METHOD4(Read, talk_base::StreamResult(void*, size_t, size_t*, int*)); | 38 MOCK_METHOD4(Read, talk_base::StreamResult(void*, size_t, size_t*, int*)); |
| 38 MOCK_METHOD4(Write, talk_base::StreamResult(const void*, size_t, | 39 MOCK_METHOD4(Write, talk_base::StreamResult(const void*, size_t, |
| 39 size_t*, int*)); | 40 size_t*, int*)); |
| 40 MOCK_CONST_METHOD1(GetAvailable, bool(size_t*)); | 41 MOCK_CONST_METHOD1(GetAvailable, bool(size_t*)); |
| 41 MOCK_METHOD0(Close, void()); | 42 MOCK_METHOD0(Close, void()); |
| 42 | 43 |
| 43 MOCK_METHOD3(PostEvent, void(talk_base::Thread*, int, int)); | 44 MOCK_METHOD3(PostEvent, void(talk_base::Thread*, int, int)); |
| 44 MOCK_METHOD2(PostEvent, void(int, int)); | 45 MOCK_METHOD2(PostEvent, void(int, int)); |
| 45 }; | 46 }; |
| 46 | 47 |
| 47 TEST(JingleChannelTest, Init) { | 48 class JingleChannelTest : public testing::Test { |
| 48 JingleThread thread; | 49 public: |
| 50 virtual ~JingleChannelTest() { } |
| 49 | 51 |
| 50 MockStream* stream = new MockStream(); | 52 // A helper that calls OnStreamEvent(). Need this because we want |
| 51 MockCallback callback; | 53 // to call it on the jingle thread. |
| 54 static void StreamEvent(JingleChannel* channel, |
| 55 talk_base::StreamInterface* stream, |
| 56 int event, int error, |
| 57 base::WaitableEvent* done_event) { |
| 58 channel->OnStreamEvent(stream, event, error); |
| 59 if (done_event) |
| 60 done_event->Signal(); |
| 61 } |
| 52 | 62 |
| 53 EXPECT_CALL(*stream, GetState()) | 63 static void OnClosed(bool* called) { |
| 64 *called = true; |
| 65 } |
| 66 |
| 67 protected: |
| 68 virtual void SetUp() { |
| 69 stream_ = new MockStream(); // Freed by the channel. |
| 70 channel_ = new JingleChannel(&callback_); |
| 71 channel_->thread_ = &thread_; |
| 72 channel_->stream_.reset(stream_); |
| 73 } |
| 74 |
| 75 JingleThread thread_; |
| 76 MockStream* stream_; |
| 77 MockJingleChannelCallback callback_; |
| 78 scoped_refptr<JingleChannel> channel_; |
| 79 }; |
| 80 |
| 81 TEST_F(JingleChannelTest, Init) { |
| 82 EXPECT_CALL(*stream_, GetState()) |
| 54 .Times(1) | 83 .Times(1) |
| 55 .WillRepeatedly(Return(talk_base::SS_OPENING)); | 84 .WillRepeatedly(Return(talk_base::SS_OPENING)); |
| 56 | 85 |
| 57 scoped_refptr<JingleChannel> channel = new JingleChannel(&callback); | 86 EXPECT_CALL(callback_, OnStateChange(channel_.get(), |
| 58 | 87 JingleChannel::CONNECTING)) |
| 59 EXPECT_CALL(callback, OnStateChange(channel.get(), JingleChannel::CONNECTING)) | |
| 60 .Times(1); | 88 .Times(1); |
| 61 | 89 |
| 62 thread.Start(); | 90 thread_.Start(); |
| 63 | 91 |
| 64 EXPECT_EQ(JingleChannel::INITIALIZING, channel->state()); | 92 EXPECT_EQ(JingleChannel::INITIALIZING, channel_->state()); |
| 65 channel->Init(&thread, stream, "user@domain.com"); | 93 channel_->Init(&thread_, stream_, "user@domain.com"); |
| 66 EXPECT_EQ(JingleChannel::CONNECTING, channel->state()); | 94 EXPECT_EQ(JingleChannel::CONNECTING, channel_->state()); |
| 67 channel->state_ = JingleChannel::CLOSED; | 95 channel_->closed_ = true; |
| 68 | 96 |
| 69 thread.Stop(); | 97 thread_.Stop(); |
| 70 } | 98 } |
| 71 | 99 |
| 72 TEST(JingleChannelTest, Write) { | 100 TEST_F(JingleChannelTest, Write) { |
| 73 JingleThread thread; | |
| 74 MockStream* stream = new MockStream(); // Freed by the channel. | |
| 75 MockCallback callback; | |
| 76 | |
| 77 scoped_refptr<media::DataBuffer> data = new media::DataBuffer(kBufferSize); | 101 scoped_refptr<media::DataBuffer> data = new media::DataBuffer(kBufferSize); |
| 78 data->SetDataSize(kBufferSize); | 102 data->SetDataSize(kBufferSize); |
| 79 | 103 |
| 80 EXPECT_CALL(*stream, Write(static_cast<const void*>(data->GetData()), | 104 EXPECT_CALL(*stream_, Write(static_cast<const void*>(data->GetData()), |
| 81 kBufferSize, _, _)) | 105 kBufferSize, _, _)) |
| 82 .WillOnce(DoAll(SetArgumentPointee<2>(kBufferSize), | 106 .WillOnce(DoAll(SetArgumentPointee<2>(kBufferSize), |
| 83 Return(talk_base::SR_SUCCESS))); | 107 Return(talk_base::SR_SUCCESS))); |
| 84 | 108 |
| 85 scoped_refptr<JingleChannel> channel = new JingleChannel(&callback); | 109 channel_->state_ = JingleChannel::OPEN; |
| 86 | 110 thread_.Start(); |
| 87 channel->thread_ = &thread; | 111 channel_->Write(data); |
| 88 channel->stream_.reset(stream); | 112 thread_.Stop(); |
| 89 channel->state_ = JingleChannel::OPEN; | 113 channel_->closed_ = true; |
| 90 thread.Start(); | |
| 91 channel->Write(data); | |
| 92 thread.Stop(); | |
| 93 channel->state_ = JingleChannel::CLOSED; | |
| 94 } | 114 } |
| 95 | 115 |
| 96 TEST(JingleChannelTest, Read) { | 116 TEST_F(JingleChannelTest, Read) { |
| 97 JingleThread thread; | |
| 98 MockStream* stream = new MockStream(); // Freed by the channel. | |
| 99 MockCallback callback; | |
| 100 | |
| 101 scoped_refptr<media::DataBuffer> data = new media::DataBuffer(kBufferSize); | 117 scoped_refptr<media::DataBuffer> data = new media::DataBuffer(kBufferSize); |
| 102 data->SetDataSize(kBufferSize); | 118 data->SetDataSize(kBufferSize); |
| 103 | 119 |
| 104 scoped_refptr<JingleChannel> channel = new JingleChannel(&callback); | 120 EXPECT_CALL(callback_, OnPacketReceived(channel_.get(), _)) |
| 105 | |
| 106 EXPECT_CALL(callback, OnPacketReceived(channel.get(), _)) | |
| 107 .Times(1); | 121 .Times(1); |
| 108 | 122 |
| 109 EXPECT_CALL(*stream, GetAvailable(_)) | 123 EXPECT_CALL(*stream_, GetAvailable(_)) |
| 110 .WillOnce(DoAll(SetArgumentPointee<0>(kBufferSize), | 124 .WillOnce(DoAll(SetArgumentPointee<0>(kBufferSize), |
| 111 Return(true))) | 125 Return(true))) |
| 112 .WillOnce(DoAll(SetArgumentPointee<0>(0), | 126 .WillOnce(DoAll(SetArgumentPointee<0>(0), |
| 113 Return(true))); | 127 Return(true))); |
| 114 | 128 |
| 115 EXPECT_CALL(*stream, Read(_, kBufferSize, _, _)) | 129 EXPECT_CALL(*stream_, Read(_, kBufferSize, _, _)) |
| 116 .WillOnce(DoAll(SetArgumentPointee<2>(kBufferSize), | 130 .WillOnce(DoAll(SetArgumentPointee<2>(kBufferSize), |
| 117 Return(talk_base::SR_SUCCESS))); | 131 Return(talk_base::SR_SUCCESS))); |
| 118 | 132 |
| 119 channel->thread_ = &thread; | 133 channel_->state_ = JingleChannel::OPEN; |
| 120 channel->stream_.reset(stream); | 134 thread_.Start(); |
| 121 channel->state_ = JingleChannel::OPEN; | 135 |
| 122 thread.Start(); | 136 base::WaitableEvent done_event(true, false); |
| 123 channel->OnStreamEvent(stream, talk_base::SE_READ, 0); | 137 thread_.message_loop()->PostTask(FROM_HERE, NewRunnableFunction( |
| 124 thread.Stop(); | 138 &JingleChannelTest::StreamEvent, channel_.get(), stream_, |
| 125 channel->state_ = JingleChannel::CLOSED; | 139 talk_base::SE_READ, 0, &done_event)); |
| 140 done_event.Wait(); |
| 141 |
| 142 thread_.Stop(); |
| 143 |
| 144 channel_->closed_ = true; |
| 126 } | 145 } |
| 127 | 146 |
| 128 TEST(JingleChannelTest, Close) { | 147 TEST_F(JingleChannelTest, Close) { |
| 129 JingleThread thread; | 148 EXPECT_CALL(*stream_, Close()).Times(1); |
| 130 MockStream* stream = new MockStream(); // Freed by the channel. | 149 // Don't expect any calls except Close(). |
| 131 MockCallback callback; | 150 EXPECT_CALL(*stream_, GetAvailable(_)).Times(0); |
| 151 EXPECT_CALL(*stream_, Read(_, _, _, _)).Times(0); |
| 152 EXPECT_CALL(callback_, OnPacketReceived(_, _)).Times(0); |
| 132 | 153 |
| 133 EXPECT_CALL(*stream, Close()) | 154 thread_.Start(); |
| 155 channel_->Close(); |
| 156 // Verify that the channel doesn't call callback anymore. |
| 157 thread_.message_loop()->PostTask(FROM_HERE, NewRunnableFunction( |
| 158 &JingleChannelTest::StreamEvent, channel_.get(), stream_, |
| 159 talk_base::SE_READ, 0, static_cast<base::WaitableEvent*>(NULL))); |
| 160 thread_.Stop(); |
| 161 } |
| 162 |
| 163 TEST_F(JingleChannelTest, ClosedTask) { |
| 164 EXPECT_CALL(*stream_, Close()) |
| 134 .Times(1); | 165 .Times(1); |
| 135 | 166 |
| 136 scoped_refptr<JingleChannel> channel = new JingleChannel(&callback); | 167 thread_.Start(); |
| 168 bool closed = false; |
| 169 channel_->Close(NewRunnableFunction(&JingleChannelTest::OnClosed, |
| 170 &closed)); |
| 171 thread_.Stop(); |
| 172 EXPECT_TRUE(closed); |
| 173 } |
| 137 | 174 |
| 138 channel->thread_ = &thread; | 175 TEST_F(JingleChannelTest, DoubleClose) { |
| 139 channel->stream_.reset(stream); | 176 EXPECT_CALL(*stream_, Close()) |
| 140 channel->state_ = JingleChannel::OPEN; | |
| 141 | |
| 142 EXPECT_CALL(callback, OnStateChange(channel.get(), JingleChannel::CLOSED)) | |
| 143 .Times(1); | 177 .Times(1); |
| 144 | 178 |
| 145 thread.Start(); | 179 thread_.Start(); |
| 146 channel->Close(); | 180 bool closed1 = false; |
| 147 thread.Stop(); | 181 channel_->Close(NewRunnableFunction(&JingleChannelTest::OnClosed, |
| 182 &closed1)); |
| 183 bool closed2 = false; |
| 184 channel_->Close(NewRunnableFunction(&JingleChannelTest::OnClosed, |
| 185 &closed2)); |
| 186 thread_.Stop(); |
| 187 EXPECT_TRUE(closed1 && closed2); |
| 148 } | 188 } |
| 149 | 189 |
| 150 } // namespace remoting | 190 } // namespace remoting |
| OLD | NEW |