Enables compositing support for webview.
[chromium-blink-merge.git] / net / spdy / spdy_http_stream_spdy3_unittest.cc
blob1b7760b4b5f87033d58e53bd7bcea74b0043f0db
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.
5 #include "net/spdy/spdy_http_stream.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "base/threading/sequenced_worker_pool.h"
9 #include "crypto/ec_private_key.h"
10 #include "crypto/ec_signature_creator.h"
11 #include "crypto/signature_creator.h"
12 #include "net/base/asn1_util.h"
13 #include "net/base/default_server_bound_cert_store.h"
14 #include "net/base/upload_data_stream.h"
15 #include "net/base/upload_element_reader.h"
16 #include "net/http/http_request_info.h"
17 #include "net/http/http_response_headers.h"
18 #include "net/http/http_response_info.h"
19 #include "net/spdy/spdy_credential_builder.h"
20 #include "net/spdy/spdy_http_utils.h"
21 #include "net/spdy/spdy_session.h"
22 #include "net/spdy/spdy_test_util_spdy3.h"
23 #include "testing/gtest/include/gtest/gtest.h"
25 using namespace net::test_spdy3;
27 namespace net {
29 class SpdyHttpStreamSpdy3Test : public testing::Test {
30 public:
31 OrderedSocketData* data() { return data_.get(); }
33 protected:
34 virtual void TearDown() {
35 UploadDataStream::ResetMergeChunks();
36 MessageLoop::current()->RunUntilIdle();
39 void set_merge_chunks(bool merge) {
40 UploadDataStream::set_merge_chunks(merge);
43 int InitSession(MockRead* reads, size_t reads_count,
44 MockWrite* writes, size_t writes_count,
45 HostPortPair& host_port_pair) {
46 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
47 data_.reset(new OrderedSocketData(reads, reads_count,
48 writes, writes_count));
49 session_deps_.socket_factory->AddSocketDataProvider(data_.get());
50 http_session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
51 session_ = http_session_->spdy_session_pool()->Get(pair, BoundNetLog());
52 transport_params_ = new TransportSocketParams(host_port_pair,
53 MEDIUM, false, false,
54 OnHostResolutionCallback());
55 TestCompletionCallback callback;
56 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
57 EXPECT_EQ(ERR_IO_PENDING,
58 connection->Init(host_port_pair.ToString(),
59 transport_params_,
60 MEDIUM,
61 callback.callback(),
62 http_session_->GetTransportSocketPool(
63 HttpNetworkSession::NORMAL_SOCKET_POOL),
64 BoundNetLog()));
65 EXPECT_EQ(OK, callback.WaitForResult());
66 return session_->InitializeWithSocket(connection.release(), false, OK);
69 void TestSendCredentials(
70 ServerBoundCertService* server_bound_cert_service,
71 const std::string& cert,
72 const std::string& proof);
74 SpdySessionDependencies session_deps_;
75 scoped_ptr<OrderedSocketData> data_;
76 scoped_refptr<HttpNetworkSession> http_session_;
77 scoped_refptr<SpdySession> session_;
78 scoped_refptr<TransportSocketParams> transport_params_;
80 private:
81 MockECSignatureCreatorFactory ec_signature_creator_factory_;
84 TEST_F(SpdyHttpStreamSpdy3Test, SendRequest) {
85 scoped_ptr<SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
86 MockWrite writes[] = {
87 CreateMockWrite(*req.get(), 1),
89 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
90 MockRead reads[] = {
91 CreateMockRead(*resp, 2),
92 MockRead(SYNCHRONOUS, 0, 3) // EOF
95 HostPortPair host_port_pair("www.google.com", 80);
96 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
97 EXPECT_EQ(OK, InitSession(reads, arraysize(reads), writes, arraysize(writes),
98 host_port_pair));
100 HttpRequestInfo request;
101 request.method = "GET";
102 request.url = GURL("http://www.google.com/");
103 TestCompletionCallback callback;
104 HttpResponseInfo response;
105 HttpRequestHeaders headers;
106 BoundNetLog net_log;
107 scoped_ptr<SpdyHttpStream> http_stream(
108 new SpdyHttpStream(session_.get(), true));
109 ASSERT_EQ(
111 http_stream->InitializeStream(&request, net_log, CompletionCallback()));
113 EXPECT_EQ(ERR_IO_PENDING, http_stream->SendRequest(headers, &response,
114 callback.callback()));
115 EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession(pair));
117 // This triggers the MockWrite and read 2
118 callback.WaitForResult();
120 // This triggers read 3. The empty read causes the session to shut down.
121 data()->CompleteRead();
123 // Because we abandoned the stream, we don't expect to find a session in the
124 // pool anymore.
125 EXPECT_FALSE(http_session_->spdy_session_pool()->HasSession(pair));
126 EXPECT_TRUE(data()->at_read_eof());
127 EXPECT_TRUE(data()->at_write_eof());
130 TEST_F(SpdyHttpStreamSpdy3Test, SendChunkedPost) {
131 set_merge_chunks(false);
133 scoped_ptr<SpdyFrame> req(ConstructChunkedSpdyPost(NULL, 0));
134 scoped_ptr<SpdyFrame> chunk1(ConstructSpdyBodyFrame(1, false));
135 scoped_ptr<SpdyFrame> chunk2(ConstructSpdyBodyFrame(1, true));
136 MockWrite writes[] = {
137 CreateMockWrite(*req.get(), 0),
138 CreateMockWrite(*chunk1, 1), // POST upload frames
139 CreateMockWrite(*chunk2, 2),
141 scoped_ptr<SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
142 MockRead reads[] = {
143 CreateMockRead(*resp, 3),
144 CreateMockRead(*chunk1, 4),
145 CreateMockRead(*chunk2, 5),
146 MockRead(SYNCHRONOUS, 0, 6) // EOF
149 HostPortPair host_port_pair("www.google.com", 80);
150 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
151 EXPECT_EQ(OK, InitSession(reads, arraysize(reads), writes, arraysize(writes),
152 host_port_pair));
154 UploadDataStream upload_stream(UploadDataStream::CHUNKED, 0);
155 upload_stream.AppendChunk(kUploadData, kUploadDataSize, false);
156 upload_stream.AppendChunk(kUploadData, kUploadDataSize, true);
158 HttpRequestInfo request;
159 request.method = "POST";
160 request.url = GURL("http://www.google.com/");
161 request.upload_data_stream = &upload_stream;
163 ASSERT_EQ(OK, upload_stream.Init(CompletionCallback()));
165 TestCompletionCallback callback;
166 HttpResponseInfo response;
167 HttpRequestHeaders headers;
168 BoundNetLog net_log;
169 SpdyHttpStream http_stream(session_.get(), true);
170 ASSERT_EQ(
172 http_stream.InitializeStream(&request, net_log, CompletionCallback()));
174 EXPECT_EQ(ERR_IO_PENDING, http_stream.SendRequest(
175 headers, &response, callback.callback()));
176 EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession(pair));
178 // This triggers the MockWrite and read 2
179 callback.WaitForResult();
181 // This triggers read 3. The empty read causes the session to shut down.
182 data()->CompleteRead();
183 MessageLoop::current()->RunUntilIdle();
185 // Because we abandoned the stream, we don't expect to find a session in the
186 // pool anymore.
187 EXPECT_FALSE(http_session_->spdy_session_pool()->HasSession(pair));
188 EXPECT_TRUE(data()->at_read_eof());
189 EXPECT_TRUE(data()->at_write_eof());
192 // Test to ensure the SpdyStream state machine does not get confused when a
193 // chunk becomes available while a write is pending.
194 TEST_F(SpdyHttpStreamSpdy3Test, DelayedSendChunkedPost) {
195 set_merge_chunks(false);
197 const char kUploadData1[] = "12345678";
198 const int kUploadData1Size = arraysize(kUploadData1)-1;
199 scoped_ptr<SpdyFrame> req(ConstructChunkedSpdyPost(NULL, 0));
200 scoped_ptr<SpdyFrame> chunk1(ConstructSpdyBodyFrame(1, false));
201 scoped_ptr<SpdyFrame> chunk2(
202 ConstructSpdyBodyFrame(1, kUploadData1, kUploadData1Size, false));
203 scoped_ptr<SpdyFrame> chunk3(ConstructSpdyBodyFrame(1, true));
204 MockWrite writes[] = {
205 CreateMockWrite(*req.get(), 0),
206 CreateMockWrite(*chunk1, 1), // POST upload frames
207 CreateMockWrite(*chunk2, 2),
208 CreateMockWrite(*chunk3, 3),
210 scoped_ptr<SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
211 MockRead reads[] = {
212 CreateMockRead(*resp, 4),
213 CreateMockRead(*chunk1, 5),
214 CreateMockRead(*chunk2, 6),
215 CreateMockRead(*chunk3, 7),
216 MockRead(ASYNC, 0, 8) // EOF
219 HostPortPair host_port_pair("www.google.com", 80);
220 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
222 DeterministicSocketData data(reads, arraysize(reads),
223 writes, arraysize(writes));
225 DeterministicMockClientSocketFactory* socket_factory =
226 session_deps_.deterministic_socket_factory.get();
227 socket_factory->AddSocketDataProvider(&data);
229 http_session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic(
230 &session_deps_);
231 session_ = http_session_->spdy_session_pool()->Get(pair, BoundNetLog());
232 transport_params_ = new TransportSocketParams(host_port_pair,
233 MEDIUM, false, false,
234 OnHostResolutionCallback());
236 TestCompletionCallback callback;
237 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
239 EXPECT_EQ(ERR_IO_PENDING,
240 connection->Init(host_port_pair.ToString(),
241 transport_params_,
242 MEDIUM,
243 callback.callback(),
244 http_session_->GetTransportSocketPool(
245 HttpNetworkSession::NORMAL_SOCKET_POOL),
246 BoundNetLog()));
248 callback.WaitForResult();
249 EXPECT_EQ(OK,
250 session_->InitializeWithSocket(connection.release(), false, OK));
252 UploadDataStream upload_stream(UploadDataStream::CHUNKED, 0);
254 HttpRequestInfo request;
255 request.method = "POST";
256 request.url = GURL("http://www.google.com/");
257 request.upload_data_stream = &upload_stream;
259 ASSERT_EQ(OK, upload_stream.Init(CompletionCallback()));
260 upload_stream.AppendChunk(kUploadData, kUploadDataSize, false);
262 BoundNetLog net_log;
263 scoped_ptr<SpdyHttpStream> http_stream(
264 new SpdyHttpStream(session_.get(), true));
265 ASSERT_EQ(OK, http_stream->InitializeStream(&request,
266 net_log,
267 CompletionCallback()));
269 HttpRequestHeaders headers;
270 HttpResponseInfo response;
271 // This will attempt to Write() the initial request and headers, which will
272 // complete asynchronously.
273 EXPECT_EQ(ERR_IO_PENDING, http_stream->SendRequest(headers, &response,
274 callback.callback()));
275 EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession(pair));
277 // Complete the initial request write and the first chunk.
278 data.RunFor(2);
279 ASSERT_TRUE(callback.have_result());
280 EXPECT_GT(callback.WaitForResult(), 0);
282 // Now append the final two chunks which will enqueue two more writes.
283 upload_stream.AppendChunk(kUploadData1, kUploadData1Size, false);
284 upload_stream.AppendChunk(kUploadData, kUploadDataSize, true);
286 // Finish writing all the chunks.
287 data.RunFor(2);
289 // Read response headers.
290 data.RunFor(1);
291 ASSERT_EQ(OK, http_stream->ReadResponseHeaders(callback.callback()));
293 // Read and check |chunk1| response.
294 data.RunFor(1);
295 scoped_refptr<IOBuffer> buf1(new IOBuffer(kUploadDataSize));
296 ASSERT_EQ(kUploadDataSize,
297 http_stream->ReadResponseBody(buf1,
298 kUploadDataSize,
299 callback.callback()));
300 EXPECT_EQ(kUploadData, std::string(buf1->data(), kUploadDataSize));
302 // Read and check |chunk2| response.
303 data.RunFor(1);
304 scoped_refptr<IOBuffer> buf2(new IOBuffer(kUploadData1Size));
305 ASSERT_EQ(kUploadData1Size,
306 http_stream->ReadResponseBody(buf2,
307 kUploadData1Size,
308 callback.callback()));
309 EXPECT_EQ(kUploadData1, std::string(buf2->data(), kUploadData1Size));
311 // Read and check |chunk3| response.
312 data.RunFor(1);
313 scoped_refptr<IOBuffer> buf3(new IOBuffer(kUploadDataSize));
314 ASSERT_EQ(kUploadDataSize,
315 http_stream->ReadResponseBody(buf3,
316 kUploadDataSize,
317 callback.callback()));
318 EXPECT_EQ(kUploadData, std::string(buf3->data(), kUploadDataSize));
320 // Finish reading the |EOF|.
321 data.RunFor(1);
322 ASSERT_TRUE(response.headers.get());
323 ASSERT_EQ(200, response.headers->response_code());
324 EXPECT_TRUE(data.at_read_eof());
325 EXPECT_TRUE(data.at_write_eof());
328 // Test the receipt of a WINDOW_UPDATE frame while waiting for a chunk to be
329 // made available is handled correctly.
330 TEST_F(SpdyHttpStreamSpdy3Test, DelayedSendChunkedPostWithWindowUpdate) {
331 set_merge_chunks(false);
333 scoped_ptr<SpdyFrame> req(ConstructChunkedSpdyPost(NULL, 0));
334 scoped_ptr<SpdyFrame> chunk1(ConstructSpdyBodyFrame(1, true));
335 MockWrite writes[] = {
336 CreateMockWrite(*req.get(), 0),
337 CreateMockWrite(*chunk1, 1),
339 scoped_ptr<SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
340 scoped_ptr<SpdyFrame> window_update(
341 ConstructSpdyWindowUpdate(1, kUploadDataSize));
342 MockRead reads[] = {
343 CreateMockRead(*window_update, 2),
344 CreateMockRead(*resp, 3),
345 CreateMockRead(*chunk1, 4),
346 MockRead(ASYNC, 0, 5) // EOF
349 HostPortPair host_port_pair("www.google.com", 80);
350 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
352 DeterministicSocketData data(reads, arraysize(reads),
353 writes, arraysize(writes));
355 DeterministicMockClientSocketFactory* socket_factory =
356 session_deps_.deterministic_socket_factory.get();
357 socket_factory->AddSocketDataProvider(&data);
359 http_session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic(
360 &session_deps_);
361 session_ = http_session_->spdy_session_pool()->Get(pair, BoundNetLog());
362 transport_params_ = new TransportSocketParams(host_port_pair,
363 MEDIUM, false, false,
364 OnHostResolutionCallback());
366 TestCompletionCallback callback;
367 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
369 EXPECT_EQ(ERR_IO_PENDING,
370 connection->Init(host_port_pair.ToString(),
371 transport_params_,
372 MEDIUM,
373 callback.callback(),
374 http_session_->GetTransportSocketPool(
375 HttpNetworkSession::NORMAL_SOCKET_POOL),
376 BoundNetLog()));
378 callback.WaitForResult();
379 EXPECT_EQ(OK,
380 session_->InitializeWithSocket(connection.release(), false, OK));
382 UploadDataStream upload_stream(UploadDataStream::CHUNKED, 0);
384 HttpRequestInfo request;
385 request.method = "POST";
386 request.url = GURL("http://www.google.com/");
387 request.upload_data_stream = &upload_stream;
389 ASSERT_EQ(OK, upload_stream.Init(CompletionCallback()));
390 upload_stream.AppendChunk(kUploadData, kUploadDataSize, true);
392 BoundNetLog net_log;
393 scoped_ptr<SpdyHttpStream> http_stream(
394 new SpdyHttpStream(session_.get(), true));
395 ASSERT_EQ(OK, http_stream->InitializeStream(&request, net_log,
396 CompletionCallback()));
398 HttpRequestHeaders headers;
399 HttpResponseInfo response;
400 // This will attempt to Write() the initial request and headers, which will
401 // complete asynchronously.
402 EXPECT_EQ(ERR_IO_PENDING, http_stream->SendRequest(headers, &response,
403 callback.callback()));
404 EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession(pair));
406 // Complete the initial request write and first chunk.
407 data.RunFor(2);
408 ASSERT_TRUE(callback.have_result());
409 EXPECT_GT(callback.WaitForResult(), 0);
411 // Verify that the window size has decreased.
412 ASSERT_TRUE(http_stream->stream() != NULL);
413 EXPECT_NE(static_cast<int>(kSpdyStreamInitialWindowSize),
414 http_stream->stream()->send_window_size());
416 // Read window update.
417 data.RunFor(1);
419 // Verify the window update.
420 ASSERT_TRUE(http_stream->stream() != NULL);
421 EXPECT_EQ(static_cast<int>(kSpdyStreamInitialWindowSize),
422 http_stream->stream()->send_window_size());
424 // Read response headers.
425 data.RunFor(1);
426 ASSERT_EQ(OK, http_stream->ReadResponseHeaders(callback.callback()));
428 // Read and check |chunk1| response.
429 data.RunFor(1);
430 scoped_refptr<IOBuffer> buf1(new IOBuffer(kUploadDataSize));
431 ASSERT_EQ(kUploadDataSize,
432 http_stream->ReadResponseBody(buf1,
433 kUploadDataSize,
434 callback.callback()));
435 EXPECT_EQ(kUploadData, std::string(buf1->data(), kUploadDataSize));
437 // Finish reading the |EOF|.
438 data.RunFor(1);
439 ASSERT_TRUE(response.headers.get());
440 ASSERT_EQ(200, response.headers->response_code());
441 EXPECT_TRUE(data.at_read_eof());
442 EXPECT_TRUE(data.at_write_eof());
445 // Test case for bug: http://code.google.com/p/chromium/issues/detail?id=50058
446 TEST_F(SpdyHttpStreamSpdy3Test, SpdyURLTest) {
447 const char * const full_url = "http://www.google.com/foo?query=what#anchor";
448 const char * const base_url = "http://www.google.com/foo?query=what";
449 scoped_ptr<SpdyFrame> req(ConstructSpdyGet(base_url, false, 1, LOWEST));
450 MockWrite writes[] = {
451 CreateMockWrite(*req.get(), 1),
453 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
454 MockRead reads[] = {
455 CreateMockRead(*resp, 2),
456 MockRead(SYNCHRONOUS, 0, 3) // EOF
459 HostPortPair host_port_pair("www.google.com", 80);
460 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
461 EXPECT_EQ(OK, InitSession(reads, arraysize(reads), writes, arraysize(writes),
462 host_port_pair));
464 HttpRequestInfo request;
465 request.method = "GET";
466 request.url = GURL(full_url);
467 TestCompletionCallback callback;
468 HttpResponseInfo response;
469 HttpRequestHeaders headers;
470 BoundNetLog net_log;
471 scoped_ptr<SpdyHttpStream> http_stream(new SpdyHttpStream(session_, true));
472 ASSERT_EQ(
474 http_stream->InitializeStream(&request, net_log, CompletionCallback()));
476 EXPECT_EQ(ERR_IO_PENDING, http_stream->SendRequest(headers, &response,
477 callback.callback()));
479 const SpdyHeaderBlock& spdy_header =
480 http_stream->stream()->spdy_headers();
481 if (spdy_header.find(":path") != spdy_header.end())
482 EXPECT_EQ("/foo?query=what", spdy_header.find(":path")->second);
483 else
484 FAIL() << "No url is set in spdy_header!";
486 // This triggers the MockWrite and read 2
487 callback.WaitForResult();
489 // This triggers read 3. The empty read causes the session to shut down.
490 data()->CompleteRead();
492 // Because we abandoned the stream, we don't expect to find a session in the
493 // pool anymore.
494 EXPECT_FALSE(http_session_->spdy_session_pool()->HasSession(pair));
495 EXPECT_TRUE(data()->at_read_eof());
496 EXPECT_TRUE(data()->at_write_eof());
499 namespace {
501 void GetECServerBoundCertAndProof(
502 const std::string& origin,
503 ServerBoundCertService* server_bound_cert_service,
504 std::string* cert,
505 std::string* proof) {
506 TestCompletionCallback callback;
507 std::vector<uint8> requested_cert_types;
508 requested_cert_types.push_back(CLIENT_CERT_ECDSA_SIGN);
509 SSLClientCertType cert_type;
510 std::string key;
511 ServerBoundCertService::RequestHandle request_handle;
512 int rv = server_bound_cert_service->GetDomainBoundCert(
513 origin, requested_cert_types, &cert_type, &key, cert, callback.callback(),
514 &request_handle);
515 EXPECT_EQ(ERR_IO_PENDING, rv);
516 EXPECT_EQ(OK, callback.WaitForResult());
517 EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, cert_type);
519 SpdyCredential credential;
520 SpdyCredentialBuilder::Build(MockClientSocket::kTlsUnique, cert_type, key,
521 *cert, 2, &credential);
523 cert->assign(credential.certs[0]);
524 proof->assign(credential.proof);
527 } // namespace
529 // Constructs a standard SPDY SYN_STREAM frame for a GET request with
530 // a credential set.
531 SpdyFrame* ConstructCredentialRequestFrame(size_t slot, const GURL& url,
532 SpdyStreamId stream_id) {
533 const SpdyHeaderInfo syn_headers = {
534 SYN_STREAM,
535 stream_id,
537 ConvertRequestPriorityToSpdyPriority(LOWEST, 3),
538 slot,
539 CONTROL_FLAG_FIN,
540 false,
541 INVALID,
542 NULL,
544 DATA_FLAG_NONE
547 // TODO(rch): this is ugly. Clean up.
548 std::string str_path = url.PathForRequest();
549 std::string str_scheme = url.scheme();
550 std::string str_host = url.host();
551 if (url.has_port()) {
552 str_host += ":";
553 str_host += url.port();
555 scoped_array<char> req(new char[str_path.size() + 1]);
556 scoped_array<char> scheme(new char[str_scheme.size() + 1]);
557 scoped_array<char> host(new char[str_host.size() + 1]);
558 memcpy(req.get(), str_path.c_str(), str_path.size());
559 memcpy(scheme.get(), str_scheme.c_str(), str_scheme.size());
560 memcpy(host.get(), str_host.c_str(), str_host.size());
561 req.get()[str_path.size()] = '\0';
562 scheme.get()[str_scheme.size()] = '\0';
563 host.get()[str_host.size()] = '\0';
565 const char* const headers[] = {
566 ":method",
567 "GET",
568 ":path",
569 req.get(),
570 ":host",
571 host.get(),
572 ":scheme",
573 scheme.get(),
574 ":version",
575 "HTTP/1.1"
577 return ConstructSpdyPacket(
578 syn_headers, NULL, 0, headers, arraysize(headers)/2);
581 // TODO(rch): When openssl supports server bound certifictes, this
582 // guard can be removed
583 #if !defined(USE_OPENSSL)
584 // Test that if we request a resource for a new origin on a session that
585 // used domain bound certificates, that we send a CREDENTIAL frame for
586 // the new domain before we send the new request.
587 void SpdyHttpStreamSpdy3Test::TestSendCredentials(
588 ServerBoundCertService* server_bound_cert_service,
589 const std::string& cert,
590 const std::string& proof) {
591 const char* kUrl1 = "https://www.google.com/";
592 const char* kUrl2 = "https://www.gmail.com/";
594 SpdyCredential cred;
595 cred.slot = 2;
596 cred.proof = proof;
597 cred.certs.push_back(cert);
599 scoped_ptr<SpdyFrame> req(ConstructCredentialRequestFrame(
600 1, GURL(kUrl1), 1));
601 scoped_ptr<SpdyFrame> credential(ConstructSpdyCredential(cred));
602 scoped_ptr<SpdyFrame> req2(ConstructCredentialRequestFrame(
603 2, GURL(kUrl2), 3));
604 MockWrite writes[] = {
605 CreateMockWrite(*req.get(), 0),
606 CreateMockWrite(*credential.get(), 2),
607 CreateMockWrite(*req2.get(), 3),
610 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
611 scoped_ptr<SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
612 MockRead reads[] = {
613 CreateMockRead(*resp, 1),
614 CreateMockRead(*resp2, 4),
615 MockRead(SYNCHRONOUS, 0, 5) // EOF
618 HostPortPair host_port_pair(HostPortPair::FromURL(GURL(kUrl1)));
619 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
621 DeterministicMockClientSocketFactory* socket_factory =
622 session_deps_.deterministic_socket_factory.get();
623 DeterministicSocketData data(reads, arraysize(reads),
624 writes, arraysize(writes));
625 socket_factory->AddSocketDataProvider(&data);
626 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
627 ssl.channel_id_sent = true;
628 ssl.server_bound_cert_service = server_bound_cert_service;
629 ssl.protocol_negotiated = kProtoSPDY3;
630 socket_factory->AddSSLSocketDataProvider(&ssl);
631 http_session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic(
632 &session_deps_);
633 session_ = http_session_->spdy_session_pool()->Get(pair, BoundNetLog());
634 transport_params_ = new TransportSocketParams(host_port_pair,
635 MEDIUM, false, false,
636 OnHostResolutionCallback());
637 TestCompletionCallback callback;
638 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
639 SSLConfig ssl_config;
640 scoped_refptr<SOCKSSocketParams> socks_params;
641 scoped_refptr<HttpProxySocketParams> http_proxy_params;
642 scoped_refptr<SSLSocketParams> ssl_params(
643 new SSLSocketParams(transport_params_,
644 socks_params,
645 http_proxy_params,
646 ProxyServer::SCHEME_DIRECT,
647 host_port_pair,
648 ssl_config,
650 false,
651 false));
652 EXPECT_EQ(ERR_IO_PENDING,
653 connection->Init(host_port_pair.ToString(),
654 ssl_params,
655 MEDIUM,
656 callback.callback(),
657 http_session_->GetSSLSocketPool(
658 HttpNetworkSession::NORMAL_SOCKET_POOL),
659 BoundNetLog()));
660 callback.WaitForResult();
661 EXPECT_EQ(OK,
662 session_->InitializeWithSocket(connection.release(), true, OK));
664 HttpRequestInfo request;
665 request.method = "GET";
666 request.url = GURL(kUrl1);
667 HttpResponseInfo response;
668 HttpRequestHeaders headers;
669 BoundNetLog net_log;
670 scoped_ptr<SpdyHttpStream> http_stream(
671 new SpdyHttpStream(session_.get(), true));
672 ASSERT_EQ(
674 http_stream->InitializeStream(&request, net_log, CompletionCallback()));
676 // EXPECT_FALSE(session_->NeedsCredentials(request.url));
677 // GURL new_origin(kUrl2);
678 // EXPECT_TRUE(session_->NeedsCredentials(new_origin));
680 EXPECT_EQ(ERR_IO_PENDING, http_stream->SendRequest(headers, &response,
681 callback.callback()));
682 EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession(pair));
684 data.RunFor(2);
685 callback.WaitForResult();
687 // Start up second request for resource on a new origin.
688 scoped_ptr<SpdyHttpStream> http_stream2(
689 new SpdyHttpStream(session_.get(), true));
690 request.url = GURL(kUrl2);
691 ASSERT_EQ(
693 http_stream2->InitializeStream(&request, net_log, CompletionCallback()));
694 EXPECT_EQ(ERR_IO_PENDING, http_stream2->SendRequest(headers, &response,
695 callback.callback()));
696 data.RunFor(2);
697 callback.WaitForResult();
699 EXPECT_EQ(ERR_IO_PENDING, http_stream2->ReadResponseHeaders(
700 callback.callback()));
701 data.RunFor(1);
702 EXPECT_EQ(OK, callback.WaitForResult());
703 ASSERT_TRUE(response.headers.get() != NULL);
704 ASSERT_EQ(200, response.headers->response_code());
707 TEST_F(SpdyHttpStreamSpdy3Test, SendCredentialsEC) {
708 scoped_refptr<base::SequencedWorkerPool> sequenced_worker_pool =
709 new base::SequencedWorkerPool(1, "SpdyHttpStreamSpdy3Test");
710 scoped_ptr<ServerBoundCertService> server_bound_cert_service(
711 new ServerBoundCertService(new DefaultServerBoundCertStore(NULL),
712 sequenced_worker_pool));
713 std::string cert;
714 std::string proof;
715 GetECServerBoundCertAndProof("http://www.gmail.com/",
716 server_bound_cert_service.get(),
717 &cert, &proof);
719 TestSendCredentials(server_bound_cert_service.get(), cert, proof);
721 sequenced_worker_pool->Shutdown();
724 #endif // !defined(USE_OPENSSL)
726 // TODO(willchan): Write a longer test for SpdyStream that exercises all
727 // methods.
729 } // namespace net