OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2015 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 "remoting/protocol/quic_channel_factory.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/message_loop/message_loop.h" | |
9 #include "base/run_loop.h" | |
10 #include "net/base/io_buffer.h" | |
11 #include "net/base/net_errors.h" | |
12 #include "net/base/test_completion_callback.h" | |
13 #include "net/quic/p2p/quic_p2p_session.h" | |
14 #include "net/quic/p2p/quic_p2p_stream.h" | |
15 #include "net/socket/socket.h" | |
16 #include "remoting/base/constants.h" | |
17 #include "remoting/protocol/connection_tester.h" | |
18 #include "remoting/protocol/fake_datagram_socket.h" | |
19 #include "remoting/protocol/p2p_stream_socket.h" | |
20 #include "testing/gmock/include/gmock/gmock.h" | |
21 #include "testing/gtest/include/gtest/gtest.h" | |
22 | |
23 using testing::_; | |
24 using testing::AtMost; | |
25 using testing::InvokeWithoutArgs; | |
26 | |
27 namespace remoting { | |
28 namespace protocol { | |
29 | |
30 namespace { | |
31 | |
32 const int kMessageSize = 1024; | |
33 const int kMessages = 100; | |
34 | |
35 const char kTestChannelName[] = "test"; | |
36 const char kTestChannelName2[] = "test2"; | |
37 | |
38 } // namespace | |
39 | |
40 class QuicChannelFactoryTest : public testing::Test, | |
41 public testing::WithParamInterface<bool> { | |
42 public: | |
43 void DeleteAll() { | |
44 host_channel1_.reset(); | |
45 host_channel2_.reset(); | |
46 client_channel1_.reset(); | |
47 client_channel2_.reset(); | |
48 host_quic_.reset(); | |
49 client_quic_.reset(); | |
50 } | |
51 | |
52 void FailedReadDeleteAll(int result) { | |
53 EXPECT_NE(net::OK, result); | |
54 DeleteAll(); | |
55 } | |
56 | |
57 void OnChannelConnected(scoped_ptr<P2PStreamSocket>* storage, | |
58 int* counter, | |
59 base::RunLoop* run_loop, | |
60 scoped_ptr<P2PStreamSocket> socket) { | |
61 *storage = socket.Pass(); | |
62 if (counter) { | |
63 --(*counter); | |
64 EXPECT_GE(*counter, 0); | |
65 if (*counter == 0) | |
66 run_loop->Quit(); | |
67 } | |
68 } | |
69 | |
70 void OnChannelConnectedExpectFail(scoped_ptr<P2PStreamSocket> socket) { | |
71 EXPECT_FALSE(socket); | |
72 host_quic_->CancelChannelCreation(kTestChannelName2); | |
73 DeleteAll(); | |
74 } | |
75 | |
76 void OnChannelConnectedNotReached(scoped_ptr<P2PStreamSocket> socket) { | |
77 NOTREACHED(); | |
78 } | |
79 | |
80 protected: | |
81 void Initialize() { | |
82 host_base_channel_factory_.PairWith(&client_base_channel_factory_); | |
83 host_base_channel_factory_.set_asynchronous_create(GetParam()); | |
84 client_base_channel_factory_.set_asynchronous_create(GetParam()); | |
85 | |
86 const char kTestSessionId[] = "123123"; | |
87 host_quic_.reset(new QuicChannelFactory(kTestSessionId, true)); | |
88 client_quic_.reset(new QuicChannelFactory(kTestSessionId, false)); | |
89 | |
90 std::string message = client_quic_->CreateSessionInitiateConfigMessage(); | |
91 EXPECT_TRUE(host_quic_->ProcessSessionInitiateConfigMessage(message)); | |
92 message = host_quic_->CreateSessionAcceptConfigMessage(); | |
93 EXPECT_TRUE(client_quic_->ProcessSessionAcceptConfigMessage(message)); | |
94 | |
95 const char kTestSharedSecret[] = "Shared Secret"; | |
96 host_quic_->Start(&host_base_channel_factory_, kTestSharedSecret); | |
97 client_quic_->Start(&client_base_channel_factory_, kTestSharedSecret); | |
98 | |
99 FakeDatagramSocket* host_base_channel = | |
100 host_base_channel_factory_.GetFakeChannel(kQuicChannelName); | |
101 if (host_base_channel) | |
102 host_base_channel->set_async_send(GetParam()); | |
103 | |
104 FakeDatagramSocket* client_base_channel = | |
105 client_base_channel_factory_.GetFakeChannel(kQuicChannelName); | |
106 if (client_base_channel) | |
107 client_base_channel->set_async_send(GetParam()); | |
108 } | |
109 | |
110 void CreateChannel(const std::string& name, | |
111 scoped_ptr<P2PStreamSocket>* host_channel, | |
112 scoped_ptr<P2PStreamSocket>* client_channel) { | |
113 int counter = 2; | |
114 base::RunLoop run_loop; | |
115 host_quic_->CreateChannel( | |
116 name, | |
117 base::Bind(&QuicChannelFactoryTest::OnChannelConnected, | |
118 base::Unretained(this), host_channel, &counter, &run_loop)); | |
119 client_quic_->CreateChannel( | |
120 name, base::Bind(&QuicChannelFactoryTest::OnChannelConnected, | |
121 base::Unretained(this), client_channel, &counter, | |
122 &run_loop)); | |
123 | |
124 run_loop.Run(); | |
125 | |
126 EXPECT_TRUE(host_channel->get()); | |
127 EXPECT_TRUE(client_channel->get()); | |
128 } | |
129 | |
130 scoped_refptr<net::IOBufferWithSize> CreateTestBuffer(int size) { | |
131 scoped_refptr<net::IOBufferWithSize> result = | |
132 new net::IOBufferWithSize(size); | |
133 for (int i = 0; i < size; ++i) { | |
134 result->data()[i] = rand() % 256; | |
135 } | |
136 return result; | |
137 } | |
138 | |
139 base::MessageLoop message_loop_; | |
140 | |
141 FakeDatagramChannelFactory host_base_channel_factory_; | |
142 FakeDatagramChannelFactory client_base_channel_factory_; | |
143 | |
144 scoped_ptr<QuicChannelFactory> host_quic_; | |
145 scoped_ptr<QuicChannelFactory> client_quic_; | |
146 | |
147 scoped_ptr<P2PStreamSocket> host_channel1_; | |
148 scoped_ptr<P2PStreamSocket> client_channel1_; | |
149 scoped_ptr<P2PStreamSocket> host_channel2_; | |
150 scoped_ptr<P2PStreamSocket> client_channel2_; | |
151 }; | |
152 | |
153 INSTANTIATE_TEST_CASE_P(SyncWrite, | |
154 QuicChannelFactoryTest, | |
155 ::testing::Values(false)); | |
dcaiafa
2015/08/10 23:31:36
That's a neat trick!
| |
156 INSTANTIATE_TEST_CASE_P(AsyncWrite, | |
157 QuicChannelFactoryTest, | |
158 ::testing::Values(true)); | |
159 | |
160 TEST_P(QuicChannelFactoryTest, OneChannel) { | |
161 Initialize(); | |
162 | |
163 scoped_ptr<P2PStreamSocket> host_channel; | |
164 scoped_ptr<P2PStreamSocket> client_channel; | |
165 ASSERT_NO_FATAL_FAILURE( | |
166 CreateChannel(kTestChannelName, &host_channel, &client_channel)); | |
167 | |
168 StreamConnectionTester tester(host_channel.get(), client_channel.get(), | |
169 kMessageSize, kMessages); | |
170 tester.Start(); | |
171 message_loop_.Run(); | |
172 tester.CheckResults(); | |
173 } | |
174 | |
175 TEST_P(QuicChannelFactoryTest, TwoChannels) { | |
176 Initialize(); | |
177 | |
178 scoped_ptr<P2PStreamSocket> host_channel1_; | |
179 scoped_ptr<P2PStreamSocket> client_channel1_; | |
180 ASSERT_NO_FATAL_FAILURE( | |
181 CreateChannel(kTestChannelName, &host_channel1_, &client_channel1_)); | |
182 | |
183 scoped_ptr<P2PStreamSocket> host_channel2_; | |
184 scoped_ptr<P2PStreamSocket> client_channel2_; | |
185 ASSERT_NO_FATAL_FAILURE( | |
186 CreateChannel(kTestChannelName2, &host_channel2_, &client_channel2_)); | |
187 | |
188 StreamConnectionTester tester1(host_channel1_.get(), client_channel1_.get(), | |
189 kMessageSize, kMessages); | |
190 StreamConnectionTester tester2(host_channel2_.get(), client_channel2_.get(), | |
191 kMessageSize, kMessages); | |
192 tester1.Start(); | |
193 tester2.Start(); | |
194 while (!tester1.done() || !tester2.done()) { | |
195 message_loop_.Run(); | |
196 } | |
197 tester1.CheckResults(); | |
198 tester2.CheckResults(); | |
199 } | |
200 | |
201 TEST_P(QuicChannelFactoryTest, SendFail) { | |
202 Initialize(); | |
203 | |
204 scoped_ptr<P2PStreamSocket> host_channel1_; | |
205 scoped_ptr<P2PStreamSocket> client_channel1_; | |
206 ASSERT_NO_FATAL_FAILURE( | |
207 CreateChannel(kTestChannelName, &host_channel1_, &client_channel1_)); | |
208 | |
209 scoped_ptr<P2PStreamSocket> host_channel2_; | |
210 scoped_ptr<P2PStreamSocket> client_channel2_; | |
211 ASSERT_NO_FATAL_FAILURE( | |
212 CreateChannel(kTestChannelName2, &host_channel2_, &client_channel2_)); | |
213 | |
214 host_base_channel_factory_.GetFakeChannel(kQuicChannelName) | |
215 ->set_next_send_error(net::ERR_FAILED); | |
216 | |
217 scoped_refptr<net::IOBufferWithSize> buf = CreateTestBuffer(100); | |
218 | |
219 | |
220 // Try writing to a channel. This should result in all stream being closed due | |
221 // to an error. | |
222 { | |
223 net::TestCompletionCallback write_cb_1; | |
224 host_channel1_->Write(buf.get(), buf->size(), write_cb_1.callback()); | |
225 base::RunLoop().RunUntilIdle(); | |
226 } | |
227 | |
228 // Repeated attempt to write should result in an error. | |
229 { | |
230 net::TestCompletionCallback write_cb_1; | |
231 net::TestCompletionCallback write_cb_2; | |
232 EXPECT_NE(net::OK, host_channel1_->Write(buf.get(), buf->size(), | |
233 write_cb_1.callback())); | |
234 EXPECT_FALSE(write_cb_1.have_result()); | |
235 EXPECT_NE(net::OK, host_channel1_->Write(buf.get(), buf->size(), | |
236 write_cb_2.callback())); | |
237 EXPECT_FALSE(write_cb_2.have_result()); | |
238 } | |
239 } | |
240 | |
241 TEST_P(QuicChannelFactoryTest, DeleteWhenFailed) { | |
242 Initialize(); | |
243 | |
244 ASSERT_NO_FATAL_FAILURE( | |
245 CreateChannel(kTestChannelName, &host_channel1_, &client_channel1_)); | |
246 ASSERT_NO_FATAL_FAILURE( | |
247 CreateChannel(kTestChannelName2, &host_channel2_, &client_channel2_)); | |
248 | |
249 host_base_channel_factory_.GetFakeChannel(kQuicChannelName) | |
250 ->set_next_send_error(net::ERR_FAILED); | |
251 | |
252 scoped_refptr<net::IOBufferWithSize> read_buf = | |
253 new net::IOBufferWithSize(100); | |
254 | |
255 EXPECT_EQ(net::ERR_IO_PENDING, | |
256 host_channel1_->Read( | |
257 read_buf.get(), read_buf->size(), | |
258 base::Bind(&QuicChannelFactoryTest::FailedReadDeleteAll, | |
259 base::Unretained(this)))); | |
260 | |
261 // Try writing to a channel. This should result it DeleteAll() called and the | |
262 // connection torn down. | |
263 scoped_refptr<net::IOBufferWithSize> buf = CreateTestBuffer(100); | |
264 net::TestCompletionCallback write_cb_1; | |
265 host_channel1_->Write(buf.get(), buf->size(), write_cb_1.callback()); | |
266 | |
267 base::RunLoop().RunUntilIdle(); | |
268 | |
269 // Check that the connection was torn down. | |
270 EXPECT_FALSE(host_quic_); | |
271 } | |
272 | |
273 TEST_P(QuicChannelFactoryTest, SessionFail) { | |
274 host_base_channel_factory_.set_fail_create(true); | |
275 Initialize(); | |
276 | |
277 host_quic_->CreateChannel( | |
278 kTestChannelName, | |
279 base::Bind(&QuicChannelFactoryTest::OnChannelConnectedExpectFail, | |
280 base::Unretained(this))); | |
281 | |
282 // host_quic_ may be destroyed at this point in sync mode. | |
283 if (host_quic_) { | |
284 host_quic_->CreateChannel( | |
285 kTestChannelName2, | |
286 base::Bind(&QuicChannelFactoryTest::OnChannelConnectedNotReached, | |
287 base::Unretained(this))); | |
288 } | |
289 | |
290 base::RunLoop().RunUntilIdle(); | |
291 | |
292 // Check that DeleteAll() was called and the connection was torn down. | |
293 EXPECT_FALSE(host_quic_); | |
294 } | |
295 | |
296 // Verify that the host just ignores incoming stream with unexpected name. | |
297 TEST_P(QuicChannelFactoryTest, UnknownName) { | |
298 Initialize(); | |
299 | |
300 // Create a new channel from the client side. | |
301 client_quic_->CreateChannel( | |
302 kTestChannelName, base::Bind(&QuicChannelFactoryTest::OnChannelConnected, | |
303 base::Unretained(this), &client_channel1_, | |
304 nullptr, nullptr)); | |
305 base::RunLoop().RunUntilIdle(); | |
306 | |
307 EXPECT_EQ(0U, host_quic_->GetP2PSessionForTests()->GetNumOpenStreams()); | |
308 } | |
309 | |
310 // Verify that incoming streams that have received only partial name are | |
311 // destroyed correctly. | |
312 TEST_P(QuicChannelFactoryTest, SendPartialName) { | |
313 Initialize(); | |
314 | |
315 base::RunLoop().RunUntilIdle(); | |
316 | |
317 net::QuicP2PSession* session = client_quic_->GetP2PSessionForTests(); | |
318 net::QuicP2PStream* stream = session->CreateOutgoingDynamicStream(); | |
319 | |
320 std::string name = kTestChannelName; | |
321 // Send only half of the name to the host. | |
322 stream->WriteHeader(std::string(1, static_cast<char>(name.size())) + | |
323 name.substr(0, name.size() / 2)); | |
324 | |
325 base::RunLoop().RunUntilIdle(); | |
326 | |
327 // Host should have received the new stream and is still waiting for the name. | |
328 EXPECT_EQ(1U, host_quic_->GetP2PSessionForTests()->GetNumOpenStreams()); | |
329 | |
330 session->CloseStream(stream->id()); | |
331 base::RunLoop().RunUntilIdle(); | |
332 | |
333 // Verify that the stream was closed on the host side. | |
334 EXPECT_EQ(0U, host_quic_->GetP2PSessionForTests()->GetNumOpenStreams()); | |
335 | |
336 // Create another stream with only partial name and tear down connection while | |
337 // it's still pending. | |
338 stream = session->CreateOutgoingDynamicStream(); | |
339 stream->WriteHeader(std::string(1, static_cast<char>(name.size())) + | |
340 name.substr(0, name.size() / 2)); | |
341 base::RunLoop().RunUntilIdle(); | |
342 EXPECT_EQ(1U, host_quic_->GetP2PSessionForTests()->GetNumOpenStreams()); | |
343 } | |
344 | |
345 } // namespace protocol | |
346 } // namespace remoting | |
OLD | NEW |