OLD | NEW |
| (Empty) |
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 "net/spdy/spdy_proxy_client_socket.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/bind_helpers.h" | |
9 #include "base/utf_string_conversions.h" | |
10 #include "net/base/address_list.h" | |
11 #include "net/base/net_log.h" | |
12 #include "net/base/net_log_unittest.h" | |
13 #include "net/base/mock_host_resolver.h" | |
14 #include "net/base/test_completion_callback.h" | |
15 #include "net/base/winsock_init.h" | |
16 #include "net/http/http_response_info.h" | |
17 #include "net/http/http_response_headers.h" | |
18 #include "net/socket/client_socket_factory.h" | |
19 #include "net/socket/tcp_client_socket.h" | |
20 #include "net/socket/socket_test_util.h" | |
21 #include "net/spdy/spdy_http_utils.h" | |
22 #include "net/spdy/spdy_protocol.h" | |
23 #include "net/spdy/spdy_session_pool.h" | |
24 #include "net/spdy/spdy_test_util.h" | |
25 #include "testing/platform_test.h" | |
26 #include "testing/gtest/include/gtest/gtest.h" | |
27 | |
28 //----------------------------------------------------------------------------- | |
29 | |
30 namespace { | |
31 | |
32 static const char kUrl[] = "https://www.google.com/"; | |
33 static const char kOriginHost[] = "www.google.com"; | |
34 static const int kOriginPort = 443; | |
35 static const char kOriginHostPort[] = "www.google.com:443"; | |
36 static const char kProxyUrl[] = "https://myproxy:6121/"; | |
37 static const char kProxyHost[] = "myproxy"; | |
38 static const int kProxyPort = 6121; | |
39 static const char kUserAgent[] = "Mozilla/1.0"; | |
40 | |
41 static const int kStreamId = 1; | |
42 | |
43 static const char kMsg1[] = "\0hello!\xff"; | |
44 static const int kLen1 = 8; | |
45 static const char kMsg2[] = "\00012345678\0"; | |
46 static const int kLen2 = 10; | |
47 static const char kMsg3[] = "bye!"; | |
48 static const int kLen3 = 4; | |
49 static const char kMsg33[] = "bye!bye!"; | |
50 static const int kLen33 = kLen3 + kLen3; | |
51 static const char kMsg333[] = "bye!bye!bye!"; | |
52 static const int kLen333 = kLen3 + kLen3 + kLen3; | |
53 | |
54 } // anonymous namespace | |
55 | |
56 namespace net { | |
57 | |
58 class SpdyProxyClientSocketTest : public PlatformTest { | |
59 public: | |
60 SpdyProxyClientSocketTest(); | |
61 | |
62 virtual void TearDown(); | |
63 | |
64 protected: | |
65 void Initialize(MockRead* reads, size_t reads_count, MockWrite* writes, | |
66 size_t writes_count); | |
67 spdy::SpdyFrame* ConstructConnectRequestFrame(); | |
68 spdy::SpdyFrame* ConstructConnectAuthRequestFrame(); | |
69 spdy::SpdyFrame* ConstructConnectReplyFrame(); | |
70 spdy::SpdyFrame* ConstructConnectAuthReplyFrame(); | |
71 spdy::SpdyFrame* ConstructConnectErrorReplyFrame(); | |
72 spdy::SpdyFrame* ConstructBodyFrame(const char* data, int length); | |
73 scoped_refptr<IOBufferWithSize> CreateBuffer(const char* data, int size); | |
74 void AssertConnectSucceeds(); | |
75 void AssertConnectFails(int result); | |
76 void AssertConnectionEstablished(); | |
77 void AssertSyncReadEquals(const char* data, int len); | |
78 void AssertAsyncReadEquals(const char* data, int len); | |
79 void AssertReadStarts(const char* data, int len); | |
80 void AssertReadReturns(const char* data, int len); | |
81 void AssertAsyncWriteSucceeds(const char* data, int len); | |
82 void AssertWriteReturns(const char* data, int len, int rv); | |
83 void AssertWriteLength(int len); | |
84 void AssertAsyncWriteWithReadsSucceeds(const char* data, int len, | |
85 int num_reads); | |
86 | |
87 void AddAuthToCache() { | |
88 const string16 kFoo(ASCIIToUTF16("foo")); | |
89 const string16 kBar(ASCIIToUTF16("bar")); | |
90 session_->http_auth_cache()->Add(GURL(kProxyUrl), | |
91 "MyRealm1", | |
92 HttpAuth::AUTH_SCHEME_BASIC, | |
93 "Basic realm=MyRealm1", | |
94 AuthCredentials(kFoo, kBar), | |
95 "/"); | |
96 } | |
97 | |
98 void Run(int steps) { | |
99 data_->StopAfter(steps); | |
100 data_->Run(); | |
101 } | |
102 | |
103 scoped_ptr<SpdyProxyClientSocket> sock_; | |
104 TestCompletionCallback read_callback_; | |
105 TestCompletionCallback write_callback_; | |
106 scoped_refptr<DeterministicSocketData> data_; | |
107 | |
108 private: | |
109 scoped_refptr<HttpNetworkSession> session_; | |
110 scoped_refptr<IOBuffer> read_buf_; | |
111 SpdySessionDependencies session_deps_; | |
112 MockConnect connect_data_; | |
113 scoped_refptr<SpdySession> spdy_session_; | |
114 scoped_refptr<SpdyStream> spdy_stream_; | |
115 spdy::SpdyFramer framer_; | |
116 | |
117 std::string user_agent_; | |
118 GURL url_; | |
119 HostPortPair proxy_host_port_; | |
120 HostPortPair endpoint_host_port_pair_; | |
121 ProxyServer proxy_; | |
122 HostPortProxyPair endpoint_host_port_proxy_pair_; | |
123 scoped_refptr<TransportSocketParams> transport_params_; | |
124 | |
125 DISALLOW_COPY_AND_ASSIGN(SpdyProxyClientSocketTest); | |
126 }; | |
127 | |
128 SpdyProxyClientSocketTest::SpdyProxyClientSocketTest() | |
129 : sock_(NULL), | |
130 data_(NULL), | |
131 session_(NULL), | |
132 read_buf_(NULL), | |
133 session_deps_(), | |
134 connect_data_(SYNCHRONOUS, OK), | |
135 spdy_session_(NULL), | |
136 spdy_stream_(NULL), | |
137 framer_(), | |
138 user_agent_(kUserAgent), | |
139 url_(kUrl), | |
140 proxy_host_port_(kProxyHost, kProxyPort), | |
141 endpoint_host_port_pair_(kOriginHost, kOriginPort), | |
142 proxy_(ProxyServer::SCHEME_HTTPS, proxy_host_port_), | |
143 endpoint_host_port_proxy_pair_(endpoint_host_port_pair_, proxy_), | |
144 transport_params_(new TransportSocketParams(proxy_host_port_, | |
145 LOWEST, | |
146 false, | |
147 false)) { | |
148 } | |
149 | |
150 void SpdyProxyClientSocketTest::TearDown() { | |
151 sock_.reset(NULL); | |
152 if (session_ != NULL) | |
153 session_->spdy_session_pool()->CloseAllSessions(); | |
154 | |
155 spdy::SpdyFramer::set_enable_compression_default(true); | |
156 // Empty the current queue. | |
157 MessageLoop::current()->RunAllPending(); | |
158 PlatformTest::TearDown(); | |
159 } | |
160 | |
161 void SpdyProxyClientSocketTest::Initialize(MockRead* reads, | |
162 size_t reads_count, | |
163 MockWrite* writes, | |
164 size_t writes_count) { | |
165 data_ = new DeterministicSocketData(reads, reads_count, writes, writes_count); | |
166 data_->set_connect_data(connect_data_); | |
167 data_->SetStop(2); | |
168 | |
169 session_deps_.deterministic_socket_factory->AddSocketDataProvider( | |
170 data_.get()); | |
171 session_deps_.host_resolver->set_synchronous_mode(true); | |
172 | |
173 session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic( | |
174 &session_deps_); | |
175 SpdySession::SetSSLMode(false); | |
176 spdy::SpdyFramer::set_enable_compression_default(false); | |
177 | |
178 // Creates a new spdy session | |
179 spdy_session_ = | |
180 session_->spdy_session_pool()->Get(endpoint_host_port_proxy_pair_, | |
181 BoundNetLog()); | |
182 | |
183 // Perform the TCP connect | |
184 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); | |
185 EXPECT_EQ(OK, | |
186 connection->Init(endpoint_host_port_pair_.ToString(), | |
187 transport_params_, LOWEST, CompletionCallback(), | |
188 session_->GetTransportSocketPool(), | |
189 BoundNetLog())); | |
190 spdy_session_->InitializeWithSocket(connection.release(), false, OK); | |
191 | |
192 // Create the SPDY Stream | |
193 ASSERT_EQ( | |
194 OK, | |
195 spdy_session_->CreateStream(url_, LOWEST, &spdy_stream_, BoundNetLog(), | |
196 CompletionCallback())); | |
197 | |
198 // Create the SpdyProxyClientSocket | |
199 sock_.reset( | |
200 new SpdyProxyClientSocket(spdy_stream_, user_agent_, | |
201 endpoint_host_port_pair_, url_, | |
202 proxy_host_port_, session_->http_auth_cache(), | |
203 session_->http_auth_handler_factory())); | |
204 } | |
205 | |
206 scoped_refptr<IOBufferWithSize> SpdyProxyClientSocketTest::CreateBuffer( | |
207 const char* data, int size) { | |
208 scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(size)); | |
209 memcpy(buf->data(), data, size); | |
210 return buf; | |
211 } | |
212 | |
213 void SpdyProxyClientSocketTest::AssertConnectSucceeds() { | |
214 ASSERT_EQ(ERR_IO_PENDING, sock_->Connect(read_callback_.callback())); | |
215 data_->Run(); | |
216 ASSERT_EQ(OK, read_callback_.WaitForResult()); | |
217 } | |
218 | |
219 void SpdyProxyClientSocketTest::AssertConnectFails(int result) { | |
220 ASSERT_EQ(ERR_IO_PENDING, sock_->Connect(read_callback_.callback())); | |
221 data_->Run(); | |
222 ASSERT_EQ(result, read_callback_.WaitForResult()); | |
223 } | |
224 | |
225 void SpdyProxyClientSocketTest::AssertConnectionEstablished() { | |
226 const HttpResponseInfo* response = sock_->GetConnectResponseInfo(); | |
227 ASSERT_TRUE(response != NULL); | |
228 ASSERT_EQ(200, response->headers->response_code()); | |
229 ASSERT_EQ("Connection Established", response->headers->GetStatusText()); | |
230 } | |
231 | |
232 void SpdyProxyClientSocketTest::AssertSyncReadEquals(const char* data, | |
233 int len) { | |
234 scoped_refptr<IOBuffer> buf(new IOBuffer(len)); | |
235 ASSERT_EQ(len, sock_->Read(buf, len, CompletionCallback())); | |
236 ASSERT_EQ(std::string(data, len), std::string(buf->data(), len)); | |
237 ASSERT_TRUE(sock_->IsConnected()); | |
238 } | |
239 | |
240 void SpdyProxyClientSocketTest::AssertAsyncReadEquals(const char* data, | |
241 int len) { | |
242 data_->StopAfter(1); | |
243 // Issue the read, which will be completed asynchronously | |
244 scoped_refptr<IOBuffer> buf(new IOBuffer(len)); | |
245 ASSERT_EQ(ERR_IO_PENDING, sock_->Read(buf, len, read_callback_.callback())); | |
246 EXPECT_TRUE(sock_->IsConnected()); | |
247 data_->Run(); | |
248 | |
249 EXPECT_TRUE(sock_->IsConnected()); | |
250 | |
251 // Now the read will return | |
252 EXPECT_EQ(len, read_callback_.WaitForResult()); | |
253 ASSERT_EQ(std::string(data, len), std::string(buf->data(), len)); | |
254 } | |
255 | |
256 void SpdyProxyClientSocketTest::AssertReadStarts(const char* data, int len) { | |
257 data_->StopAfter(1); | |
258 // Issue the read, which will be completed asynchronously | |
259 read_buf_ = new IOBuffer(len); | |
260 ASSERT_EQ(ERR_IO_PENDING, | |
261 sock_->Read(read_buf_, len, read_callback_.callback())); | |
262 EXPECT_TRUE(sock_->IsConnected()); | |
263 } | |
264 | |
265 void SpdyProxyClientSocketTest::AssertReadReturns(const char* data, int len) { | |
266 EXPECT_TRUE(sock_->IsConnected()); | |
267 | |
268 // Now the read will return | |
269 EXPECT_EQ(len, read_callback_.WaitForResult()); | |
270 ASSERT_EQ(std::string(data, len), std::string(read_buf_->data(), len)); | |
271 } | |
272 | |
273 void SpdyProxyClientSocketTest::AssertAsyncWriteSucceeds(const char* data, | |
274 int len) { | |
275 AssertWriteReturns(data, len, ERR_IO_PENDING); | |
276 data_->RunFor(1); | |
277 AssertWriteLength(len); | |
278 } | |
279 | |
280 void SpdyProxyClientSocketTest::AssertWriteReturns(const char* data, int len, | |
281 int rv) { | |
282 scoped_refptr<IOBufferWithSize> buf(CreateBuffer(data, len)); | |
283 EXPECT_EQ(rv, sock_->Write(buf, buf->size(), write_callback_.callback())); | |
284 } | |
285 | |
286 void SpdyProxyClientSocketTest::AssertWriteLength(int len) { | |
287 EXPECT_EQ(len, write_callback_.WaitForResult()); | |
288 } | |
289 | |
290 void SpdyProxyClientSocketTest::AssertAsyncWriteWithReadsSucceeds( | |
291 const char* data, int len, int num_reads) { | |
292 scoped_refptr<IOBufferWithSize> buf(CreateBuffer(data, len)); | |
293 | |
294 EXPECT_EQ(ERR_IO_PENDING, sock_->Write(buf, buf->size(), | |
295 write_callback_.callback())); | |
296 | |
297 for (int i = 0; i < num_reads; i++) { | |
298 Run(1); | |
299 AssertSyncReadEquals(kMsg2, kLen2); | |
300 } | |
301 | |
302 write_callback_.WaitForResult(); | |
303 } | |
304 | |
305 // Constructs a standard SPDY SYN_STREAM frame for a CONNECT request. | |
306 spdy::SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectRequestFrame() { | |
307 const SpdyHeaderInfo kSynStartHeader = { | |
308 spdy::SYN_STREAM, | |
309 kStreamId, | |
310 0, | |
311 net::ConvertRequestPriorityToSpdyPriority(LOWEST), | |
312 spdy::CONTROL_FLAG_NONE, | |
313 false, | |
314 spdy::INVALID, | |
315 NULL, | |
316 0, | |
317 spdy::DATA_FLAG_NONE | |
318 }; | |
319 const char* const kConnectHeaders[] = { | |
320 "method", "CONNECT", | |
321 "url", kOriginHostPort, | |
322 "host", kOriginHost, | |
323 "user-agent", kUserAgent, | |
324 "version", "HTTP/1.1", | |
325 }; | |
326 return ConstructSpdyPacket( | |
327 kSynStartHeader, NULL, 0, kConnectHeaders, arraysize(kConnectHeaders)/2); | |
328 } | |
329 | |
330 // Constructs a SPDY SYN_STREAM frame for a CONNECT request which includes | |
331 // Proxy-Authorization headers. | |
332 spdy::SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectAuthRequestFrame() { | |
333 const SpdyHeaderInfo kSynStartHeader = { | |
334 spdy::SYN_STREAM, | |
335 kStreamId, | |
336 0, | |
337 net::ConvertRequestPriorityToSpdyPriority(LOWEST), | |
338 spdy::CONTROL_FLAG_NONE, | |
339 false, | |
340 spdy::INVALID, | |
341 NULL, | |
342 0, | |
343 spdy::DATA_FLAG_NONE | |
344 }; | |
345 const char* const kConnectHeaders[] = { | |
346 "method", "CONNECT", | |
347 "url", kOriginHostPort, | |
348 "host", kOriginHost, | |
349 "user-agent", kUserAgent, | |
350 "version", "HTTP/1.1", | |
351 "proxy-authorization", "Basic Zm9vOmJhcg==", | |
352 }; | |
353 return ConstructSpdyPacket( | |
354 kSynStartHeader, NULL, 0, kConnectHeaders, arraysize(kConnectHeaders)/2); | |
355 } | |
356 | |
357 // Constructs a standard SPDY SYN_REPLY frame to match the SPDY CONNECT. | |
358 spdy::SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectReplyFrame() { | |
359 const char* const kStandardReplyHeaders[] = { | |
360 "status", "200 Connection Established", | |
361 "version", "HTTP/1.1" | |
362 }; | |
363 return ConstructSpdyControlFrame(NULL, | |
364 0, | |
365 false, | |
366 kStreamId, | |
367 LOWEST, | |
368 spdy::SYN_REPLY, | |
369 spdy::CONTROL_FLAG_NONE, | |
370 kStandardReplyHeaders, | |
371 arraysize(kStandardReplyHeaders)); | |
372 } | |
373 | |
374 // Constructs a standard SPDY SYN_REPLY frame to match the SPDY CONNECT. | |
375 spdy::SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectAuthReplyFrame() { | |
376 const char* const kStandardReplyHeaders[] = { | |
377 "status", "407 Proxy Authentication Required", | |
378 "version", "HTTP/1.1", | |
379 "proxy-authenticate", "Basic realm=\"MyRealm1\"", | |
380 }; | |
381 | |
382 return ConstructSpdyControlFrame(NULL, | |
383 0, | |
384 false, | |
385 kStreamId, | |
386 LOWEST, | |
387 spdy::SYN_REPLY, | |
388 spdy::CONTROL_FLAG_NONE, | |
389 kStandardReplyHeaders, | |
390 arraysize(kStandardReplyHeaders)); | |
391 } | |
392 | |
393 // Constructs a SPDY SYN_REPLY frame with an HTTP 500 error. | |
394 spdy::SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectErrorReplyFrame() { | |
395 const char* const kStandardReplyHeaders[] = { | |
396 "status", "500 Internal Server Error", | |
397 "version", "HTTP/1.1", | |
398 }; | |
399 | |
400 return ConstructSpdyControlFrame(NULL, | |
401 0, | |
402 false, | |
403 kStreamId, | |
404 LOWEST, | |
405 spdy::SYN_REPLY, | |
406 spdy::CONTROL_FLAG_NONE, | |
407 kStandardReplyHeaders, | |
408 arraysize(kStandardReplyHeaders)); | |
409 } | |
410 | |
411 spdy::SpdyFrame* SpdyProxyClientSocketTest::ConstructBodyFrame(const char* data, | |
412 int length) { | |
413 return framer_.CreateDataFrame(kStreamId, data, length, spdy::DATA_FLAG_NONE); | |
414 } | |
415 | |
416 // ----------- Connect | |
417 | |
418 TEST_F(SpdyProxyClientSocketTest, ConnectSendsCorrectRequest) { | |
419 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
420 MockWrite writes[] = { | |
421 CreateMockWrite(*conn, 0, SYNCHRONOUS), | |
422 }; | |
423 | |
424 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
425 MockRead reads[] = { | |
426 CreateMockRead(*resp, 1, ASYNC), | |
427 MockRead(ASYNC, 0, 3), // EOF | |
428 }; | |
429 | |
430 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
431 | |
432 ASSERT_FALSE(sock_->IsConnected()); | |
433 | |
434 AssertConnectSucceeds(); | |
435 | |
436 AssertConnectionEstablished(); | |
437 } | |
438 | |
439 TEST_F(SpdyProxyClientSocketTest, ConnectWithAuthRequested) { | |
440 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
441 MockWrite writes[] = { | |
442 CreateMockWrite(*conn, 0, SYNCHRONOUS), | |
443 }; | |
444 | |
445 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectAuthReplyFrame()); | |
446 MockRead reads[] = { | |
447 CreateMockRead(*resp, 1, ASYNC), | |
448 MockRead(ASYNC, 0, 3), // EOF | |
449 }; | |
450 | |
451 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
452 | |
453 AssertConnectFails(ERR_PROXY_AUTH_REQUESTED); | |
454 | |
455 const HttpResponseInfo* response = sock_->GetConnectResponseInfo(); | |
456 ASSERT_TRUE(response != NULL); | |
457 ASSERT_EQ(407, response->headers->response_code()); | |
458 ASSERT_EQ("Proxy Authentication Required", | |
459 response->headers->GetStatusText()); | |
460 } | |
461 | |
462 TEST_F(SpdyProxyClientSocketTest, ConnectWithAuthCredentials) { | |
463 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectAuthRequestFrame()); | |
464 MockWrite writes[] = { | |
465 CreateMockWrite(*conn, 0, SYNCHRONOUS), | |
466 }; | |
467 | |
468 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
469 MockRead reads[] = { | |
470 CreateMockRead(*resp, 1, ASYNC), | |
471 MockRead(ASYNC, 0, 3), // EOF | |
472 }; | |
473 | |
474 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
475 AddAuthToCache(); | |
476 | |
477 AssertConnectSucceeds(); | |
478 | |
479 AssertConnectionEstablished(); | |
480 } | |
481 | |
482 TEST_F(SpdyProxyClientSocketTest, ConnectFails) { | |
483 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
484 MockWrite writes[] = { | |
485 CreateMockWrite(*conn, 0, SYNCHRONOUS), | |
486 }; | |
487 | |
488 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
489 MockRead reads[] = { | |
490 MockRead(ASYNC, 0, 1), // EOF | |
491 }; | |
492 | |
493 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
494 | |
495 ASSERT_FALSE(sock_->IsConnected()); | |
496 | |
497 AssertConnectFails(ERR_CONNECTION_CLOSED); | |
498 | |
499 ASSERT_FALSE(sock_->IsConnected()); | |
500 } | |
501 | |
502 // ----------- WasEverUsed | |
503 | |
504 TEST_F(SpdyProxyClientSocketTest, WasEverUsedReturnsCorrectValues) { | |
505 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
506 MockWrite writes[] = { | |
507 CreateMockWrite(*conn, 0, SYNCHRONOUS), | |
508 }; | |
509 | |
510 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
511 MockRead reads[] = { | |
512 CreateMockRead(*resp, 1, ASYNC), | |
513 MockRead(ASYNC, 0, 2), // EOF | |
514 }; | |
515 | |
516 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
517 | |
518 EXPECT_FALSE(sock_->WasEverUsed()); | |
519 AssertConnectSucceeds(); | |
520 EXPECT_TRUE(sock_->WasEverUsed()); | |
521 sock_->Disconnect(); | |
522 EXPECT_TRUE(sock_->WasEverUsed()); | |
523 } | |
524 | |
525 // ----------- GetPeerAddress | |
526 | |
527 TEST_F(SpdyProxyClientSocketTest, GetPeerAddressReturnsCorrectValues) { | |
528 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
529 MockWrite writes[] = { | |
530 CreateMockWrite(*conn, 0, SYNCHRONOUS), | |
531 }; | |
532 | |
533 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
534 MockRead reads[] = { | |
535 CreateMockRead(*resp, 1, ASYNC), | |
536 MockRead(ASYNC, 0, 2), // EOF | |
537 }; | |
538 | |
539 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
540 | |
541 net::AddressList addr; | |
542 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED, sock_->GetPeerAddress(&addr)); | |
543 | |
544 AssertConnectSucceeds(); | |
545 EXPECT_TRUE(sock_->IsConnected()); | |
546 EXPECT_EQ(OK, sock_->GetPeerAddress(&addr)); | |
547 | |
548 Run(1); | |
549 | |
550 EXPECT_FALSE(sock_->IsConnected()); | |
551 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED, sock_->GetPeerAddress(&addr)); | |
552 | |
553 sock_->Disconnect(); | |
554 | |
555 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED, sock_->GetPeerAddress(&addr)); | |
556 } | |
557 | |
558 // ----------- Write | |
559 | |
560 TEST_F(SpdyProxyClientSocketTest, WriteSendsDataInDataFrame) { | |
561 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
562 scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); | |
563 scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); | |
564 MockWrite writes[] = { | |
565 CreateMockWrite(*conn, 0, SYNCHRONOUS), | |
566 CreateMockWrite(*msg1, 2, SYNCHRONOUS), | |
567 CreateMockWrite(*msg2, 3, SYNCHRONOUS), | |
568 }; | |
569 | |
570 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
571 MockRead reads[] = { | |
572 CreateMockRead(*resp, 1, ASYNC), | |
573 MockRead(ASYNC, 0, 4), // EOF | |
574 }; | |
575 | |
576 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
577 | |
578 AssertConnectSucceeds(); | |
579 | |
580 AssertAsyncWriteSucceeds(kMsg1, kLen1); | |
581 AssertAsyncWriteSucceeds(kMsg2, kLen2); | |
582 } | |
583 | |
584 TEST_F(SpdyProxyClientSocketTest, WriteSplitsLargeDataIntoMultipleFrames) { | |
585 std::string chunk_data(kMaxSpdyFrameChunkSize, 'x'); | |
586 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
587 scoped_ptr<spdy::SpdyFrame> chunk(ConstructBodyFrame(chunk_data.data(), | |
588 chunk_data.length())); | |
589 MockWrite writes[] = { | |
590 CreateMockWrite(*conn, 0, SYNCHRONOUS), | |
591 CreateMockWrite(*chunk, 2, SYNCHRONOUS), | |
592 CreateMockWrite(*chunk, 3, SYNCHRONOUS), | |
593 CreateMockWrite(*chunk, 4, SYNCHRONOUS) | |
594 }; | |
595 | |
596 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
597 MockRead reads[] = { | |
598 CreateMockRead(*resp, 1, ASYNC), | |
599 MockRead(ASYNC, 0, 5), // EOF | |
600 }; | |
601 | |
602 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
603 | |
604 AssertConnectSucceeds(); | |
605 | |
606 std::string big_data(kMaxSpdyFrameChunkSize * 3, 'x'); | |
607 scoped_refptr<IOBufferWithSize> buf(CreateBuffer(big_data.data(), | |
608 big_data.length())); | |
609 | |
610 EXPECT_EQ(ERR_IO_PENDING, sock_->Write(buf, buf->size(), | |
611 write_callback_.callback())); | |
612 data_->RunFor(3); | |
613 | |
614 EXPECT_EQ(buf->size(), write_callback_.WaitForResult()); | |
615 } | |
616 | |
617 // ----------- Read | |
618 | |
619 TEST_F(SpdyProxyClientSocketTest, ReadReadsDataInDataFrame) { | |
620 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
621 MockWrite writes[] = { | |
622 CreateMockWrite(*conn, 0, SYNCHRONOUS), | |
623 }; | |
624 | |
625 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
626 scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); | |
627 MockRead reads[] = { | |
628 CreateMockRead(*resp, 1, ASYNC), | |
629 CreateMockRead(*msg1, 2, ASYNC), | |
630 MockRead(ASYNC, 0, 3), // EOF | |
631 }; | |
632 | |
633 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
634 | |
635 AssertConnectSucceeds(); | |
636 | |
637 Run(1); // SpdySession consumes the next read and sends it to | |
638 // sock_ to be buffered. | |
639 AssertSyncReadEquals(kMsg1, kLen1); | |
640 } | |
641 | |
642 TEST_F(SpdyProxyClientSocketTest, ReadDataFromBufferedFrames) { | |
643 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
644 MockWrite writes[] = { | |
645 CreateMockWrite(*conn, 0, SYNCHRONOUS), | |
646 }; | |
647 | |
648 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
649 scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); | |
650 scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); | |
651 MockRead reads[] = { | |
652 CreateMockRead(*resp, 1, ASYNC), | |
653 CreateMockRead(*msg1, 2, ASYNC), | |
654 CreateMockRead(*msg2, 3, ASYNC), | |
655 MockRead(ASYNC, 0, 4), // EOF | |
656 }; | |
657 | |
658 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
659 | |
660 AssertConnectSucceeds(); | |
661 | |
662 Run(1); // SpdySession consumes the next read and sends it to | |
663 // sock_ to be buffered. | |
664 AssertSyncReadEquals(kMsg1, kLen1); | |
665 Run(1); // SpdySession consumes the next read and sends it to | |
666 // sock_ to be buffered. | |
667 AssertSyncReadEquals(kMsg2, kLen2); | |
668 } | |
669 | |
670 TEST_F(SpdyProxyClientSocketTest, ReadDataMultipleBufferedFrames) { | |
671 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
672 MockWrite writes[] = { | |
673 CreateMockWrite(*conn, 0, SYNCHRONOUS), | |
674 }; | |
675 | |
676 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
677 scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); | |
678 scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); | |
679 MockRead reads[] = { | |
680 CreateMockRead(*resp, 1, ASYNC), | |
681 CreateMockRead(*msg1, 2, ASYNC), | |
682 CreateMockRead(*msg2, 3, ASYNC), | |
683 MockRead(ASYNC, 0, 4), // EOF | |
684 }; | |
685 | |
686 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
687 | |
688 AssertConnectSucceeds(); | |
689 | |
690 Run(2); // SpdySession consumes the next two reads and sends then to | |
691 // sock_ to be buffered. | |
692 AssertSyncReadEquals(kMsg1, kLen1); | |
693 AssertSyncReadEquals(kMsg2, kLen2); | |
694 } | |
695 | |
696 TEST_F(SpdyProxyClientSocketTest, LargeReadWillMergeDataFromDifferentFrames) { | |
697 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
698 MockWrite writes[] = { | |
699 CreateMockWrite(*conn, 0, SYNCHRONOUS), | |
700 }; | |
701 | |
702 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
703 scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); | |
704 scoped_ptr<spdy::SpdyFrame> msg3(ConstructBodyFrame(kMsg3, kLen3)); | |
705 MockRead reads[] = { | |
706 CreateMockRead(*resp, 1, ASYNC), | |
707 CreateMockRead(*msg3, 2, ASYNC), | |
708 CreateMockRead(*msg3, 3, ASYNC), | |
709 MockRead(ASYNC, 0, 4), // EOF | |
710 }; | |
711 | |
712 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
713 | |
714 AssertConnectSucceeds(); | |
715 | |
716 Run(2); // SpdySession consumes the next two reads and sends then to | |
717 // sock_ to be buffered. | |
718 // The payload from two data frames, each with kMsg3 will be combined | |
719 // together into a single read(). | |
720 AssertSyncReadEquals(kMsg33, kLen33); | |
721 } | |
722 | |
723 TEST_F(SpdyProxyClientSocketTest, MultipleShortReadsThenMoreRead) { | |
724 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
725 MockWrite writes[] = { | |
726 CreateMockWrite(*conn, 0, SYNCHRONOUS), | |
727 }; | |
728 | |
729 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
730 scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); | |
731 scoped_ptr<spdy::SpdyFrame> msg3(ConstructBodyFrame(kMsg3, kLen3)); | |
732 scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); | |
733 MockRead reads[] = { | |
734 CreateMockRead(*resp, 1, ASYNC), | |
735 CreateMockRead(*msg1, 2, ASYNC), | |
736 CreateMockRead(*msg3, 3, ASYNC), | |
737 CreateMockRead(*msg3, 4, ASYNC), | |
738 CreateMockRead(*msg2, 5, ASYNC), | |
739 MockRead(ASYNC, 0, 6), // EOF | |
740 }; | |
741 | |
742 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
743 | |
744 AssertConnectSucceeds(); | |
745 | |
746 Run(4); // SpdySession consumes the next four reads and sends then to | |
747 // sock_ to be buffered. | |
748 AssertSyncReadEquals(kMsg1, kLen1); | |
749 // The payload from two data frames, each with kMsg3 will be combined | |
750 // together into a single read(). | |
751 AssertSyncReadEquals(kMsg33, kLen33); | |
752 AssertSyncReadEquals(kMsg2, kLen2); | |
753 } | |
754 | |
755 TEST_F(SpdyProxyClientSocketTest, ReadWillSplitDataFromLargeFrame) { | |
756 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
757 MockWrite writes[] = { | |
758 CreateMockWrite(*conn, 0, SYNCHRONOUS), | |
759 }; | |
760 | |
761 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
762 scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); | |
763 scoped_ptr<spdy::SpdyFrame> msg33(ConstructBodyFrame(kMsg33, kLen33)); | |
764 scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); | |
765 MockRead reads[] = { | |
766 CreateMockRead(*resp, 1, ASYNC), | |
767 CreateMockRead(*msg1, 2, ASYNC), | |
768 CreateMockRead(*msg33, 3, ASYNC), | |
769 MockRead(ASYNC, 0, 4), // EOF | |
770 }; | |
771 | |
772 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
773 | |
774 AssertConnectSucceeds(); | |
775 | |
776 Run(2); // SpdySession consumes the next two reads and sends then to | |
777 // sock_ to be buffered. | |
778 AssertSyncReadEquals(kMsg1, kLen1); | |
779 // The payload from the single large data frame will be read across | |
780 // two different reads. | |
781 AssertSyncReadEquals(kMsg3, kLen3); | |
782 AssertSyncReadEquals(kMsg3, kLen3); | |
783 } | |
784 | |
785 TEST_F(SpdyProxyClientSocketTest, MultipleReadsFromSameLargeFrame) { | |
786 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
787 MockWrite writes[] = { | |
788 CreateMockWrite(*conn, 0, SYNCHRONOUS), | |
789 }; | |
790 | |
791 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
792 scoped_ptr<spdy::SpdyFrame> msg333(ConstructBodyFrame(kMsg333, kLen333)); | |
793 MockRead reads[] = { | |
794 CreateMockRead(*resp, 1, ASYNC), | |
795 CreateMockRead(*msg333, 2, ASYNC), | |
796 MockRead(ASYNC, 0, 3), // EOF | |
797 }; | |
798 | |
799 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
800 | |
801 AssertConnectSucceeds(); | |
802 | |
803 Run(1); // SpdySession consumes the next read and sends it to | |
804 // sock_ to be buffered. | |
805 // The payload from the single large data frame will be read across | |
806 // two different reads. | |
807 AssertSyncReadEquals(kMsg33, kLen33); | |
808 | |
809 // Now attempt to do a read of more data than remains buffered | |
810 scoped_refptr<IOBuffer> buf(new IOBuffer(kLen33)); | |
811 ASSERT_EQ(kLen3, sock_->Read(buf, kLen33, read_callback_.callback())); | |
812 ASSERT_EQ(std::string(kMsg3, kLen3), std::string(buf->data(), kLen3)); | |
813 ASSERT_TRUE(sock_->IsConnected()); | |
814 } | |
815 | |
816 TEST_F(SpdyProxyClientSocketTest, ReadAuthResponseBody) { | |
817 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
818 MockWrite writes[] = { | |
819 CreateMockWrite(*conn, 0, SYNCHRONOUS), | |
820 }; | |
821 | |
822 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectAuthReplyFrame()); | |
823 scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); | |
824 scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); | |
825 MockRead reads[] = { | |
826 CreateMockRead(*resp, 1, ASYNC), | |
827 CreateMockRead(*msg1, 2, ASYNC), | |
828 CreateMockRead(*msg2, 3, ASYNC), | |
829 MockRead(ASYNC, 0, 4), // EOF | |
830 }; | |
831 | |
832 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
833 | |
834 AssertConnectFails(ERR_PROXY_AUTH_REQUESTED); | |
835 | |
836 Run(2); // SpdySession consumes the next two reads and sends then to | |
837 // sock_ to be buffered. | |
838 AssertSyncReadEquals(kMsg1, kLen1); | |
839 AssertSyncReadEquals(kMsg2, kLen2); | |
840 } | |
841 | |
842 TEST_F(SpdyProxyClientSocketTest, ReadErrorResponseBody) { | |
843 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
844 MockWrite writes[] = { | |
845 CreateMockWrite(*conn, 0, SYNCHRONOUS), | |
846 }; | |
847 | |
848 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectErrorReplyFrame()); | |
849 scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); | |
850 scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); | |
851 MockRead reads[] = { | |
852 CreateMockRead(*resp, 1, ASYNC), | |
853 CreateMockRead(*msg1, 2, ASYNC), | |
854 CreateMockRead(*msg2, 3, ASYNC), | |
855 MockRead(ASYNC, 0, 4), // EOF | |
856 }; | |
857 | |
858 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
859 | |
860 AssertConnectFails(ERR_HTTPS_PROXY_TUNNEL_RESPONSE); | |
861 | |
862 Run(2); // SpdySession consumes the next two reads and sends then to | |
863 // sock_ to be buffered. | |
864 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED, | |
865 sock_->Read(NULL, 1, CompletionCallback())); | |
866 scoped_refptr<IOBuffer> buf(new IOBuffer(kLen1 + kLen2)); | |
867 scoped_ptr<HttpStream> stream(sock_->CreateConnectResponseStream()); | |
868 stream->ReadResponseBody(buf, kLen1 + kLen2, read_callback_.callback()); | |
869 } | |
870 | |
871 // ----------- Reads and Writes | |
872 | |
873 TEST_F(SpdyProxyClientSocketTest, AsyncReadAroundWrite) { | |
874 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
875 scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); | |
876 MockWrite writes[] = { | |
877 CreateMockWrite(*conn, 0, SYNCHRONOUS), | |
878 CreateMockWrite(*msg2, 3, SYNCHRONOUS), | |
879 }; | |
880 | |
881 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
882 scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); | |
883 scoped_ptr<spdy::SpdyFrame> msg3(ConstructBodyFrame(kMsg3, kLen3)); | |
884 MockRead reads[] = { | |
885 CreateMockRead(*resp, 1, ASYNC), | |
886 CreateMockRead(*msg1, 2, ASYNC), // sync read | |
887 CreateMockRead(*msg3, 4, ASYNC), // async read | |
888 MockRead(ASYNC, 0, 5), // EOF | |
889 }; | |
890 | |
891 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
892 | |
893 AssertConnectSucceeds(); | |
894 | |
895 Run(1); | |
896 AssertSyncReadEquals(kMsg1, kLen1); | |
897 | |
898 AssertReadStarts(kMsg3, kLen3); | |
899 // Read should block until after the write succeeds | |
900 | |
901 AssertAsyncWriteSucceeds(kMsg2, kLen2); // Runs 1 step | |
902 | |
903 ASSERT_FALSE(read_callback_.have_result()); | |
904 Run(1); | |
905 // Now the read will return | |
906 AssertReadReturns(kMsg3, kLen3); | |
907 } | |
908 | |
909 TEST_F(SpdyProxyClientSocketTest, AsyncWriteAroundReads) { | |
910 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
911 scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2)); | |
912 MockWrite writes[] = { | |
913 CreateMockWrite(*conn, 0, SYNCHRONOUS), | |
914 CreateMockWrite(*msg2, 4, ASYNC), | |
915 }; | |
916 | |
917 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
918 scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); | |
919 scoped_ptr<spdy::SpdyFrame> msg3(ConstructBodyFrame(kMsg3, kLen3)); | |
920 MockRead reads[] = { | |
921 CreateMockRead(*resp, 1, ASYNC), | |
922 CreateMockRead(*msg1, 2, ASYNC), | |
923 CreateMockRead(*msg3, 3, ASYNC), | |
924 MockRead(ASYNC, 0, 5), // EOF | |
925 }; | |
926 | |
927 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
928 | |
929 AssertConnectSucceeds(); | |
930 | |
931 Run(1); | |
932 AssertSyncReadEquals(kMsg1, kLen1); | |
933 // Write should block until the read completes | |
934 AssertWriteReturns(kMsg2, kLen2, ERR_IO_PENDING); | |
935 | |
936 AssertAsyncReadEquals(kMsg3, kLen3); | |
937 | |
938 ASSERT_FALSE(write_callback_.have_result()); | |
939 | |
940 // Now the write will complete | |
941 Run(1); | |
942 AssertWriteLength(kLen2); | |
943 } | |
944 | |
945 // ----------- Reading/Writing on Closed socket | |
946 | |
947 // Reading from an already closed socket should return 0 | |
948 TEST_F(SpdyProxyClientSocketTest, ReadOnClosedSocketReturnsZero) { | |
949 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
950 MockWrite writes[] = { | |
951 CreateMockWrite(*conn, 0, SYNCHRONOUS), | |
952 }; | |
953 | |
954 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
955 MockRead reads[] = { | |
956 CreateMockRead(*resp, 1, ASYNC), | |
957 MockRead(ASYNC, 0, 2), // EOF | |
958 }; | |
959 | |
960 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
961 | |
962 AssertConnectSucceeds(); | |
963 | |
964 Run(1); | |
965 | |
966 ASSERT_FALSE(sock_->IsConnected()); | |
967 ASSERT_EQ(0, sock_->Read(NULL, 1, CompletionCallback())); | |
968 ASSERT_EQ(0, sock_->Read(NULL, 1, CompletionCallback())); | |
969 ASSERT_EQ(0, sock_->Read(NULL, 1, CompletionCallback())); | |
970 ASSERT_FALSE(sock_->IsConnectedAndIdle()); | |
971 } | |
972 | |
973 // Read pending when socket is closed should return 0 | |
974 TEST_F(SpdyProxyClientSocketTest, PendingReadOnCloseReturnsZero) { | |
975 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
976 MockWrite writes[] = { | |
977 CreateMockWrite(*conn, 0, SYNCHRONOUS), | |
978 }; | |
979 | |
980 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
981 MockRead reads[] = { | |
982 CreateMockRead(*resp, 1, ASYNC), | |
983 MockRead(ASYNC, 0, 2), // EOF | |
984 }; | |
985 | |
986 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
987 | |
988 AssertConnectSucceeds(); | |
989 | |
990 AssertReadStarts(kMsg1, kLen1); | |
991 | |
992 Run(1); | |
993 | |
994 ASSERT_EQ(0, read_callback_.WaitForResult()); | |
995 } | |
996 | |
997 // Reading from a disconnected socket is an error | |
998 TEST_F(SpdyProxyClientSocketTest, ReadOnDisconnectSocketReturnsNotConnected) { | |
999 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
1000 MockWrite writes[] = { | |
1001 CreateMockWrite(*conn, 0, SYNCHRONOUS), | |
1002 }; | |
1003 | |
1004 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
1005 MockRead reads[] = { | |
1006 CreateMockRead(*resp, 1, ASYNC), | |
1007 MockRead(ASYNC, 0, 2), // EOF | |
1008 }; | |
1009 | |
1010 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
1011 | |
1012 AssertConnectSucceeds(); | |
1013 | |
1014 sock_->Disconnect(); | |
1015 | |
1016 ASSERT_EQ(ERR_SOCKET_NOT_CONNECTED, | |
1017 sock_->Read(NULL, 1, CompletionCallback())); | |
1018 } | |
1019 | |
1020 // Reading buffered data from an already closed socket should return | |
1021 // buffered data, then 0. | |
1022 TEST_F(SpdyProxyClientSocketTest, ReadOnClosedSocketReturnsBufferedData) { | |
1023 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
1024 MockWrite writes[] = { | |
1025 CreateMockWrite(*conn, 0, SYNCHRONOUS), | |
1026 }; | |
1027 | |
1028 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
1029 scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); | |
1030 MockRead reads[] = { | |
1031 CreateMockRead(*resp, 1, ASYNC), | |
1032 CreateMockRead(*msg1, 2, ASYNC), | |
1033 MockRead(ASYNC, 0, 3), // EOF | |
1034 }; | |
1035 | |
1036 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
1037 | |
1038 AssertConnectSucceeds(); | |
1039 | |
1040 Run(2); | |
1041 | |
1042 ASSERT_FALSE(sock_->IsConnected()); | |
1043 scoped_refptr<IOBuffer> buf(new IOBuffer(kLen1)); | |
1044 ASSERT_EQ(kLen1, sock_->Read(buf, kLen1, CompletionCallback())); | |
1045 ASSERT_EQ(std::string(kMsg1, kLen1), std::string(buf->data(), kLen1)); | |
1046 | |
1047 ASSERT_EQ(0, sock_->Read(NULL, 1, CompletionCallback())); | |
1048 ASSERT_EQ(0, sock_->Read(NULL, 1, CompletionCallback())); | |
1049 sock_->Disconnect(); | |
1050 ASSERT_EQ(ERR_SOCKET_NOT_CONNECTED, | |
1051 sock_->Read(NULL, 1, CompletionCallback())); | |
1052 } | |
1053 | |
1054 // Calling Write() on a closed socket is an error | |
1055 TEST_F(SpdyProxyClientSocketTest, WriteOnClosedStream) { | |
1056 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
1057 MockWrite writes[] = { | |
1058 CreateMockWrite(*conn, 0, SYNCHRONOUS), | |
1059 }; | |
1060 | |
1061 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
1062 scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); | |
1063 MockRead reads[] = { | |
1064 CreateMockRead(*resp, 1, ASYNC), | |
1065 MockRead(ASYNC, 0, 2), // EOF | |
1066 }; | |
1067 | |
1068 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
1069 | |
1070 AssertConnectSucceeds(); | |
1071 | |
1072 Run(1); // Read EOF which will close the stream | |
1073 scoped_refptr<IOBufferWithSize> buf(CreateBuffer(kMsg1, kLen1)); | |
1074 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED, | |
1075 sock_->Write(buf, buf->size(), CompletionCallback())); | |
1076 } | |
1077 | |
1078 // Calling Write() on a disconnected socket is an error | |
1079 TEST_F(SpdyProxyClientSocketTest, WriteOnDisconnectedSocket) { | |
1080 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
1081 MockWrite writes[] = { | |
1082 CreateMockWrite(*conn, 0, SYNCHRONOUS), | |
1083 }; | |
1084 | |
1085 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
1086 scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1)); | |
1087 MockRead reads[] = { | |
1088 CreateMockRead(*resp, 1, ASYNC), | |
1089 MockRead(ASYNC, 0, 2), // EOF | |
1090 }; | |
1091 | |
1092 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
1093 | |
1094 AssertConnectSucceeds(); | |
1095 | |
1096 sock_->Disconnect(); | |
1097 | |
1098 scoped_refptr<IOBufferWithSize> buf(CreateBuffer(kMsg1, kLen1)); | |
1099 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED, | |
1100 sock_->Write(buf, buf->size(), CompletionCallback())); | |
1101 } | |
1102 | |
1103 // If the socket is closed with a pending Write(), the callback | |
1104 // should be called with ERR_CONNECTION_CLOSED. | |
1105 TEST_F(SpdyProxyClientSocketTest, WritePendingOnClose) { | |
1106 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
1107 MockWrite writes[] = { | |
1108 CreateMockWrite(*conn, 0, SYNCHRONOUS), | |
1109 MockWrite(ASYNC, ERR_IO_PENDING, 2), | |
1110 }; | |
1111 | |
1112 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
1113 MockRead reads[] = { | |
1114 CreateMockRead(*resp, 1, ASYNC), | |
1115 MockRead(ASYNC, 0, 3), // EOF | |
1116 }; | |
1117 | |
1118 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
1119 | |
1120 AssertConnectSucceeds(); | |
1121 | |
1122 EXPECT_TRUE(sock_->IsConnected()); | |
1123 | |
1124 scoped_refptr<IOBufferWithSize> buf(CreateBuffer(kMsg1, kLen1)); | |
1125 EXPECT_EQ(ERR_IO_PENDING, | |
1126 sock_->Write(buf, buf->size(), write_callback_.callback())); | |
1127 | |
1128 Run(1); | |
1129 | |
1130 EXPECT_EQ(ERR_CONNECTION_CLOSED, write_callback_.WaitForResult()); | |
1131 } | |
1132 | |
1133 // If the socket is Disconnected with a pending Write(), the callback | |
1134 // should not be called. | |
1135 TEST_F(SpdyProxyClientSocketTest, DisconnectWithWritePending) { | |
1136 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
1137 MockWrite writes[] = { | |
1138 CreateMockWrite(*conn, 0, SYNCHRONOUS), | |
1139 MockWrite(SYNCHRONOUS, 0, 2), // EOF | |
1140 }; | |
1141 | |
1142 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
1143 MockRead reads[] = { | |
1144 CreateMockRead(*resp, 1, ASYNC), | |
1145 MockRead(ASYNC, 0, 3), // EOF | |
1146 }; | |
1147 | |
1148 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
1149 | |
1150 AssertConnectSucceeds(); | |
1151 | |
1152 EXPECT_TRUE(sock_->IsConnected()); | |
1153 | |
1154 scoped_refptr<IOBufferWithSize> buf(CreateBuffer(kMsg1, kLen1)); | |
1155 EXPECT_EQ(ERR_IO_PENDING, | |
1156 sock_->Write(buf, buf->size(), write_callback_.callback())); | |
1157 | |
1158 sock_->Disconnect(); | |
1159 | |
1160 EXPECT_FALSE(sock_->IsConnected()); | |
1161 EXPECT_FALSE(write_callback_.have_result()); | |
1162 } | |
1163 | |
1164 // If the socket is Disconnected with a pending Read(), the callback | |
1165 // should not be called. | |
1166 TEST_F(SpdyProxyClientSocketTest, DisconnectWithReadPending) { | |
1167 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
1168 MockWrite writes[] = { | |
1169 CreateMockWrite(*conn, 0, SYNCHRONOUS), | |
1170 }; | |
1171 | |
1172 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
1173 MockRead reads[] = { | |
1174 CreateMockRead(*resp, 1, ASYNC), | |
1175 MockRead(ASYNC, 0, 2), // EOF | |
1176 }; | |
1177 | |
1178 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
1179 | |
1180 AssertConnectSucceeds(); | |
1181 | |
1182 EXPECT_TRUE(sock_->IsConnected()); | |
1183 | |
1184 scoped_refptr<IOBuffer> buf(new IOBuffer(kLen1)); | |
1185 ASSERT_EQ(ERR_IO_PENDING, | |
1186 sock_->Read(buf, kLen1, read_callback_.callback())); | |
1187 | |
1188 sock_->Disconnect(); | |
1189 | |
1190 EXPECT_FALSE(sock_->IsConnected()); | |
1191 EXPECT_FALSE(read_callback_.have_result()); | |
1192 } | |
1193 | |
1194 // If the socket is Reset when both a read and write are pending, | |
1195 // both should be called back. | |
1196 TEST_F(SpdyProxyClientSocketTest, RstWithReadAndWritePending) { | |
1197 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
1198 MockWrite writes[] = { | |
1199 CreateMockWrite(*conn, 0, SYNCHRONOUS), | |
1200 MockWrite(ASYNC, ERR_IO_PENDING, 2), | |
1201 }; | |
1202 | |
1203 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
1204 scoped_ptr<spdy::SpdyFrame> rst(ConstructSpdyRstStream(1, spdy::CANCEL)); | |
1205 MockRead reads[] = { | |
1206 CreateMockRead(*resp, 1, ASYNC), | |
1207 CreateMockRead(*rst, 3, ASYNC), | |
1208 }; | |
1209 | |
1210 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
1211 | |
1212 AssertConnectSucceeds(); | |
1213 | |
1214 EXPECT_TRUE(sock_->IsConnected()); | |
1215 | |
1216 scoped_refptr<IOBuffer> read_buf(new IOBuffer(kLen1)); | |
1217 ASSERT_EQ(ERR_IO_PENDING, | |
1218 sock_->Read(read_buf, kLen1, read_callback_.callback())); | |
1219 | |
1220 scoped_refptr<IOBufferWithSize> write_buf(CreateBuffer(kMsg1, kLen1)); | |
1221 EXPECT_EQ(ERR_IO_PENDING, | |
1222 sock_->Write(write_buf, write_buf->size(), | |
1223 write_callback_.callback())); | |
1224 | |
1225 Run(2); | |
1226 | |
1227 EXPECT_TRUE(sock_.get()); | |
1228 EXPECT_TRUE(read_callback_.have_result()); | |
1229 EXPECT_TRUE(write_callback_.have_result()); | |
1230 } | |
1231 | |
1232 // CompletionCallback that causes the SpdyProxyClientSocket to be | |
1233 // deleted when Run is invoked. | |
1234 class DeleteSockCallback : public TestCompletionCallbackBase { | |
1235 public: | |
1236 explicit DeleteSockCallback(scoped_ptr<SpdyProxyClientSocket>* sock) | |
1237 : sock_(sock), | |
1238 ALLOW_THIS_IN_INITIALIZER_LIST(callback_( | |
1239 base::Bind(&DeleteSockCallback::OnComplete, | |
1240 base::Unretained(this)))) { | |
1241 } | |
1242 | |
1243 virtual ~DeleteSockCallback() { | |
1244 } | |
1245 | |
1246 const CompletionCallback& callback() const { return callback_; } | |
1247 | |
1248 private: | |
1249 void OnComplete(int result) { | |
1250 sock_->reset(NULL); | |
1251 SetResult(result); | |
1252 } | |
1253 | |
1254 scoped_ptr<SpdyProxyClientSocket>* sock_; | |
1255 CompletionCallback callback_; | |
1256 | |
1257 DISALLOW_COPY_AND_ASSIGN(DeleteSockCallback); | |
1258 }; | |
1259 | |
1260 // If the socket is Reset when both a read and write are pending, and the | |
1261 // read callback causes the socket to be deleted, the write callback should | |
1262 // not be called. | |
1263 TEST_F(SpdyProxyClientSocketTest, RstWithReadAndWritePendingDelete) { | |
1264 scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame()); | |
1265 MockWrite writes[] = { | |
1266 CreateMockWrite(*conn, 0, SYNCHRONOUS), | |
1267 MockWrite(ASYNC, ERR_IO_PENDING, 2), | |
1268 }; | |
1269 | |
1270 scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame()); | |
1271 scoped_ptr<spdy::SpdyFrame> rst(ConstructSpdyRstStream(1, spdy::CANCEL)); | |
1272 MockRead reads[] = { | |
1273 CreateMockRead(*resp, 1, ASYNC), | |
1274 CreateMockRead(*rst, 3, ASYNC), | |
1275 }; | |
1276 | |
1277 Initialize(reads, arraysize(reads), writes, arraysize(writes)); | |
1278 | |
1279 AssertConnectSucceeds(); | |
1280 | |
1281 EXPECT_TRUE(sock_->IsConnected()); | |
1282 | |
1283 DeleteSockCallback read_callback(&sock_); | |
1284 | |
1285 scoped_refptr<IOBuffer> read_buf(new IOBuffer(kLen1)); | |
1286 ASSERT_EQ(ERR_IO_PENDING, | |
1287 sock_->Read(read_buf, kLen1, read_callback.callback())); | |
1288 | |
1289 scoped_refptr<IOBufferWithSize> write_buf(CreateBuffer(kMsg1, kLen1)); | |
1290 EXPECT_EQ(ERR_IO_PENDING, sock_->Write(write_buf, write_buf->size(), | |
1291 write_callback_.callback())); | |
1292 | |
1293 Run(2); | |
1294 | |
1295 EXPECT_FALSE(sock_.get()); | |
1296 EXPECT_TRUE(read_callback.have_result()); | |
1297 EXPECT_FALSE(write_callback_.have_result()); | |
1298 } | |
1299 | |
1300 } // namespace net | |
OLD | NEW |