Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(151)

Side by Side Diff: net/spdy/spdy_http_stream_unittest.cc

Issue 2832973003: Split net/spdy into core and chromium subdirectories. (Closed)
Patch Set: Fix some more build rules. Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/spdy/spdy_http_stream.cc ('k') | net/spdy/spdy_http_utils.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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_http_stream.h"
6
7 #include <stdint.h>
8
9 #include <memory>
10
11 #include "base/run_loop.h"
12 #include "base/stl_util.h"
13 #include "base/threading/thread_task_runner_handle.h"
14 #include "crypto/ec_private_key.h"
15 #include "crypto/ec_signature_creator.h"
16 #include "crypto/signature_creator.h"
17 #include "net/base/chunked_upload_data_stream.h"
18 #include "net/base/load_timing_info.h"
19 #include "net/base/load_timing_info_test_util.h"
20 #include "net/base/test_completion_callback.h"
21 #include "net/cert/asn1_util.h"
22 #include "net/http/http_request_info.h"
23 #include "net/http/http_response_headers.h"
24 #include "net/http/http_response_info.h"
25 #include "net/log/net_log_with_source.h"
26 #include "net/log/test_net_log.h"
27 #include "net/socket/socket_test_util.h"
28 #include "net/spdy/platform/api/spdy_string.h"
29 #include "net/spdy/spdy_http_utils.h"
30 #include "net/spdy/spdy_session.h"
31 #include "net/spdy/spdy_test_util_common.h"
32 #include "net/ssl/default_channel_id_store.h"
33 #include "net/test/cert_test_util.h"
34 #include "net/test/gtest_util.h"
35 #include "net/test/test_data_directory.h"
36 #include "testing/gmock/include/gmock/gmock.h"
37 #include "testing/gtest/include/gtest/gtest.h"
38
39 namespace net {
40
41 namespace test {
42
43 namespace {
44
45 // Tests the load timing of a stream that's connected and is not the first
46 // request sent on a connection.
47 void TestLoadTimingReused(const HttpStream& stream) {
48 LoadTimingInfo load_timing_info;
49 EXPECT_TRUE(stream.GetLoadTimingInfo(&load_timing_info));
50
51 EXPECT_TRUE(load_timing_info.socket_reused);
52 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
53
54 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
55 ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info);
56 }
57
58 // Tests the load timing of a stream that's connected and using a fresh
59 // connection.
60 void TestLoadTimingNotReused(const HttpStream& stream) {
61 LoadTimingInfo load_timing_info;
62 EXPECT_TRUE(stream.GetLoadTimingInfo(&load_timing_info));
63
64 EXPECT_FALSE(load_timing_info.socket_reused);
65 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
66
67 ExpectConnectTimingHasTimes(
68 load_timing_info.connect_timing,
69 CONNECT_TIMING_HAS_DNS_TIMES | CONNECT_TIMING_HAS_SSL_TIMES);
70 ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info);
71 }
72
73 class ReadErrorUploadDataStream : public UploadDataStream {
74 public:
75 enum class FailureMode { SYNC, ASYNC };
76
77 explicit ReadErrorUploadDataStream(FailureMode mode)
78 : UploadDataStream(true, 0), async_(mode), weak_factory_(this) {}
79
80 private:
81 void CompleteRead() { UploadDataStream::OnReadCompleted(ERR_FAILED); }
82
83 // UploadDataStream implementation:
84 int InitInternal(const NetLogWithSource& net_log) override { return OK; }
85
86 int ReadInternal(IOBuffer* buf, int buf_len) override {
87 if (async_ == FailureMode::ASYNC) {
88 base::ThreadTaskRunnerHandle::Get()->PostTask(
89 FROM_HERE, base::Bind(&ReadErrorUploadDataStream::CompleteRead,
90 weak_factory_.GetWeakPtr()));
91 return ERR_IO_PENDING;
92 }
93 return ERR_FAILED;
94 }
95
96 void ResetInternal() override {}
97
98 const FailureMode async_;
99
100 base::WeakPtrFactory<ReadErrorUploadDataStream> weak_factory_;
101
102 DISALLOW_COPY_AND_ASSIGN(ReadErrorUploadDataStream);
103 };
104
105 class CancelStreamCallback : public TestCompletionCallbackBase {
106 public:
107 explicit CancelStreamCallback(SpdyHttpStream* stream)
108 : stream_(stream),
109 callback_(base::Bind(&CancelStreamCallback::CancelStream,
110 base::Unretained(this))) {}
111
112 const CompletionCallback& callback() const { return callback_; }
113
114 private:
115 void CancelStream(int result) {
116 stream_->Cancel();
117 SetResult(result);
118 }
119
120 SpdyHttpStream* stream_;
121 CompletionCallback callback_;
122 };
123
124 } // namespace
125
126 class SpdyHttpStreamTest : public testing::Test {
127 public:
128 SpdyHttpStreamTest()
129 : url_(kDefaultUrl),
130 host_port_pair_(HostPortPair::FromURL(url_)),
131 key_(host_port_pair_, ProxyServer::Direct(), PRIVACY_MODE_DISABLED),
132 ssl_(SYNCHRONOUS, OK) {
133 session_deps_.net_log = &net_log_;
134 }
135
136 ~SpdyHttpStreamTest() override {}
137
138 protected:
139 void TearDown() override {
140 crypto::ECSignatureCreator::SetFactoryForTesting(nullptr);
141 base::RunLoop().RunUntilIdle();
142 EXPECT_TRUE(sequenced_data_->AllReadDataConsumed());
143 EXPECT_TRUE(sequenced_data_->AllWriteDataConsumed());
144 }
145
146 // Initializes the session using SequencedSocketData.
147 void InitSession(MockRead* reads,
148 size_t reads_count,
149 MockWrite* writes,
150 size_t writes_count) {
151 sequenced_data_.reset(
152 new SequencedSocketData(reads, reads_count, writes, writes_count));
153 session_deps_.socket_factory->AddSocketDataProvider(sequenced_data_.get());
154
155 ssl_.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
156 ASSERT_TRUE(ssl_.cert);
157 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_);
158
159 http_session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
160 session_ =
161 CreateSecureSpdySession(http_session_.get(), key_, NetLogWithSource());
162 }
163
164 void TestSendCredentials(ChannelIDService* channel_id_service,
165 const SpdyString& cert,
166 const SpdyString& proof);
167
168 SpdyTestUtil spdy_util_;
169 TestNetLog net_log_;
170 SpdySessionDependencies session_deps_;
171 const GURL url_;
172 const HostPortPair host_port_pair_;
173 const SpdySessionKey key_;
174 std::unique_ptr<SequencedSocketData> sequenced_data_;
175 std::unique_ptr<HttpNetworkSession> http_session_;
176 base::WeakPtr<SpdySession> session_;
177
178 private:
179 MockECSignatureCreatorFactory ec_signature_creator_factory_;
180 SSLSocketDataProvider ssl_;
181 };
182
183 TEST_F(SpdyHttpStreamTest, SendRequest) {
184 SpdySerializedFrame req(
185 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
186 MockWrite writes[] = {
187 CreateMockWrite(req, 0),
188 };
189 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
190 MockRead reads[] = {
191 CreateMockRead(resp, 1), MockRead(SYNCHRONOUS, 0, 2) // EOF
192 };
193
194 InitSession(reads, arraysize(reads), writes, arraysize(writes));
195
196 HttpRequestInfo request;
197 request.method = "GET";
198 request.url = url_;
199 TestCompletionCallback callback;
200 HttpResponseInfo response;
201 HttpRequestHeaders headers;
202 NetLogWithSource net_log;
203 std::unique_ptr<SpdyHttpStream> http_stream(
204 new SpdyHttpStream(session_, true, net_log.source()));
205 // Make sure getting load timing information the stream early does not crash.
206 LoadTimingInfo load_timing_info;
207 EXPECT_FALSE(http_stream->GetLoadTimingInfo(&load_timing_info));
208
209 ASSERT_THAT(http_stream->InitializeStream(&request, DEFAULT_PRIORITY, net_log,
210 CompletionCallback()),
211 IsOk());
212 EXPECT_FALSE(http_stream->GetLoadTimingInfo(&load_timing_info));
213
214 EXPECT_THAT(http_stream->SendRequest(headers, &response, callback.callback()),
215 IsError(ERR_IO_PENDING));
216 EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key_));
217 EXPECT_FALSE(http_stream->GetLoadTimingInfo(&load_timing_info));
218
219 callback.WaitForResult();
220
221 // Can get timing information once the stream connects.
222 TestLoadTimingNotReused(*http_stream);
223
224 // Because we abandoned the stream, we don't expect to find a session in the
225 // pool anymore.
226 EXPECT_FALSE(HasSpdySession(http_session_->spdy_session_pool(), key_));
227
228 TestLoadTimingNotReused(*http_stream);
229 http_stream->Close(true);
230 // Test that there's no crash when trying to get the load timing after the
231 // stream has been closed.
232 TestLoadTimingNotReused(*http_stream);
233
234 EXPECT_EQ(static_cast<int64_t>(req.size()), http_stream->GetTotalSentBytes());
235 EXPECT_EQ(static_cast<int64_t>(resp.size()),
236 http_stream->GetTotalReceivedBytes());
237 }
238
239 TEST_F(SpdyHttpStreamTest, LoadTimingTwoRequests) {
240 SpdySerializedFrame req1(
241 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
242 SpdySerializedFrame req2(
243 spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST, true));
244 MockWrite writes[] = {
245 CreateMockWrite(req1, 0), CreateMockWrite(req2, 1),
246 };
247 SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
248 SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, "", 0, true));
249 SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
250 SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, "", 0, true));
251 MockRead reads[] = {
252 CreateMockRead(resp1, 2), CreateMockRead(body1, 3),
253 CreateMockRead(resp2, 4), CreateMockRead(body2, 5),
254 MockRead(ASYNC, 0, 6) // EOF
255 };
256
257 InitSession(reads, arraysize(reads), writes, arraysize(writes));
258
259 HttpRequestInfo request1;
260 request1.method = "GET";
261 request1.url = url_;
262 TestCompletionCallback callback1;
263 HttpResponseInfo response1;
264 HttpRequestHeaders headers1;
265 NetLogWithSource net_log;
266 std::unique_ptr<SpdyHttpStream> http_stream1(
267 new SpdyHttpStream(session_, true, net_log.source()));
268
269 HttpRequestInfo request2;
270 request2.method = "GET";
271 request2.url = url_;
272 TestCompletionCallback callback2;
273 HttpResponseInfo response2;
274 HttpRequestHeaders headers2;
275 std::unique_ptr<SpdyHttpStream> http_stream2(
276 new SpdyHttpStream(session_, true, net_log.source()));
277
278 // First write.
279 ASSERT_THAT(http_stream1->InitializeStream(&request1, DEFAULT_PRIORITY,
280 net_log, CompletionCallback()),
281 IsOk());
282 EXPECT_THAT(
283 http_stream1->SendRequest(headers1, &response1, callback1.callback()),
284 IsError(ERR_IO_PENDING));
285 EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key_));
286
287 EXPECT_LE(0, callback1.WaitForResult());
288
289 TestLoadTimingNotReused(*http_stream1);
290 LoadTimingInfo load_timing_info1;
291 LoadTimingInfo load_timing_info2;
292 EXPECT_TRUE(http_stream1->GetLoadTimingInfo(&load_timing_info1));
293 EXPECT_FALSE(http_stream2->GetLoadTimingInfo(&load_timing_info2));
294
295 // Second write.
296 ASSERT_THAT(http_stream2->InitializeStream(&request2, DEFAULT_PRIORITY,
297 net_log, CompletionCallback()),
298 IsOk());
299 EXPECT_THAT(
300 http_stream2->SendRequest(headers2, &response2, callback2.callback()),
301 IsError(ERR_IO_PENDING));
302 EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key_));
303
304 EXPECT_LE(0, callback2.WaitForResult());
305
306 // Perform all async reads.
307 base::RunLoop().RunUntilIdle();
308
309 TestLoadTimingReused(*http_stream2);
310 EXPECT_TRUE(http_stream2->GetLoadTimingInfo(&load_timing_info2));
311 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
312
313 // Read stream 1 to completion, before making sure we can still read load
314 // timing from both streams.
315 scoped_refptr<IOBuffer> buf1(new IOBuffer(1));
316 ASSERT_EQ(
317 0, http_stream1->ReadResponseBody(buf1.get(), 1, callback1.callback()));
318
319 // Stream 1 has been read to completion.
320 TestLoadTimingNotReused(*http_stream1);
321
322 EXPECT_EQ(static_cast<int64_t>(req1.size()),
323 http_stream1->GetTotalSentBytes());
324 EXPECT_EQ(static_cast<int64_t>(resp1.size() + body1.size()),
325 http_stream1->GetTotalReceivedBytes());
326
327 // Stream 2 still has queued body data.
328 TestLoadTimingReused(*http_stream2);
329
330 EXPECT_EQ(static_cast<int64_t>(req2.size()),
331 http_stream2->GetTotalSentBytes());
332 EXPECT_EQ(static_cast<int64_t>(resp2.size() + body2.size()),
333 http_stream2->GetTotalReceivedBytes());
334 }
335
336 TEST_F(SpdyHttpStreamTest, SendChunkedPost) {
337 SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
338 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, kUploadData,
339 kUploadDataSize,
340 /*fin=*/true));
341 MockWrite writes[] = {
342 CreateMockWrite(req, 0), // request
343 CreateMockWrite(body, 1) // POST upload frame
344 };
345
346 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
347 MockRead reads[] = {
348 CreateMockRead(resp, 2), CreateMockRead(body, 3, SYNCHRONOUS),
349 MockRead(SYNCHRONOUS, 0, 4) // EOF
350 };
351
352 InitSession(reads, arraysize(reads), writes, arraysize(writes));
353
354 ChunkedUploadDataStream upload_stream(0);
355 const int kFirstChunkSize = kUploadDataSize/2;
356 upload_stream.AppendData(kUploadData, kFirstChunkSize, false);
357 upload_stream.AppendData(kUploadData + kFirstChunkSize,
358 kUploadDataSize - kFirstChunkSize, true);
359
360 HttpRequestInfo request;
361 request.method = "POST";
362 request.url = url_;
363 request.upload_data_stream = &upload_stream;
364
365 ASSERT_THAT(upload_stream.Init(TestCompletionCallback().callback(),
366 NetLogWithSource()),
367 IsOk());
368
369 TestCompletionCallback callback;
370 HttpResponseInfo response;
371 HttpRequestHeaders headers;
372 NetLogWithSource net_log;
373 SpdyHttpStream http_stream(session_, true, net_log.source());
374 ASSERT_THAT(http_stream.InitializeStream(&request, DEFAULT_PRIORITY, net_log,
375 CompletionCallback()),
376 IsOk());
377
378 EXPECT_THAT(http_stream.SendRequest(headers, &response, callback.callback()),
379 IsError(ERR_IO_PENDING));
380 EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key_));
381
382 EXPECT_THAT(callback.WaitForResult(), IsOk());
383
384 EXPECT_EQ(static_cast<int64_t>(req.size() + body.size()),
385 http_stream.GetTotalSentBytes());
386 EXPECT_EQ(static_cast<int64_t>(resp.size() + body.size()),
387 http_stream.GetTotalReceivedBytes());
388
389 // Because the server closed the connection, we there shouldn't be a session
390 // in the pool anymore.
391 EXPECT_FALSE(HasSpdySession(http_session_->spdy_session_pool(), key_));
392 }
393
394 // This unittest tests the request callback is properly called and handled.
395 TEST_F(SpdyHttpStreamTest, SendChunkedPostLastEmpty) {
396 SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
397 SpdySerializedFrame chunk(
398 spdy_util_.ConstructSpdyDataFrame(1, nullptr, 0, true));
399 MockWrite writes[] = {
400 CreateMockWrite(req, 0), // request
401 CreateMockWrite(chunk, 1),
402 };
403
404 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
405 MockRead reads[] = {
406 CreateMockRead(resp, 2), CreateMockRead(chunk, 3, SYNCHRONOUS),
407 MockRead(SYNCHRONOUS, 0, 4) // EOF
408 };
409
410 InitSession(reads, arraysize(reads), writes, arraysize(writes));
411
412 ChunkedUploadDataStream upload_stream(0);
413 upload_stream.AppendData(nullptr, 0, true);
414
415 HttpRequestInfo request;
416 request.method = "POST";
417 request.url = url_;
418 request.upload_data_stream = &upload_stream;
419
420 ASSERT_THAT(upload_stream.Init(TestCompletionCallback().callback(),
421 NetLogWithSource()),
422 IsOk());
423
424 TestCompletionCallback callback;
425 HttpResponseInfo response;
426 HttpRequestHeaders headers;
427 NetLogWithSource net_log;
428 SpdyHttpStream http_stream(session_, true, net_log.source());
429 ASSERT_THAT(http_stream.InitializeStream(&request, DEFAULT_PRIORITY, net_log,
430 CompletionCallback()),
431 IsOk());
432 EXPECT_THAT(http_stream.SendRequest(headers, &response, callback.callback()),
433 IsError(ERR_IO_PENDING));
434 EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key_));
435
436 EXPECT_THAT(callback.WaitForResult(), IsOk());
437
438 EXPECT_EQ(static_cast<int64_t>(req.size() + chunk.size()),
439 http_stream.GetTotalSentBytes());
440 EXPECT_EQ(static_cast<int64_t>(resp.size() + chunk.size()),
441 http_stream.GetTotalReceivedBytes());
442
443 // Because the server closed the connection, there shouldn't be a session
444 // in the pool anymore.
445 EXPECT_FALSE(HasSpdySession(http_session_->spdy_session_pool(), key_));
446 }
447
448 TEST_F(SpdyHttpStreamTest, ConnectionClosedDuringChunkedPost) {
449 SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
450 SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, kUploadData,
451 kUploadDataSize,
452 /*fin=*/false));
453 MockWrite writes[] = {
454 CreateMockWrite(req, 0), // Request
455 CreateMockWrite(body, 1) // First POST upload frame
456 };
457
458 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
459 MockRead reads[] = {
460 MockRead(ASYNC, ERR_CONNECTION_CLOSED, 2) // Server hangs up early.
461 };
462
463 InitSession(reads, arraysize(reads), writes, arraysize(writes));
464
465 ChunkedUploadDataStream upload_stream(0);
466 // Append first chunk.
467 upload_stream.AppendData(kUploadData, kUploadDataSize, false);
468
469 HttpRequestInfo request;
470 request.method = "POST";
471 request.url = url_;
472 request.upload_data_stream = &upload_stream;
473
474 ASSERT_THAT(upload_stream.Init(TestCompletionCallback().callback(),
475 NetLogWithSource()),
476 IsOk());
477
478 TestCompletionCallback callback;
479 HttpResponseInfo response;
480 HttpRequestHeaders headers;
481 NetLogWithSource net_log;
482 SpdyHttpStream http_stream(session_, true, net_log.source());
483 ASSERT_THAT(http_stream.InitializeStream(&request, DEFAULT_PRIORITY, net_log,
484 CompletionCallback()),
485 IsOk());
486
487 EXPECT_THAT(http_stream.SendRequest(headers, &response, callback.callback()),
488 IsError(ERR_IO_PENDING));
489 EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key_));
490
491 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
492
493 EXPECT_EQ(static_cast<int64_t>(req.size() + body.size()),
494 http_stream.GetTotalSentBytes());
495 EXPECT_EQ(0, http_stream.GetTotalReceivedBytes());
496
497 // Because the server closed the connection, we there shouldn't be a session
498 // in the pool anymore.
499 EXPECT_FALSE(HasSpdySession(http_session_->spdy_session_pool(), key_));
500
501 // Appending a second chunk now should not result in a crash.
502 upload_stream.AppendData(kUploadData, kUploadDataSize, true);
503 // Appending data is currently done synchronously, but seems best to be
504 // paranoid.
505 base::RunLoop().RunUntilIdle();
506
507 // The total sent and received bytes should be unchanged.
508 EXPECT_EQ(static_cast<int64_t>(req.size() + body.size()),
509 http_stream.GetTotalSentBytes());
510 EXPECT_EQ(0, http_stream.GetTotalReceivedBytes());
511 }
512
513 // Test to ensure the SpdyStream state machine does not get confused when a
514 // chunk becomes available while a write is pending.
515 TEST_F(SpdyHttpStreamTest, DelayedSendChunkedPost) {
516 const char kUploadData1[] = "12345678";
517 const int kUploadData1Size = arraysize(kUploadData1)-1;
518 SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
519 SpdySerializedFrame chunk1(spdy_util_.ConstructSpdyDataFrame(1, false));
520 SpdySerializedFrame chunk2(spdy_util_.ConstructSpdyDataFrame(
521 1, kUploadData1, kUploadData1Size, false));
522 SpdySerializedFrame chunk3(spdy_util_.ConstructSpdyDataFrame(1, true));
523 MockWrite writes[] = {
524 CreateMockWrite(req, 0),
525 CreateMockWrite(chunk1, 1), // POST upload frames
526 CreateMockWrite(chunk2, 2), CreateMockWrite(chunk3, 3),
527 };
528 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
529 MockRead reads[] = {
530 CreateMockRead(resp, 4), CreateMockRead(chunk1, 5),
531 CreateMockRead(chunk2, 6), CreateMockRead(chunk3, 7),
532 MockRead(ASYNC, 0, 8) // EOF
533 };
534
535 InitSession(reads, arraysize(reads), writes, arraysize(writes));
536
537 ChunkedUploadDataStream upload_stream(0);
538
539 HttpRequestInfo request;
540 request.method = "POST";
541 request.url = url_;
542 request.upload_data_stream = &upload_stream;
543
544 ASSERT_THAT(upload_stream.Init(TestCompletionCallback().callback(),
545 NetLogWithSource()),
546 IsOk());
547 upload_stream.AppendData(kUploadData, kUploadDataSize, false);
548
549 NetLogWithSource net_log;
550 std::unique_ptr<SpdyHttpStream> http_stream(
551 new SpdyHttpStream(session_, true, net_log.source()));
552 ASSERT_THAT(http_stream->InitializeStream(&request, DEFAULT_PRIORITY, net_log,
553 CompletionCallback()),
554 IsOk());
555
556 TestCompletionCallback callback;
557 HttpRequestHeaders headers;
558 HttpResponseInfo response;
559 // This will attempt to Write() the initial request and headers, which will
560 // complete asynchronously.
561 EXPECT_THAT(http_stream->SendRequest(headers, &response, callback.callback()),
562 IsError(ERR_IO_PENDING));
563 EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key_));
564
565 // Complete the initial request write and the first chunk.
566 base::RunLoop().RunUntilIdle();
567 ASSERT_FALSE(callback.have_result());
568
569 // Now append the final two chunks which will enqueue two more writes.
570 upload_stream.AppendData(kUploadData1, kUploadData1Size, false);
571 upload_stream.AppendData(kUploadData, kUploadDataSize, true);
572
573 // Finish writing all the chunks and do all reads.
574 base::RunLoop().RunUntilIdle();
575 ASSERT_TRUE(callback.have_result());
576 EXPECT_THAT(callback.WaitForResult(), IsOk());
577
578 EXPECT_EQ(static_cast<int64_t>(req.size() + chunk1.size() + chunk2.size() +
579 chunk3.size()),
580 http_stream->GetTotalSentBytes());
581 EXPECT_EQ(static_cast<int64_t>(resp.size() + chunk1.size() + chunk2.size() +
582 chunk3.size()),
583 http_stream->GetTotalReceivedBytes());
584
585 // Check response headers.
586 ASSERT_THAT(http_stream->ReadResponseHeaders(callback.callback()), IsOk());
587
588 // Check |chunk1| response.
589 scoped_refptr<IOBuffer> buf1(new IOBuffer(kUploadDataSize));
590 ASSERT_EQ(kUploadDataSize,
591 http_stream->ReadResponseBody(
592 buf1.get(), kUploadDataSize, callback.callback()));
593 EXPECT_EQ(kUploadData, SpdyString(buf1->data(), kUploadDataSize));
594
595 // Check |chunk2| response.
596 scoped_refptr<IOBuffer> buf2(new IOBuffer(kUploadData1Size));
597 ASSERT_EQ(kUploadData1Size,
598 http_stream->ReadResponseBody(
599 buf2.get(), kUploadData1Size, callback.callback()));
600 EXPECT_EQ(kUploadData1, SpdyString(buf2->data(), kUploadData1Size));
601
602 // Check |chunk3| response.
603 scoped_refptr<IOBuffer> buf3(new IOBuffer(kUploadDataSize));
604 ASSERT_EQ(kUploadDataSize,
605 http_stream->ReadResponseBody(
606 buf3.get(), kUploadDataSize, callback.callback()));
607 EXPECT_EQ(kUploadData, SpdyString(buf3->data(), kUploadDataSize));
608
609 ASSERT_TRUE(response.headers.get());
610 ASSERT_EQ(200, response.headers->response_code());
611 }
612
613 // Test that the SpdyStream state machine can handle sending a final empty data
614 // frame when uploading a chunked data stream.
615 TEST_F(SpdyHttpStreamTest, DelayedSendChunkedPostWithEmptyFinalDataFrame) {
616 SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
617 SpdySerializedFrame chunk1(spdy_util_.ConstructSpdyDataFrame(1, false));
618 SpdySerializedFrame chunk2(spdy_util_.ConstructSpdyDataFrame(1, "", 0, true));
619 MockWrite writes[] = {
620 CreateMockWrite(req, 0),
621 CreateMockWrite(chunk1, 1), // POST upload frames
622 CreateMockWrite(chunk2, 2),
623 };
624 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
625 MockRead reads[] = {
626 CreateMockRead(resp, 3), CreateMockRead(chunk1, 4),
627 CreateMockRead(chunk2, 5), MockRead(ASYNC, 0, 6) // EOF
628 };
629
630 InitSession(reads, arraysize(reads), writes, arraysize(writes));
631
632 ChunkedUploadDataStream upload_stream(0);
633
634 HttpRequestInfo request;
635 request.method = "POST";
636 request.url = url_;
637 request.upload_data_stream = &upload_stream;
638
639 ASSERT_THAT(upload_stream.Init(TestCompletionCallback().callback(),
640 NetLogWithSource()),
641 IsOk());
642 upload_stream.AppendData(kUploadData, kUploadDataSize, false);
643
644 NetLogWithSource net_log;
645 std::unique_ptr<SpdyHttpStream> http_stream(
646 new SpdyHttpStream(session_, true, net_log.source()));
647 ASSERT_THAT(http_stream->InitializeStream(&request, DEFAULT_PRIORITY, net_log,
648 CompletionCallback()),
649 IsOk());
650
651 TestCompletionCallback callback;
652 HttpRequestHeaders headers;
653 HttpResponseInfo response;
654 // This will attempt to Write() the initial request and headers, which will
655 // complete asynchronously.
656 EXPECT_THAT(http_stream->SendRequest(headers, &response, callback.callback()),
657 IsError(ERR_IO_PENDING));
658 EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key_));
659
660 // Complete the initial request write and the first chunk.
661 base::RunLoop().RunUntilIdle();
662 ASSERT_FALSE(callback.have_result());
663
664 EXPECT_EQ(static_cast<int64_t>(req.size() + chunk1.size()),
665 http_stream->GetTotalSentBytes());
666 EXPECT_EQ(0, http_stream->GetTotalReceivedBytes());
667
668 // Now end the stream with an empty data frame and the FIN set.
669 upload_stream.AppendData(nullptr, 0, true);
670
671 // Finish writing the final frame, and perform all reads.
672 base::RunLoop().RunUntilIdle();
673 ASSERT_TRUE(callback.have_result());
674 EXPECT_THAT(callback.WaitForResult(), IsOk());
675
676 // Check response headers.
677 ASSERT_THAT(http_stream->ReadResponseHeaders(callback.callback()), IsOk());
678
679 EXPECT_EQ(static_cast<int64_t>(req.size() + chunk1.size() + chunk2.size()),
680 http_stream->GetTotalSentBytes());
681 EXPECT_EQ(static_cast<int64_t>(resp.size() + chunk1.size() + chunk2.size()),
682 http_stream->GetTotalReceivedBytes());
683
684 // Check |chunk1| response.
685 scoped_refptr<IOBuffer> buf1(new IOBuffer(kUploadDataSize));
686 ASSERT_EQ(kUploadDataSize,
687 http_stream->ReadResponseBody(
688 buf1.get(), kUploadDataSize, callback.callback()));
689 EXPECT_EQ(kUploadData, SpdyString(buf1->data(), kUploadDataSize));
690
691 // Check |chunk2| response.
692 ASSERT_EQ(0,
693 http_stream->ReadResponseBody(
694 buf1.get(), kUploadDataSize, callback.callback()));
695
696 ASSERT_TRUE(response.headers.get());
697 ASSERT_EQ(200, response.headers->response_code());
698 }
699
700 // Test that the SpdyStream state machine handles a chunked upload with no
701 // payload. Unclear if this is a case worth supporting.
702 TEST_F(SpdyHttpStreamTest, ChunkedPostWithEmptyPayload) {
703 SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
704 SpdySerializedFrame chunk(spdy_util_.ConstructSpdyDataFrame(1, "", 0, true));
705 MockWrite writes[] = {
706 CreateMockWrite(req, 0), CreateMockWrite(chunk, 1),
707 };
708 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
709 MockRead reads[] = {
710 CreateMockRead(resp, 2), CreateMockRead(chunk, 3),
711 MockRead(ASYNC, 0, 4) // EOF
712 };
713
714 InitSession(reads, arraysize(reads), writes, arraysize(writes));
715
716 ChunkedUploadDataStream upload_stream(0);
717
718 HttpRequestInfo request;
719 request.method = "POST";
720 request.url = url_;
721 request.upload_data_stream = &upload_stream;
722
723 ASSERT_THAT(upload_stream.Init(TestCompletionCallback().callback(),
724 NetLogWithSource()),
725 IsOk());
726 upload_stream.AppendData("", 0, true);
727
728 NetLogWithSource net_log;
729 std::unique_ptr<SpdyHttpStream> http_stream(
730 new SpdyHttpStream(session_, true, net_log.source()));
731 ASSERT_THAT(http_stream->InitializeStream(&request, DEFAULT_PRIORITY, net_log,
732 CompletionCallback()),
733 IsOk());
734
735 TestCompletionCallback callback;
736 HttpRequestHeaders headers;
737 HttpResponseInfo response;
738 // This will attempt to Write() the initial request and headers, which will
739 // complete asynchronously.
740 EXPECT_THAT(http_stream->SendRequest(headers, &response, callback.callback()),
741 IsError(ERR_IO_PENDING));
742 EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key_));
743
744 // Complete writing request, followed by a FIN.
745 base::RunLoop().RunUntilIdle();
746 ASSERT_TRUE(callback.have_result());
747 EXPECT_THAT(callback.WaitForResult(), IsOk());
748
749 EXPECT_EQ(static_cast<int64_t>(req.size() + chunk.size()),
750 http_stream->GetTotalSentBytes());
751 EXPECT_EQ(static_cast<int64_t>(resp.size() + chunk.size()),
752 http_stream->GetTotalReceivedBytes());
753
754 // Check response headers.
755 ASSERT_THAT(http_stream->ReadResponseHeaders(callback.callback()), IsOk());
756
757 // Check |chunk| response.
758 scoped_refptr<IOBuffer> buf(new IOBuffer(1));
759 ASSERT_EQ(0,
760 http_stream->ReadResponseBody(
761 buf.get(), 1, callback.callback()));
762
763 ASSERT_TRUE(response.headers.get());
764 ASSERT_EQ(200, response.headers->response_code());
765 }
766
767 // Test case for https://crbug.com/50058.
768 TEST_F(SpdyHttpStreamTest, SpdyURLTest) {
769 const char* const full_url = "https://www.example.org/foo?query=what#anchor";
770 const char* const base_url = "https://www.example.org/foo?query=what";
771 SpdySerializedFrame req(spdy_util_.ConstructSpdyGet(base_url, 1, LOWEST));
772 MockWrite writes[] = {
773 CreateMockWrite(req, 0),
774 };
775 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
776 MockRead reads[] = {
777 CreateMockRead(resp, 1), MockRead(SYNCHRONOUS, 0, 2) // EOF
778 };
779
780 InitSession(reads, arraysize(reads), writes, arraysize(writes));
781
782 HttpRequestInfo request;
783 request.method = "GET";
784 request.url = GURL(full_url);
785 TestCompletionCallback callback;
786 HttpResponseInfo response;
787 HttpRequestHeaders headers;
788 NetLogWithSource net_log;
789 std::unique_ptr<SpdyHttpStream> http_stream(
790 new SpdyHttpStream(session_, true, net_log.source()));
791 ASSERT_THAT(http_stream->InitializeStream(&request, DEFAULT_PRIORITY, net_log,
792 CompletionCallback()),
793 IsOk());
794
795 EXPECT_THAT(http_stream->SendRequest(headers, &response, callback.callback()),
796 IsError(ERR_IO_PENDING));
797
798 EXPECT_EQ(base_url, http_stream->stream()->GetUrlFromHeaders().spec());
799
800 callback.WaitForResult();
801
802 EXPECT_EQ(static_cast<int64_t>(req.size()), http_stream->GetTotalSentBytes());
803 EXPECT_EQ(static_cast<int64_t>(resp.size()),
804 http_stream->GetTotalReceivedBytes());
805
806 // Because we abandoned the stream, we don't expect to find a session in the
807 // pool anymore.
808 EXPECT_FALSE(HasSpdySession(http_session_->spdy_session_pool(), key_));
809 }
810
811 // Test the receipt of a WINDOW_UPDATE frame while waiting for a chunk to be
812 // made available is handled correctly.
813 TEST_F(SpdyHttpStreamTest, DelayedSendChunkedPostWithWindowUpdate) {
814 SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
815 SpdySerializedFrame chunk1(spdy_util_.ConstructSpdyDataFrame(1, true));
816 MockWrite writes[] = {
817 CreateMockWrite(req, 0), CreateMockWrite(chunk1, 1),
818 };
819 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
820 SpdySerializedFrame window_update(
821 spdy_util_.ConstructSpdyWindowUpdate(1, kUploadDataSize));
822 MockRead reads[] = {
823 CreateMockRead(window_update, 2), MockRead(ASYNC, ERR_IO_PENDING, 3),
824 CreateMockRead(resp, 4), CreateMockRead(chunk1, 5),
825 MockRead(ASYNC, 0, 6) // EOF
826 };
827
828 InitSession(reads, arraysize(reads), writes, arraysize(writes));
829
830 ChunkedUploadDataStream upload_stream(0);
831
832 HttpRequestInfo request;
833 request.method = "POST";
834 request.url = url_;
835 request.upload_data_stream = &upload_stream;
836
837 ASSERT_THAT(upload_stream.Init(TestCompletionCallback().callback(),
838 NetLogWithSource()),
839 IsOk());
840
841 NetLogWithSource net_log;
842 std::unique_ptr<SpdyHttpStream> http_stream(
843 new SpdyHttpStream(session_, true, net_log.source()));
844 ASSERT_THAT(http_stream->InitializeStream(&request, DEFAULT_PRIORITY, net_log,
845 CompletionCallback()),
846 IsOk());
847
848 HttpRequestHeaders headers;
849 HttpResponseInfo response;
850 // This will attempt to Write() the initial request and headers, which will
851 // complete asynchronously.
852 TestCompletionCallback callback;
853 EXPECT_THAT(http_stream->SendRequest(headers, &response, callback.callback()),
854 IsError(ERR_IO_PENDING));
855 EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key_));
856
857 // Complete the initial request write and first chunk.
858 base::RunLoop().RunUntilIdle();
859 ASSERT_FALSE(callback.have_result());
860
861 EXPECT_EQ(static_cast<int64_t>(req.size()), http_stream->GetTotalSentBytes());
862 EXPECT_EQ(0, http_stream->GetTotalReceivedBytes());
863
864 upload_stream.AppendData(kUploadData, kUploadDataSize, true);
865
866 // Verify that the window size has decreased.
867 ASSERT_TRUE(http_stream->stream() != nullptr);
868 EXPECT_NE(static_cast<int>(kDefaultInitialWindowSize),
869 http_stream->stream()->send_window_size());
870
871 // Read window update.
872 base::RunLoop().RunUntilIdle();
873
874 ASSERT_TRUE(callback.have_result());
875 EXPECT_THAT(callback.WaitForResult(), IsOk());
876
877 EXPECT_EQ(static_cast<int64_t>(req.size() + chunk1.size()),
878 http_stream->GetTotalSentBytes());
879 // The window update is not counted in the total received bytes.
880 EXPECT_EQ(0, http_stream->GetTotalReceivedBytes());
881
882 // Verify the window update.
883 ASSERT_TRUE(http_stream->stream() != nullptr);
884 EXPECT_EQ(static_cast<int>(kDefaultInitialWindowSize),
885 http_stream->stream()->send_window_size());
886
887 // Read rest of data.
888 sequenced_data_->Resume();
889 base::RunLoop().RunUntilIdle();
890
891 EXPECT_EQ(static_cast<int64_t>(req.size() + chunk1.size()),
892 http_stream->GetTotalSentBytes());
893 EXPECT_EQ(static_cast<int64_t>(resp.size() + chunk1.size()),
894 http_stream->GetTotalReceivedBytes());
895
896 // Check response headers.
897 ASSERT_THAT(http_stream->ReadResponseHeaders(callback.callback()), IsOk());
898
899 // Check |chunk1| response.
900 scoped_refptr<IOBuffer> buf1(new IOBuffer(kUploadDataSize));
901 ASSERT_EQ(kUploadDataSize,
902 http_stream->ReadResponseBody(
903 buf1.get(), kUploadDataSize, callback.callback()));
904 EXPECT_EQ(kUploadData, SpdyString(buf1->data(), kUploadDataSize));
905
906 ASSERT_TRUE(response.headers.get());
907 ASSERT_EQ(200, response.headers->response_code());
908 }
909
910 TEST_F(SpdyHttpStreamTest, DataReadErrorSynchronous) {
911 SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
912
913 // Server receives ERROR_CODE_INTERNAL_ERROR on client's internal failure.
914 // The failure is a reading error in this case caused by
915 // UploadDataStream::Read().
916 SpdySerializedFrame rst_frame(
917 spdy_util_.ConstructSpdyRstStream(1, ERROR_CODE_INTERNAL_ERROR));
918
919 MockWrite writes[] = {
920 CreateMockWrite(req, 0, SYNCHRONOUS), // Request
921 CreateMockWrite(rst_frame, 1, SYNCHRONOUS) // Reset frame
922 };
923
924 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
925
926 MockRead reads[] = {
927 CreateMockRead(resp, 2), MockRead(SYNCHRONOUS, 0, 3),
928 };
929
930 InitSession(reads, arraysize(reads), writes, arraysize(writes));
931
932 ReadErrorUploadDataStream upload_data_stream(
933 ReadErrorUploadDataStream::FailureMode::SYNC);
934 ASSERT_THAT(upload_data_stream.Init(TestCompletionCallback().callback(),
935 NetLogWithSource()),
936 IsOk());
937
938 HttpRequestInfo request;
939 request.method = "POST";
940 request.url = url_;
941 request.upload_data_stream = &upload_data_stream;
942
943 TestCompletionCallback callback;
944 HttpResponseInfo response;
945 HttpRequestHeaders headers;
946 NetLogWithSource net_log;
947 SpdyHttpStream http_stream(session_, true, net_log.source());
948 ASSERT_THAT(http_stream.InitializeStream(&request, DEFAULT_PRIORITY, net_log,
949 CompletionCallback()),
950 IsOk());
951
952 int result = http_stream.SendRequest(headers, &response, callback.callback());
953 EXPECT_THAT(callback.GetResult(result), IsError(ERR_FAILED));
954
955 // Run posted SpdyHttpStream::ResetStreamInternal() task.
956 base::RunLoop().RunUntilIdle();
957
958 // Because the server has not closed the connection yet, there shouldn't be
959 // a stream but a session in the pool
960 EXPECT_FALSE(HasSpdySession(http_session_->spdy_session_pool(), key_));
961 }
962
963 TEST_F(SpdyHttpStreamTest, DataReadErrorAsynchronous) {
964 SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
965
966 // Server receives ERROR_CODE_INTERNAL_ERROR on client's internal failure.
967 // The failure is a reading error in this case caused by
968 // UploadDataStream::Read().
969 SpdySerializedFrame rst_frame(
970 spdy_util_.ConstructSpdyRstStream(1, ERROR_CODE_INTERNAL_ERROR));
971
972 MockWrite writes[] = {
973 CreateMockWrite(req, 0), // Request
974 CreateMockWrite(rst_frame, 1) // Reset frame
975 };
976
977 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
978
979 MockRead reads[] = {
980 MockRead(ASYNC, 0, 2),
981 };
982
983 InitSession(reads, arraysize(reads), writes, arraysize(writes));
984
985 ReadErrorUploadDataStream upload_data_stream(
986 ReadErrorUploadDataStream::FailureMode::ASYNC);
987 ASSERT_THAT(upload_data_stream.Init(TestCompletionCallback().callback(),
988 NetLogWithSource()),
989 IsOk());
990
991 HttpRequestInfo request;
992 request.method = "POST";
993 request.url = url_;
994 request.upload_data_stream = &upload_data_stream;
995
996 TestCompletionCallback callback;
997 HttpResponseInfo response;
998 HttpRequestHeaders headers;
999 NetLogWithSource net_log;
1000 SpdyHttpStream http_stream(session_, true, net_log.source());
1001 ASSERT_THAT(http_stream.InitializeStream(&request, DEFAULT_PRIORITY, net_log,
1002 CompletionCallback()),
1003 IsOk());
1004
1005 int result = http_stream.SendRequest(headers, &response, callback.callback());
1006 EXPECT_THAT(result, IsError(ERR_IO_PENDING));
1007 EXPECT_THAT(callback.GetResult(result), IsError(ERR_FAILED));
1008
1009 // Run posted SpdyHttpStream::ResetStreamInternal() task.
1010 base::RunLoop().RunUntilIdle();
1011
1012 // Because the server has closed the connection, there shouldn't be a session
1013 // in the pool anymore.
1014 EXPECT_FALSE(HasSpdySession(http_session_->spdy_session_pool(), key_));
1015 }
1016
1017 // Regression test for https://crbug.com/622447.
1018 TEST_F(SpdyHttpStreamTest, RequestCallbackCancelsStream) {
1019 SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
1020 SpdySerializedFrame chunk(
1021 spdy_util_.ConstructSpdyDataFrame(1, nullptr, 0, true));
1022 SpdySerializedFrame rst(
1023 spdy_util_.ConstructSpdyRstStream(1, ERROR_CODE_CANCEL));
1024 MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(chunk, 1),
1025 CreateMockWrite(rst, 2)};
1026 MockRead reads[] = {MockRead(ASYNC, 0, 3)};
1027 InitSession(reads, arraysize(reads), writes, arraysize(writes));
1028
1029 HttpRequestInfo request;
1030 request.method = "POST";
1031 request.url = url_;
1032 ChunkedUploadDataStream upload_stream(0);
1033 request.upload_data_stream = &upload_stream;
1034
1035 TestCompletionCallback upload_callback;
1036 ASSERT_THAT(
1037 upload_stream.Init(upload_callback.callback(), NetLogWithSource()),
1038 IsOk());
1039 upload_stream.AppendData("", 0, true);
1040
1041 NetLogWithSource net_log;
1042 SpdyHttpStream http_stream(session_, true, net_log.source());
1043 ASSERT_THAT(http_stream.InitializeStream(&request, DEFAULT_PRIORITY, net_log,
1044 CompletionCallback()),
1045 IsOk());
1046
1047 CancelStreamCallback callback(&http_stream);
1048 HttpRequestHeaders headers;
1049 HttpResponseInfo response;
1050 // This will attempt to Write() the initial request and headers, which will
1051 // complete asynchronously.
1052 EXPECT_THAT(http_stream.SendRequest(headers, &response, callback.callback()),
1053 IsError(ERR_IO_PENDING));
1054 EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key_));
1055
1056 // The callback cancels |http_stream|.
1057 EXPECT_THAT(callback.WaitForResult(), IsOk());
1058
1059 // Finish async network reads/writes.
1060 base::RunLoop().RunUntilIdle();
1061
1062 EXPECT_FALSE(HasSpdySession(http_session_->spdy_session_pool(), key_));
1063 }
1064
1065 // TODO(willchan): Write a longer test for SpdyStream that exercises all
1066 // methods.
1067
1068 } // namespace test
1069
1070 } // namespace net
OLDNEW
« no previous file with comments | « net/spdy/spdy_http_stream.cc ('k') | net/spdy/spdy_http_utils.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698