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