Enables compositing support for webview.
[chromium-blink-merge.git] / net / spdy / spdy_http_stream_spdy2_unittest.cc
blob88e2fa93bc9fb72d2ea58df86f1351a9500c7351
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 "crypto/ec_private_key.h"
8 #include "crypto/ec_signature_creator.h"
9 #include "crypto/signature_creator.h"
10 #include "net/base/asn1_util.h"
11 #include "net/base/default_server_bound_cert_store.h"
12 #include "net/base/upload_data_stream.h"
13 #include "net/base/upload_element_reader.h"
14 #include "net/http/http_request_info.h"
15 #include "net/http/http_response_headers.h"
16 #include "net/http/http_response_info.h"
17 #include "net/spdy/spdy_session.h"
18 #include "net/spdy/spdy_test_util_spdy2.h"
19 #include "testing/gtest/include/gtest/gtest.h"
21 using namespace net::test_spdy2;
23 namespace net {
25 class SpdyHttpStreamSpdy2Test : public testing::Test {
26 public:
27 OrderedSocketData* data() { return data_.get(); }
28 protected:
29 SpdyHttpStreamSpdy2Test() {}
31 virtual void TearDown() {
32 crypto::ECSignatureCreator::SetFactoryForTesting(NULL);
33 UploadDataStream::ResetMergeChunks();
34 MessageLoop::current()->RunUntilIdle();
37 void set_merge_chunks(bool merge) {
38 UploadDataStream::set_merge_chunks(merge);
41 int InitSession(MockRead* reads, size_t reads_count,
42 MockWrite* writes, size_t writes_count,
43 HostPortPair& host_port_pair) {
44 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
45 data_.reset(new OrderedSocketData(reads, reads_count,
46 writes, writes_count));
47 session_deps_.socket_factory->AddSocketDataProvider(data_.get());
48 http_session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
49 session_ = http_session_->spdy_session_pool()->Get(pair, BoundNetLog());
50 transport_params_ = new TransportSocketParams(host_port_pair,
51 MEDIUM, false, false,
52 OnHostResolutionCallback());
53 TestCompletionCallback callback;
54 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
55 EXPECT_EQ(ERR_IO_PENDING,
56 connection->Init(host_port_pair.ToString(),
57 transport_params_,
58 MEDIUM,
59 callback.callback(),
60 http_session_->GetTransportSocketPool(
61 HttpNetworkSession::NORMAL_SOCKET_POOL),
62 BoundNetLog()));
63 EXPECT_EQ(OK, callback.WaitForResult());
64 return session_->InitializeWithSocket(connection.release(), false, OK);
67 SpdySessionDependencies session_deps_;
68 scoped_ptr<OrderedSocketData> data_;
69 scoped_refptr<HttpNetworkSession> http_session_;
70 scoped_refptr<SpdySession> session_;
71 scoped_refptr<TransportSocketParams> transport_params_;
74 TEST_F(SpdyHttpStreamSpdy2Test, SendRequest) {
75 scoped_ptr<SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
76 MockWrite writes[] = {
77 CreateMockWrite(*req.get(), 1),
79 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
80 MockRead reads[] = {
81 CreateMockRead(*resp, 2),
82 MockRead(SYNCHRONOUS, 0, 3) // EOF
85 HostPortPair host_port_pair("www.google.com", 80);
86 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
87 EXPECT_EQ(OK, InitSession(reads, arraysize(reads), writes, arraysize(writes),
88 host_port_pair));
90 HttpRequestInfo request;
91 request.method = "GET";
92 request.url = GURL("http://www.google.com/");
93 TestCompletionCallback callback;
94 HttpResponseInfo response;
95 HttpRequestHeaders headers;
96 BoundNetLog net_log;
97 scoped_ptr<SpdyHttpStream> http_stream(
98 new SpdyHttpStream(session_.get(), true));
99 ASSERT_EQ(
101 http_stream->InitializeStream(&request, net_log, CompletionCallback()));
103 EXPECT_EQ(ERR_IO_PENDING, http_stream->SendRequest(headers, &response,
104 callback.callback()));
105 EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession(pair));
107 // This triggers the MockWrite and read 2
108 callback.WaitForResult();
110 // This triggers read 3. The empty read causes the session to shut down.
111 data()->CompleteRead();
113 // Because we abandoned the stream, we don't expect to find a session in the
114 // pool anymore.
115 EXPECT_FALSE(http_session_->spdy_session_pool()->HasSession(pair));
116 EXPECT_TRUE(data()->at_read_eof());
117 EXPECT_TRUE(data()->at_write_eof());
120 TEST_F(SpdyHttpStreamSpdy2Test, SendChunkedPost) {
121 set_merge_chunks(false);
123 scoped_ptr<SpdyFrame> req(ConstructChunkedSpdyPost(NULL, 0));
124 scoped_ptr<SpdyFrame> chunk1(ConstructSpdyBodyFrame(1, false));
125 scoped_ptr<SpdyFrame> chunk2(ConstructSpdyBodyFrame(1, true));
126 MockWrite writes[] = {
127 CreateMockWrite(*req.get(), 0),
128 CreateMockWrite(*chunk1, 1), // POST upload frames
129 CreateMockWrite(*chunk2, 2),
131 scoped_ptr<SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
132 MockRead reads[] = {
133 CreateMockRead(*resp, 3),
134 CreateMockRead(*chunk1, 4),
135 CreateMockRead(*chunk2, 5),
136 MockRead(SYNCHRONOUS, 0, 6) // EOF
139 HostPortPair host_port_pair("www.google.com", 80);
140 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
141 EXPECT_EQ(OK, InitSession(reads, arraysize(reads), writes, arraysize(writes),
142 host_port_pair));
144 UploadDataStream upload_stream(UploadDataStream::CHUNKED, 0);
145 upload_stream.AppendChunk(kUploadData, kUploadDataSize, false);
146 upload_stream.AppendChunk(kUploadData, kUploadDataSize, true);
148 HttpRequestInfo request;
149 request.method = "POST";
150 request.url = GURL("http://www.google.com/");
151 request.upload_data_stream = &upload_stream;
153 ASSERT_EQ(OK, upload_stream.Init(CompletionCallback()));
155 TestCompletionCallback callback;
156 HttpResponseInfo response;
157 HttpRequestHeaders headers;
158 BoundNetLog net_log;
159 SpdyHttpStream http_stream(session_.get(), true);
160 ASSERT_EQ(
162 http_stream.InitializeStream(&request, net_log, CompletionCallback()));
164 EXPECT_EQ(ERR_IO_PENDING, http_stream.SendRequest(
165 headers, &response, callback.callback()));
166 EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession(pair));
168 // This triggers the MockWrite and read 2
169 callback.WaitForResult();
171 // This triggers read 3. The empty read causes the session to shut down.
172 data()->CompleteRead();
173 MessageLoop::current()->RunUntilIdle();
175 // Because we abandoned the stream, we don't expect to find a session in the
176 // pool anymore.
177 EXPECT_FALSE(http_session_->spdy_session_pool()->HasSession(pair));
178 EXPECT_TRUE(data()->at_read_eof());
179 EXPECT_TRUE(data()->at_write_eof());
182 // Test to ensure the SpdyStream state machine does not get confused when a
183 // chunk becomes available while a write is pending.
184 TEST_F(SpdyHttpStreamSpdy2Test, DelayedSendChunkedPost) {
185 set_merge_chunks(false);
187 const char kUploadData1[] = "12345678";
188 const int kUploadData1Size = arraysize(kUploadData1)-1;
189 scoped_ptr<SpdyFrame> req(ConstructChunkedSpdyPost(NULL, 0));
190 scoped_ptr<SpdyFrame> chunk1(ConstructSpdyBodyFrame(1, false));
191 scoped_ptr<SpdyFrame> chunk2(
192 ConstructSpdyBodyFrame(1, kUploadData1, kUploadData1Size, false));
193 scoped_ptr<SpdyFrame> chunk3(ConstructSpdyBodyFrame(1, true));
194 MockWrite writes[] = {
195 CreateMockWrite(*req.get(), 0),
196 CreateMockWrite(*chunk1, 1), // POST upload frames
197 CreateMockWrite(*chunk2, 2),
198 CreateMockWrite(*chunk3, 3),
200 scoped_ptr<SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
201 MockRead reads[] = {
202 CreateMockRead(*resp, 4),
203 CreateMockRead(*chunk1, 5),
204 CreateMockRead(*chunk2, 6),
205 CreateMockRead(*chunk3, 7),
206 MockRead(ASYNC, 0, 8) // EOF
209 HostPortPair host_port_pair("www.google.com", 80);
210 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
212 DeterministicSocketData data(reads, arraysize(reads),
213 writes, arraysize(writes));
215 DeterministicMockClientSocketFactory* socket_factory =
216 session_deps_.deterministic_socket_factory.get();
217 socket_factory->AddSocketDataProvider(&data);
219 http_session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic(
220 &session_deps_);
221 session_ = http_session_->spdy_session_pool()->Get(pair, BoundNetLog());
222 transport_params_ = new TransportSocketParams(host_port_pair,
223 MEDIUM, false, false,
224 OnHostResolutionCallback());
226 TestCompletionCallback callback;
227 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
229 EXPECT_EQ(ERR_IO_PENDING,
230 connection->Init(host_port_pair.ToString(),
231 transport_params_,
232 MEDIUM,
233 callback.callback(),
234 http_session_->GetTransportSocketPool(
235 HttpNetworkSession::NORMAL_SOCKET_POOL),
236 BoundNetLog()));
238 callback.WaitForResult();
239 EXPECT_EQ(OK,
240 session_->InitializeWithSocket(connection.release(), false, OK));
242 UploadDataStream upload_stream(UploadDataStream::CHUNKED, 0);
244 HttpRequestInfo request;
245 request.method = "POST";
246 request.url = GURL("http://www.google.com/");
247 request.upload_data_stream = &upload_stream;
249 ASSERT_EQ(OK, upload_stream.Init(CompletionCallback()));
250 upload_stream.AppendChunk(kUploadData, kUploadDataSize, false);
252 BoundNetLog net_log;
253 scoped_ptr<SpdyHttpStream> http_stream(
254 new SpdyHttpStream(session_.get(), true));
255 ASSERT_EQ(OK, http_stream->InitializeStream(&request,
256 net_log,
257 CompletionCallback()));
259 HttpRequestHeaders headers;
260 HttpResponseInfo response;
261 // This will attempt to Write() the initial request and headers, which will
262 // complete asynchronously.
263 EXPECT_EQ(ERR_IO_PENDING, http_stream->SendRequest(headers, &response,
264 callback.callback()));
265 EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession(pair));
267 // Complete the initial request write and the first chunk.
268 data.RunFor(2);
269 ASSERT_TRUE(callback.have_result());
270 EXPECT_GT(callback.WaitForResult(), 0);
272 // Now append the final two chunks which will enqueue two more writes.
273 upload_stream.AppendChunk(kUploadData1, kUploadData1Size, false);
274 upload_stream.AppendChunk(kUploadData, kUploadDataSize, true);
276 // Finish writing all the chunks.
277 data.RunFor(2);
279 // Read response headers.
280 data.RunFor(1);
281 ASSERT_EQ(OK, http_stream->ReadResponseHeaders(callback.callback()));
283 // Read and check |chunk1| response.
284 data.RunFor(1);
285 scoped_refptr<IOBuffer> buf1(new IOBuffer(kUploadDataSize));
286 ASSERT_EQ(kUploadDataSize,
287 http_stream->ReadResponseBody(buf1,
288 kUploadDataSize,
289 callback.callback()));
290 EXPECT_EQ(kUploadData, std::string(buf1->data(), kUploadDataSize));
292 // Read and check |chunk2| response.
293 data.RunFor(1);
294 scoped_refptr<IOBuffer> buf2(new IOBuffer(kUploadData1Size));
295 ASSERT_EQ(kUploadData1Size,
296 http_stream->ReadResponseBody(buf2,
297 kUploadData1Size,
298 callback.callback()));
299 EXPECT_EQ(kUploadData1, std::string(buf2->data(), kUploadData1Size));
301 // Read and check |chunk3| response.
302 data.RunFor(1);
303 scoped_refptr<IOBuffer> buf3(new IOBuffer(kUploadDataSize));
304 ASSERT_EQ(kUploadDataSize,
305 http_stream->ReadResponseBody(buf3,
306 kUploadDataSize,
307 callback.callback()));
308 EXPECT_EQ(kUploadData, std::string(buf3->data(), kUploadDataSize));
310 // Finish reading the |EOF|.
311 data.RunFor(1);
312 ASSERT_TRUE(response.headers.get());
313 ASSERT_EQ(200, response.headers->response_code());
314 EXPECT_TRUE(data.at_read_eof());
315 EXPECT_TRUE(data.at_write_eof());
318 // Test case for bug: http://code.google.com/p/chromium/issues/detail?id=50058
319 TEST_F(SpdyHttpStreamSpdy2Test, SpdyURLTest) {
320 const char * const full_url = "http://www.google.com/foo?query=what#anchor";
321 const char * const base_url = "http://www.google.com/foo?query=what";
322 scoped_ptr<SpdyFrame> req(ConstructSpdyGet(base_url, false, 1, LOWEST));
323 MockWrite writes[] = {
324 CreateMockWrite(*req.get(), 1),
326 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
327 MockRead reads[] = {
328 CreateMockRead(*resp, 2),
329 MockRead(SYNCHRONOUS, 0, 3) // EOF
332 HostPortPair host_port_pair("www.google.com", 80);
333 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
334 EXPECT_EQ(OK, InitSession(reads, arraysize(reads), writes, arraysize(writes),
335 host_port_pair));
337 HttpRequestInfo request;
338 request.method = "GET";
339 request.url = GURL(full_url);
340 TestCompletionCallback callback;
341 HttpResponseInfo response;
342 HttpRequestHeaders headers;
343 BoundNetLog net_log;
344 scoped_ptr<SpdyHttpStream> http_stream(new SpdyHttpStream(session_, true));
345 ASSERT_EQ(
347 http_stream->InitializeStream(&request, net_log, CompletionCallback()));
349 EXPECT_EQ(ERR_IO_PENDING, http_stream->SendRequest(headers, &response,
350 callback.callback()));
352 const SpdyHeaderBlock& spdy_header =
353 http_stream->stream()->spdy_headers();
354 if (spdy_header.find("url") != spdy_header.end())
355 EXPECT_EQ("/foo?query=what", spdy_header.find("url")->second);
356 else
357 FAIL() << "No url is set in spdy_header!";
359 // This triggers the MockWrite and read 2
360 callback.WaitForResult();
362 // This triggers read 3. The empty read causes the session to shut down.
363 data()->CompleteRead();
365 // Because we abandoned the stream, we don't expect to find a session in the
366 // pool anymore.
367 EXPECT_FALSE(http_session_->spdy_session_pool()->HasSession(pair));
368 EXPECT_TRUE(data()->at_read_eof());
369 EXPECT_TRUE(data()->at_write_eof());
372 // TODO(willchan): Write a longer test for SpdyStream that exercises all
373 // methods.
375 } // namespace net