OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "net/spdy/spdy_proxy_client_socket.h" | |
6 | |
7 #include "base/utf_string_conversions.h" | |
8 #include "net/base/address_list.h" | |
9 #include "net/base/net_log.h" | |
10 #include "net/base/net_log_unittest.h" | |
11 #include "net/base/mock_host_resolver.h" | |
12 #include "net/base/test_completion_callback.h" | |
13 #include "net/base/winsock_init.h" | |
14 #include "net/http/http_response_info.h" | |
15 #include "net/http/http_response_headers.h" | |
16 #include "net/socket/client_socket_factory.h" | |
17 #include "net/socket/tcp_client_socket.h" | |
18 #include "net/socket/socket_test_util.h" | |
19 #include "net/spdy/spdy_protocol.h" | |
20 #include "net/spdy/spdy_session_pool.h" | |
21 #include "net/spdy/spdy_test_util.h" | |
22 #include "testing/platform_test.h" | |
23 #include "testing/gtest/include/gtest/gtest.h" | |
24 | |
25 //----------------------------------------------------------------------------- | |
26 | |
27 namespace { | |
28 | |
29 static const char kUrl[] = "https://www.google.com/"; | |
30 static const char kOriginHost[] = "www.google.com"; | |
31 static const int kOriginPort = 443; | |
32 static const char kOriginHostPort[] = "www.google.com:443"; | |
33 static const char kProxyUrl[] = "http://myproxy:6121/"; | |
34 static const char kProxyHost[] = "myproxy"; | |
35 static const int kProxyPort = 6121; | |
36 static const char kUserAgent[] = "Mozilla/1.0"; | |
37 | |
38 static const int kStreamId = 1; | |
39 | |
40 static const char kMsg1[] = "\0hello!\xff"; | |
41 static const int kLen1 = 8; | |
42 static const char kMsg2[] = "\012345678\0"; | |
43 static const int kLen2 = 10; | |
44 static const char kMsg3[] = "bye!"; | |
45 static const int kLen3 = 4; | |
46 static const char kMsg33[] = "bye!bye!"; | |
47 static const int kLen33 = kLen3 + kLen3; | |
48 | |
49 } // anonymous namespace | |
50 | |
51 namespace net { | |
52 | |
53 class SpdyProxyClientSocketTest : public PlatformTest { | |
54 public: | |
55 SpdyProxyClientSocketTest(); | |
56 | |
57 virtual void TearDown(); | |
58 | |
59 protected: | |
60 void Initialize(MockRead* reads, size_t reads_count, MockWrite* writes, | |
61 size_t writes_count); | |
62 spdy::SpdyFrame* ConstructConnectRequestFrame(); | |
63 spdy::SpdyFrame* ConstructConnectAuthRequestFrame(); | |
64 spdy::SpdyFrame* ConstructConnectReplyFrame(); | |
65 spdy::SpdyFrame* ConstructConnectAuthReplyFrame(); | |
66 spdy::SpdyFrame* ConstructConnectErrorReplyFrame(); | |
67 spdy::SpdyFrame* ConstructBodyFrame(const char* data, int length); | |
68 scoped_refptr<IOBufferWithSize> CreateBuffer(const char* data, int size); | |
69 void AssertConnectSucceeds(); | |
70 void AssertConnectionEstablished(); | |
71 void AssertSyncReadEquals(const char* data, int len); | |
72 void AssertAsyncReadEquals(const char* data, int len); | |
73 void AssertAsyncWriteSucceeds(const char* data, int len); | |
74 void AssertAsyncWriteWithReadsSucceeds(const char* data, int len, | |
75 int num_reads); | |
76 | |
77 void AddAuthToCache() { | |
78 const string16 kFoo(ASCIIToUTF16("foo")); | |
79 const string16 kBar(ASCIIToUTF16("bar")); | |
80 session_->auth_cache()->Add(GURL(kProxyUrl), "MyRealm1", "Basic", | |
81 "Basic realm=MyRealm1", kFoo, kBar, "/"); | |
82 } | |
83 | |
84 scoped_ptr<SpdyProxyClientSocket> sock_; | |
85 TestCompletionCallback callback_; | |
86 | |
87 private: | |
88 scoped_refptr<HttpNetworkSession> session_; | |
89 scoped_refptr<OrderedSocketData> data_; | |
90 SpdySessionDependencies session_deps_; | |
91 MockConnect connect_data_; | |
92 scoped_refptr<SpdySession> spdy_session_; | |
93 scoped_refptr<SpdyStream> spdy_stream_; | |
94 spdy::SpdyFramer framer_; | |
95 | |
96 std::string user_agent_; | |
97 GURL url_; | |
98 HostPortPair proxy_host_port_; | |
99 HostPortPair endpoint_host_port_pair_; | |
100 ProxyServer proxy_; | |
101 HostPortProxyPair endpoint_host_port_proxy_pair_; | |
102 scoped_refptr<TCPSocketParams> tcp_params_; | |
103 | |
104 DISALLOW_COPY_AND_ASSIGN(SpdyProxyClientSocketTest); | |
105 }; | |
106 | |
107 SpdyProxyClientSocketTest::SpdyProxyClientSocketTest() | |
108 : sock_(NULL), | |
109 callback_(), | |
110 session_(NULL), | |
111 data_(NULL), | |
112 session_deps_(), | |
113 connect_data_(false, OK), | |
114 spdy_session_(NULL), | |
115 spdy_stream_(NULL), | |
116 framer_(), | |
117 user_agent_(kUserAgent), | |
118 url_(kUrl), | |
119 proxy_host_port_(kProxyHost, kProxyPort), | |
120 endpoint_host_port_pair_(kOriginHost, kOriginPort), | |
121 proxy_(ProxyServer::SCHEME_HTTPS, proxy_host_port_), | |
122 endpoint_host_port_proxy_pair_(endpoint_host_port_pair_, proxy_), | |
123 tcp_params_(new TCPSocketParams(proxy_host_port_, LOWEST, url_, false)) { | |
124 } | |
125 | |
126 void SpdyProxyClientSocketTest::TearDown() { | |
127 if (session_ != NULL) | |
128 session_->spdy_session_pool()->CloseAllSessions(); | |
129 | |
130 spdy::SpdyFramer::set_enable_compression_default(true); | |
131 // Empty the current queue. | |
132 MessageLoop::current()->RunAllPending(); | |
133 PlatformTest::TearDown(); | |
134 } | |
135 | |
136 void SpdyProxyClientSocketTest::Initialize(MockRead* reads, | |
137 size_t reads_count, | |
138 MockWrite* writes, | |
139 size_t writes_count) { | |
140 data_ = new OrderedSocketData(reads, reads_count, writes, writes_count); | |
141 data_->set_connect_data(connect_data_); | |
142 | |
143 session_deps_.socket_factory->AddSocketDataProvider(data_.get()); | |
144 session_deps_.host_resolver->set_synchronous_mode(true); | |
145 | |
146 session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_); | |
147 SpdySession::SetSSLMode(false); | |
148 spdy::SpdyFramer::set_enable_compression_default(false); | |
149 | |
150 // Creates a new spdy session | |
151 spdy_session_ = | |
152 session_->spdy_session_pool()->Get(endpoint_host_port_proxy_pair_, | |
153 session_->mutable_spdy_settings(), | |
154 BoundNetLog()); | |
155 | |
156 // Perform the TCP connect | |
157 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); | |
158 EXPECT_EQ(OK, | |
159 connection->Init(endpoint_host_port_pair_.ToString(), tcp_params_, | |
160 LOWEST, NULL, session_->tcp_socket_pool(), | |
161 BoundNetLog())); | |
162 spdy_session_->InitializeWithSocket(connection.release(), false, OK); | |
163 | |
164 // Create the SPDY Stream | |
165 ASSERT_EQ( | |
166 OK, | |
167 spdy_session_->CreateStream(url_, LOWEST, &spdy_stream_, BoundNetLog(), | |
168 NULL)); | |
169 | |
170 // Create the SpdyProxyClientSocket | |
171 sock_.reset( | |
172 new SpdyProxyClientSocket(spdy_stream_, user_agent_, | |
173 endpoint_host_port_pair_, url_, | |
174 proxy_host_port_, session_->auth_cache(), | |
175 session_->http_auth_handler_factory())); | |
176 } | |
177 | |
178 scoped_refptr<IOBufferWithSize> SpdyProxyClientSocketTest::CreateBuffer( | |
179 const char* data, int size) { | |
180 scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(size)); | |
181 memcpy(buf->data(), data, size); | |
182 return buf; | |
183 } | |
184 | |
185 void SpdyProxyClientSocketTest::AssertConnectSucceeds() { | |
186 ASSERT_EQ(ERR_IO_PENDING, sock_->Connect(&callback_)); | |
187 ASSERT_EQ(OK, callback_.WaitForResult()); | |
188 } | |
189 | |
190 void SpdyProxyClientSocketTest::AssertConnectionEstablished() { | |
191 const HttpResponseInfo* response = sock_->GetConnectResponseInfo(); | |
192 ASSERT_TRUE(response != NULL); | |
193 ASSERT_EQ(200, response->headers->response_code()); | |
194 ASSERT_EQ("Connection Established", response->headers->GetStatusText()); | |
195 } | |
196 | |
197 void SpdyProxyClientSocketTest::AssertSyncReadEquals(const char* data, | |
198 int len) { | |
199 scoped_refptr<IOBuffer> buf(new IOBuffer(len)); | |
200 ASSERT_EQ(len, sock_->Read(buf, len, NULL)); | |
201 ASSERT_EQ(std::string(data, len), std::string(buf->data(), len)); | |
202 ASSERT_TRUE(sock_->IsConnected()); | |
203 } | |
204 | |
205 void SpdyProxyClientSocketTest::AssertAsyncReadEquals(const char* data, | |
206 int len) { | |
207 // Issue the read, which will be completed asynchronously | |
208 scoped_refptr<IOBuffer> buf(new IOBuffer(len)); | |
209 ASSERT_EQ(ERR_IO_PENDING, sock_->Read(buf, len, &callback_)); | |
210 EXPECT_TRUE(sock_->IsConnected()); | |
211 | |
212 // Dummy write to un-block the read | |
213 AssertAsyncWriteSucceeds(kMsg2, kLen2); | |
214 EXPECT_TRUE(sock_->IsConnected()); | |
215 | |
216 // Now the read will return | |
217 EXPECT_EQ(len, callback_.WaitForResult()); | |
218 ASSERT_EQ(std::string(data, len), std::string(buf->data(), len)); | |
219 } | |
220 | |
221 void SpdyProxyClientSocketTest::AssertAsyncWriteSucceeds(const char* data, | |
222 int len) { | |
223 AssertAsyncWriteWithReadsSucceeds(data, len, 0); | |
224 } | |
225 | |
226 void SpdyProxyClientSocketTest::AssertAsyncWriteWithReadsSucceeds( | |
227 const char* data, int len, int num_reads) { | |
228 scoped_refptr<IOBufferWithSize> buf(CreateBuffer(data, len)); | |
229 | |
230 TestCompletionCallback callback; | |
231 EXPECT_EQ(ERR_IO_PENDING, sock_->Write(buf, buf->size(), &callback)); | |
232 | |
233 // Dummy reads to un-block the writes | |
234 for (int i = 0; i < num_reads; i++) { | |
235 AssertSyncReadEquals(kMsg2, kLen2); | |
236 } | |
237 | |
238 callback.WaitForResult(); | |
239 } | |
240 | |
241 // Constructs a standard SPDY SYN_STREAM frame for a CONNECT request. | |
242 spdy::SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectRequestFrame() { | |
243 const SpdyHeaderInfo kSynStartHeader = { | |
244 spdy::SYN_STREAM, | |
245 kStreamId, | |
246 0, | |
247 net::ConvertRequestPriorityToSpdyPriority(LOWEST), | |
248 spdy::CONTROL_FLAG_NONE, | |
249 false, | |
250 spdy::INVALID, | |
251 NULL, | |
252 0, | |
253 spdy::DATA_FLAG_NONE | |
254 }; | |
255 const char* const kConnectHeaders[] = { | |
256 "method", "CONNECT", | |
257 "url", kOriginHostPort, | |
258 "host", kOriginHost, | |
259 "user-agent", kUserAgent, | |
260 "version", "HTTP/1.1", | |
261 "proxy-connection", "keep-alive", | |
262 }; | |
263 return ConstructSpdyPacket( | |
264 kSynStartHeader, NULL, 0, kConnectHeaders, arraysize(kConnectHeaders)/2); | |
265 } | |
266 | |
267 // Constructs a SPDY SYN_STREAM frame for a CONNECT request which includes | |
268 // Proxy-Authorization headers. | |
269 spdy::SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectAuthRequestFrame() { | |
270 const SpdyHeaderInfo kSynStartHeader = { | |
271 spdy::SYN_STREAM, | |
272 kStreamId, | |
273 0, | |
274 net::ConvertRequestPriorityToSpdyPriority(LOWEST), | |
275 spdy::CONTROL_FLAG_NONE, | |
276 false, | |
277 spdy::INVALID, | |
278 NULL, | |
279 0, | |
280 spdy::DATA_FLAG_NONE | |
281 }; | |
282 const char* const kConnectHeaders[] = { | |
283 "method", "CONNECT", | |
284 "url", kOriginHostPort, | |
285 "host", kOriginHost, | |
286 "user-agent", kUserAgent, | |
287 "version", "HTTP/1.1", | |
288 "proxy-authorization", "Basic Zm9vOmJhcg==", | |
289 "proxy-connection", "keep-alive", | |
290 }; | |
291 return ConstructSpdyPacket( | |
292 kSynStartHeader, NULL, 0, kConnectHeaders, arraysize(kConnectHeaders)/2); | |
293 } | |
294 | |
295 // Constructs a standard SPDY SYN_REPLY frame to match the SPDY CONNECT. | |
296 spdy::SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectReplyFrame() { | |
297 const char* const kStandardReplyHeaders[] = { | |
298 "status", "200 Connection Established", | |
299 "version", "HTTP/1.1" | |
300 }; | |
301 return ConstructSpdyControlFrame(NULL, | |
302 0, | |
303 false, | |
304 kStreamId, | |
305 LOWEST, | |
306 spdy::SYN_REPLY, | |
307 spdy::CONTROL_FLAG_NONE, | |
308 kStandardReplyHeaders, | |
309 arraysize(kStandardReplyHeaders)); | |
310 } | |
311 | |
312 // Constructs a standard SPDY SYN_REPLY frame to match the SPDY CONNECT. | |
313 spdy::SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectAuthReplyFrame() { | |
314 const char* const kStandardReplyHeaders[] = { | |
315 "status", "407 Proxy Authentication Required", | |
316 "version", "HTTP/1.1", | |
317 "proxy-authenticate", "Basic realm=\"MyRealm1\"", | |
318 }; | |
319 | |
320 return ConstructSpdyControlFrame(NULL, | |
321 0, | |
322 false, | |
323 kStreamId, | |
324 LOWEST, | |
325 spdy::SYN_REPLY, | |
326 spdy::CONTROL_FLAG_NONE, | |
327 kStandardReplyHeaders, | |
328 arraysize(kStandardReplyHeaders)); | |
329 } | |
330 | |
331 // Constructs a SPDY SYN_REPLY frame with an HTTP 500 error. | |
332 spdy::SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectErrorReplyFrame() { | |
333 const char* const kStandardReplyHeaders[] = { | |
334 "status", "500 Internal Server Error", | |
335 "version", "HTTP/1.1", | |
336 }; | |
337 | |
338 return ConstructSpdyControlFrame(NULL, | |
339 0, | |
340 false, | |
341 kStreamId, | |
342 LOWEST, | |
343 spdy::SYN_REPLY, | |
344 spdy::CONTROL_FLAG_NONE, | |
345 kStandardReplyHeaders, | |
346 arraysize(kStandardReplyHeaders)); | |
347 } | |
348 | |
349 spdy::SpdyFrame* SpdyProxyClientSocketTest::ConstructBodyFrame(const char* data, | |
350 int length) { | |
351 return framer_.CreateDataFrame(kStreamId, data, length, spdy::DATA_FLAG_NONE); | |
352 } | |
353 | |
354 // ----------- Connect | |
355 | |
356 TEST_F(SpdyProxyClientSocketTest, ConnectSendsCorrectRequest) { | |
357 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
358 MockWrite writes[] = { | |
359 CreateMockWrite(*conn, 0), | |
360 }; | |
361 | |
362 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
363 MockRead reads[] = { | |
364 CreateMockRead(*resp, 1), | |
365 MockRead(true, 0, 0), // EOF | |
366 }; | |
367 | |
368 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
369 | |
370 ASSERT_FALSE(sock_->IsConnected()); | |
371 | |
372 AssertConnectSucceeds(); | |
373 | |
374 AssertConnectionEstablished(); | |
375 } | |
376 | |
377 TEST_F(SpdyProxyClientSocketTest, ConnectWithAuthRequested) { | |
378 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
379 MockWrite writes[] = { | |
380 CreateMockWrite(*conn, 0), | |
381 }; | |
382 | |
383 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectAuthReplyFrame()); | |
384 MockRead reads[] = { | |
385 CreateMockRead(*resp, 1), | |
386 MockRead(true, 0, 0), // EOF | |
387 }; | |
388 | |
389 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
390 | |
391 EXPECT_EQ(ERR_IO_PENDING, sock_->Connect(&callback_)); | |
392 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, callback_.WaitForResult()); | |
393 | |
394 const HttpResponseInfo* response = sock_->GetConnectResponseInfo(); | |
395 ASSERT_TRUE(response != NULL); | |
396 ASSERT_EQ(407, response->headers->response_code()); | |
397 ASSERT_EQ("Proxy Authentication Required", | |
398 response->headers->GetStatusText()); | |
399 } | |
400 | |
401 TEST_F(SpdyProxyClientSocketTest, ConnectWithAuthCredentials) { | |
402 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectAuthRequestFrame()); | |
403 MockWrite writes[] = { | |
404 CreateMockWrite(*conn, 0), | |
405 }; | |
406 | |
407 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
408 MockRead reads[] = { | |
409 CreateMockRead(*resp, 1), | |
410 MockRead(true, 0, 0), // EOF | |
411 }; | |
412 | |
413 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
414 AddAuthToCache(); | |
415 | |
416 EXPECT_EQ(ERR_IO_PENDING, sock_->Connect(&callback_)); | |
417 EXPECT_EQ(OK, callback_.WaitForResult()); | |
418 | |
419 AssertConnectionEstablished(); | |
420 } | |
421 | |
422 TEST_F(SpdyProxyClientSocketTest, ConnectFails) { | |
423 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
424 MockWrite writes[] = { | |
425 CreateMockWrite(*conn, 0), | |
426 }; | |
427 | |
428 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
429 MockRead reads[] = { | |
430 MockRead(true, 0, 0), // EOF | |
431 }; | |
432 | |
433 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
434 | |
435 ASSERT_FALSE(sock_->IsConnected()); | |
436 | |
437 ASSERT_EQ(ERR_IO_PENDING, sock_->Connect(&callback_)); | |
438 ASSERT_EQ(ERR_CONNECTION_CLOSED, callback_.WaitForResult()); | |
439 | |
440 ASSERT_FALSE(sock_->IsConnected()); | |
441 } | |
442 | |
443 // ----------- WasEverUsed | |
444 | |
445 TEST_F(SpdyProxyClientSocketTest, WasEverUsedReturnsCorrectValues) { | |
446 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
447 MockWrite writes[] = { | |
448 CreateMockWrite(*conn, 0), | |
449 }; | |
450 | |
451 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
452 MockRead reads[] = { | |
453 CreateMockRead(*resp, 1), | |
454 MockRead(true, 0, 0), // EOF | |
455 }; | |
456 | |
457 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
458 | |
459 EXPECT_FALSE(sock_->WasEverUsed()); | |
460 AssertConnectSucceeds(); | |
461 EXPECT_TRUE(sock_->WasEverUsed()); | |
462 sock_->Disconnect(); | |
463 EXPECT_TRUE(sock_->WasEverUsed()); | |
464 } | |
465 | |
466 // ----------- GetPeerAddress | |
467 | |
468 TEST_F(SpdyProxyClientSocketTest, GetPeerAddressReturnsCorrectValues) { | |
469 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
470 MockWrite writes[] = { | |
471 CreateMockWrite(*conn, 1), | |
472 MockWrite(true, 0, 3), // EOF | |
473 }; | |
474 | |
475 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
476 MockRead reads[] = { | |
477 CreateMockRead(*resp, 2), | |
478 MockRead(false, 0, 4), // EOF | |
479 }; | |
480 | |
481 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
482 | |
483 net::AddressList addr; | |
484 EXPECT_EQ(ERR_UNEXPECTED, sock_->GetPeerAddress(&addr)); | |
485 AssertConnectSucceeds(); | |
486 EXPECT_TRUE(sock_->IsConnected()); | |
487 EXPECT_EQ(OK, sock_->GetPeerAddress(&addr)); | |
488 sock_->Disconnect(); | |
489 EXPECT_EQ(ERR_UNEXPECTED, sock_->GetPeerAddress(&addr)); | |
490 } | |
491 | |
492 // ----------- Write | |
493 | |
494 TEST_F(SpdyProxyClientSocketTest, WriteSendsDataInDataFrame) { | |
495 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
496 scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); | |
497 scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); | |
498 MockWrite writes[] = { | |
499 CreateMockWrite(*conn, 0), | |
500 CreateMockWrite(*msg1, 3), | |
501 CreateMockWrite(*msg2, 4), | |
502 }; | |
503 | |
504 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
505 MockRead reads[] = { | |
506 CreateMockRead(*resp, 2), | |
507 MockRead(true, 0, 6), // EOF | |
508 }; | |
509 | |
510 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
511 | |
512 AssertConnectSucceeds(); | |
513 | |
514 AssertAsyncWriteSucceeds(kMsg1, kLen1); | |
515 AssertAsyncWriteSucceeds(kMsg2, kLen2); | |
516 } | |
517 | |
518 // ----------- Read | |
519 | |
520 TEST_F(SpdyProxyClientSocketTest, ReadReadsDataInDataFrame) { | |
521 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
522 MockWrite writes[] = { | |
523 CreateMockWrite(*conn, 1), | |
524 }; | |
525 | |
526 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
527 scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); | |
528 scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); | |
529 MockRead reads[] = { | |
530 CreateMockRead(*resp, 2), | |
531 CreateMockRead(*msg1, 3), | |
532 CreateMockRead(*msg2, 4), | |
533 MockRead(true, 0, 6), // EOF | |
534 }; | |
535 | |
536 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
537 | |
538 AssertConnectSucceeds(); | |
539 | |
540 AssertSyncReadEquals(kMsg1, kLen1); | |
541 AssertSyncReadEquals(kMsg2, kLen2); | |
542 } | |
543 | |
544 TEST_F(SpdyProxyClientSocketTest, ReadAuthResponseBody) { | |
545 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
546 MockWrite writes[] = { | |
547 CreateMockWrite(*conn, 1), | |
548 }; | |
549 | |
550 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectAuthReplyFrame()); | |
551 scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); | |
552 scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); | |
553 MockRead reads[] = { | |
554 CreateMockRead(*resp, 2), | |
555 CreateMockRead(*msg1, 3), | |
556 CreateMockRead(*msg2, 4), | |
557 MockRead(true, 0, 6), // EOF | |
558 }; | |
559 | |
560 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
561 | |
562 EXPECT_EQ(ERR_IO_PENDING, sock_->Connect(&callback_)); | |
563 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, callback_.WaitForResult()); | |
564 // EXPECT_EQ(ERR_PROXY_AUTH_REQUESTED, callback_.WaitForResult()); | |
565 | |
566 AssertSyncReadEquals(kMsg1, kLen1); | |
567 AssertSyncReadEquals(kMsg2, kLen2); | |
568 } | |
569 | |
570 TEST_F(SpdyProxyClientSocketTest, ReadErrorResponseBody) { | |
571 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
572 MockWrite writes[] = { | |
573 CreateMockWrite(*conn, 1), | |
574 }; | |
575 | |
576 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectErrorReplyFrame()); | |
577 scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); | |
578 scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); | |
579 MockRead reads[] = { | |
580 CreateMockRead(*resp, 2), | |
581 CreateMockRead(*msg1, 3), | |
582 CreateMockRead(*msg2, 4), | |
583 MockRead(true, 0, 6), // EOF | |
584 }; | |
585 | |
586 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
587 | |
588 EXPECT_EQ(ERR_IO_PENDING, sock_->Connect(&callback_)); | |
589 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, callback_.WaitForResult()); | |
590 | |
591 AssertSyncReadEquals(kMsg1, kLen1); | |
592 AssertSyncReadEquals(kMsg2, kLen2); | |
593 } | |
594 | |
595 // ----------- Reads and Writes | |
596 | |
597 TEST_F(SpdyProxyClientSocketTest, AsyncReadAroundWrite) { | |
598 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
599 scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); | |
600 MockWrite writes[] = { | |
601 CreateMockWrite(*conn, 1), | |
602 CreateMockWrite(*msg2, 4), // write to un-cork the read | |
603 }; | |
604 | |
605 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
606 scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); | |
607 scoped_ptr<spdy::SpdyFrame> msg3(ConstructBodyFrame(kMsg3, kLen3)); | |
608 MockRead reads[] = { | |
609 CreateMockRead(*resp, 2), | |
610 CreateMockRead(*msg1, 3), // sync read | |
611 CreateMockRead(*msg3, 5, true), // async read | |
612 MockRead(true, 0, 9), // EOF | |
613 }; | |
614 | |
615 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
616 | |
617 AssertConnectSucceeds(); | |
618 | |
619 AssertSyncReadEquals(kMsg1, kLen1); | |
620 | |
621 AssertAsyncReadEquals(kMsg3, kLen3); | |
622 } | |
623 | |
624 TEST_F(SpdyProxyClientSocketTest, AsyncWriteAroundRead) { | |
625 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
626 scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); | |
627 MockWrite writes[] = { | |
628 CreateMockWrite(*conn, 1), | |
629 CreateMockWrite(*msg1, 4), | |
630 }; | |
631 | |
632 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
633 scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); | |
634 MockRead reads[] = { | |
635 CreateMockRead(*resp, 2), | |
636 CreateMockRead(*msg2, 3), // sync read (which will un-cork the write) | |
637 MockRead(true, 0, 5), // EOF | |
638 }; | |
639 | |
640 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
641 | |
642 AssertConnectSucceeds(); | |
643 | |
644 AssertAsyncWriteWithReadsSucceeds(kMsg1, kLen1, 1); | |
645 } | |
646 | |
647 TEST_F(SpdyProxyClientSocketTest, Mixed) { | |
648 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
649 scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); | |
650 MockWrite writes[] = { | |
651 CreateMockWrite(*conn, 1), | |
652 CreateMockWrite(*msg2, 4), // write to un-cork the read | |
653 }; | |
654 | |
655 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
656 scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); | |
657 scoped_ptr<spdy::SpdyFrame> msg3(ConstructBodyFrame(kMsg3, kLen3)); | |
658 MockRead reads[] = { | |
659 CreateMockRead(*resp, 2), | |
660 CreateMockRead(*msg1, 3), // sync read | |
661 CreateMockRead(*msg3, 5, true), // async read | |
662 MockRead(true, 0, 9), // EOF | |
663 }; | |
664 | |
665 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
666 | |
667 AssertConnectSucceeds(); | |
668 | |
669 AssertSyncReadEquals(kMsg1, kLen1); | |
670 AssertAsyncReadEquals(kMsg3, kLen3); | |
671 } | |
672 | |
673 TEST_F(SpdyProxyClientSocketTest, MultipleShortReads) { | |
674 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
675 MockWrite writes[] = { | |
676 CreateMockWrite(*conn, 1), | |
677 }; | |
678 | |
679 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
680 scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); | |
681 scoped_ptr<spdy::SpdyFrame> msg3(ConstructBodyFrame(kMsg3, kLen3)); | |
682 MockRead reads[] = { | |
683 CreateMockRead(*resp, 2), | |
684 CreateMockRead(*msg1, 3), // sync read | |
685 CreateMockRead(*msg3, 4), // sync read | |
686 CreateMockRead(*msg3, 5), // sync read | |
687 MockRead(true, 0, 8), // EOF | |
688 }; | |
689 | |
690 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
691 | |
692 AssertConnectSucceeds(); | |
693 | |
694 AssertSyncReadEquals(kMsg1, kLen1); | |
695 // The payload from two data frames, each with kMsg3 will be combined | |
696 // together into a single read(). | |
697 AssertSyncReadEquals(kMsg33, kLen33); | |
698 } | |
699 | |
700 TEST_F(SpdyProxyClientSocketTest, MultipleShortReadsThenMoreRead) { | |
701 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
702 MockWrite writes[] = { | |
703 CreateMockWrite(*conn, 1), | |
704 }; | |
705 | |
706 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
707 scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); | |
708 scoped_ptr<spdy::SpdyFrame> msg3(ConstructBodyFrame(kMsg3, kLen3)); | |
709 scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); | |
710 MockRead reads[] = { | |
711 CreateMockRead(*resp, 2), | |
712 CreateMockRead(*msg1, 3), // sync read | |
713 CreateMockRead(*msg3, 4), // sync read | |
714 CreateMockRead(*msg3, 5), // sync read | |
715 CreateMockRead(*msg2, 5), // sync read | |
716 MockRead(true, 0, 8), // EOF | |
717 }; | |
718 | |
719 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
720 | |
721 AssertConnectSucceeds(); | |
722 | |
723 AssertSyncReadEquals(kMsg1, kLen1); | |
724 // The payload from two data frames, each with kMsg3 will be combined | |
725 // together into a single read(). | |
726 AssertSyncReadEquals(kMsg33, kLen33); | |
727 AssertSyncReadEquals(kMsg2, kLen2); | |
728 } | |
729 | |
730 | |
731 TEST_F(SpdyProxyClientSocketTest, LargeSplitRead) { | |
732 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
733 MockWrite writes[] = { | |
734 CreateMockWrite(*conn, 1), | |
735 }; | |
736 | |
737 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
738 scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); | |
739 scoped_ptr<spdy::SpdyFrame> msg33(ConstructBodyFrame(kMsg33, kLen33)); | |
740 scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); | |
741 MockRead reads[] = { | |
742 CreateMockRead(*resp, 2), | |
743 CreateMockRead(*msg1, 3), | |
744 CreateMockRead(*msg33, 4), | |
745 MockRead(true, 0, 8), // EOF | |
746 }; | |
747 | |
748 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
749 | |
750 AssertConnectSucceeds(); | |
751 | |
752 AssertSyncReadEquals(kMsg1, kLen1); | |
753 // The payload from the single large data frame will be read across | |
754 // two different reads. | |
755 AssertSyncReadEquals(kMsg3, kLen3); | |
756 AssertSyncReadEquals(kMsg3, kLen3); | |
757 } | |
758 | |
759 TEST_F(SpdyProxyClientSocketTest, WriteLargeDataSplits) { | |
760 std::string chunk_data(kMaxSpdyFrameChunkSize, 'x'); | |
761 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
762 scoped_ptr<spdy::SpdyFrame> chunk(ConstructBodyFrame(chunk_data.data(), | |
763 chunk_data.length())); | |
764 MockWrite writes[] = { | |
765 CreateMockWrite(*conn, 1), | |
766 CreateMockWrite(*chunk, 3, false), | |
767 CreateMockWrite(*chunk, 4, false), | |
768 CreateMockWrite(*chunk, 5, false) | |
769 }; | |
770 | |
771 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
772 MockRead reads[] = { | |
773 CreateMockRead(*resp, 2), | |
774 MockRead(true, 0, 7), // EOF | |
775 }; | |
776 | |
777 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
778 | |
779 AssertConnectSucceeds(); | |
780 | |
781 std::string big_data(kMaxSpdyFrameChunkSize * 3, 'x'); | |
782 AssertAsyncWriteSucceeds(big_data.data(), big_data.length()); | |
783 } | |
784 | |
785 // ----------- Reading/Writing on Closed socket | |
786 | |
787 // Reading from an already closed socket should return 0 | |
788 TEST_F(SpdyProxyClientSocketTest, ReadOnClosedSocketReturnsZero) { | |
789 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
790 MockWrite writes[] = { | |
791 CreateMockWrite(*conn, 1), | |
792 }; | |
793 | |
794 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
795 MockRead reads[] = { | |
796 CreateMockRead(*resp, 2), | |
797 MockRead(true, 0, 4), // EOF | |
798 }; | |
799 | |
800 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
801 | |
802 AssertConnectSucceeds(); | |
803 | |
804 sock_->Disconnect(); | |
805 | |
806 ASSERT_EQ(0, sock_->Read(NULL, 1, NULL)); | |
807 ASSERT_EQ(ERR_CONNECTION_CLOSED, sock_->Read(NULL, 1, NULL)); | |
808 ASSERT_EQ(ERR_CONNECTION_CLOSED, sock_->Read(NULL, 1, NULL)); | |
809 } | |
810 | |
811 // Calling Write() on a closed socket is an error | |
812 TEST_F(SpdyProxyClientSocketTest, WriteOnClosedStream) { | |
813 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
814 MockWrite writes[] = { | |
815 CreateMockWrite(*conn, 1), | |
816 }; | |
817 | |
818 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
819 scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); | |
820 MockRead reads[] = { | |
821 CreateMockRead(*resp, 2), | |
822 MockRead(false, 0, 3), // EOF | |
823 }; | |
824 | |
825 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
826 | |
827 AssertConnectSucceeds(); | |
828 | |
829 scoped_refptr<IOBufferWithSize> buf(CreateBuffer(kMsg1, kLen1)); | |
830 EXPECT_EQ(ERR_CONNECTION_CLOSED, sock_->Write(buf, buf->size(), NULL)); | |
831 } | |
832 | |
833 // ----------- Pending read/write when closed | |
834 | |
835 // If the socket is closed with a pending Write(), the callback | |
836 // should not be called. | |
837 TEST_F(SpdyProxyClientSocketTest, DisconnectWithWritePending) { | |
838 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
839 MockWrite writes[] = { | |
840 CreateMockWrite(*conn, 1), | |
841 MockWrite(true, 0, 3), // EOF | |
842 }; | |
843 | |
844 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
845 MockRead reads[] = { | |
846 CreateMockRead(*resp, 2), | |
847 MockRead(false, 0, 4), // EOF | |
848 }; | |
849 | |
850 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
851 | |
852 AssertConnectSucceeds(); | |
853 | |
854 EXPECT_TRUE(sock_->IsConnected()); | |
855 | |
856 scoped_refptr<IOBufferWithSize> buf(CreateBuffer(kMsg1, kLen1)); | |
857 EXPECT_EQ(ERR_IO_PENDING, sock_->Write(buf, buf->size(), &callback_)); | |
858 | |
859 sock_->Disconnect(); | |
860 | |
861 EXPECT_FALSE(sock_->IsConnected()); | |
862 EXPECT_FALSE(callback_.have_result()); | |
863 } | |
864 | |
865 // If the socket is closed with a pending Read(), the callback | |
866 // should not be called. | |
867 TEST_F(SpdyProxyClientSocketTest, DisconnectWithReadPending) { | |
868 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
869 MockWrite writes[] = { | |
870 CreateMockWrite(*conn, 1), | |
871 }; | |
872 | |
873 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
874 MockRead reads[] = { | |
875 CreateMockRead(*resp, 2), | |
876 MockRead(true, 0, 4), // EOF | |
877 }; | |
878 | |
879 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
880 | |
881 AssertConnectSucceeds(); | |
882 | |
883 EXPECT_TRUE(sock_->IsConnected()); | |
884 | |
885 scoped_refptr<IOBuffer> buf(new IOBuffer(kLen1)); | |
886 ASSERT_EQ(ERR_IO_PENDING, sock_->Read(buf, kLen1, &callback_)); | |
887 | |
888 sock_->Disconnect(); | |
889 | |
890 EXPECT_FALSE(sock_->IsConnected()); | |
891 EXPECT_FALSE(callback_.have_result()); | |
892 } | |
893 | |
894 } // namespace net | |
OLD | NEW |