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 |