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

Side by Side Diff: net/http/bidirectional_stream_unittest.cc

Issue 1326503003: Added a net::BidirectionalStream to expose a bidirectional streaming interface (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address Misha's comments Created 5 years 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
OLDNEW
(Empty)
1 // Copyright 2015 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/http/bidirectional_stream.h"
6
7 #include "base/macros.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/run_loop.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/string_piece.h"
12 #include "base/time/time.h"
13 #include "base/timer/mock_timer.h"
14 #include "net/base/net_errors.h"
15 #include "net/base/test_data_directory.h"
16 #include "net/http/bidirectional_stream_request_info.h"
17 #include "net/http/http_network_session.h"
18 #include "net/http/http_response_headers.h"
19 #include "net/log/net_log.h"
20 #include "net/socket/socket_test_util.h"
21 #include "net/spdy/spdy_session.h"
22 #include "net/spdy/spdy_test_util_common.h"
23 #include "net/test/cert_test_util.h"
24 #include "net/url_request/url_request_test_util.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26
27 namespace net {
28
29 namespace {
30
31 const char kBodyData[] = "Body data";
32 const size_t kBodyDataSize = arraysize(kBodyData);
33 // Size of the buffer to be allocated for each read.
34 const size_t kReadBufferSize = 4096;
35
36 // Delegate that reads data but does not send any data.
37 class TestDelegateBase : public BidirectionalStream::Delegate {
38 public:
39 TestDelegateBase(IOBuffer* read_buf, int read_buf_len)
40 : TestDelegateBase(read_buf,
41 read_buf_len,
42 make_scoped_ptr(new base::Timer(false, false))) {}
43
44 TestDelegateBase(IOBuffer* read_buf,
45 int read_buf_len,
46 scoped_ptr<base::Timer> timer)
47 : read_buf_(read_buf),
48 read_buf_len_(read_buf_len),
49 timer_(std::move(timer)),
50 loop_(nullptr),
51 error_(OK),
52 on_data_read_count_(0),
53 on_data_sent_count_(0),
54 do_not_start_read_(false),
55 run_until_completion_(false),
56 not_expect_callback_(false) {}
57
58 ~TestDelegateBase() override {}
59
60 void OnHeadersSent() override { CHECK(!not_expect_callback_); }
61
62 void OnHeadersReceived(const SpdyHeaderBlock& response_headers) override {
63 CHECK(!not_expect_callback_);
64
65 response_headers_ = response_headers;
66 if (!do_not_start_read_)
67 StartOrContinueReading();
68 }
69
70 void OnDataRead(int bytes_read) override {
71 CHECK(!not_expect_callback_);
72
73 ++on_data_read_count_;
74 CHECK_GE(bytes_read, OK);
75 data_received_.append(read_buf_->data(), bytes_read);
76 if (!do_not_start_read_)
77 StartOrContinueReading();
78 }
79
80 void OnDataSent() override {
81 CHECK(!not_expect_callback_);
82
83 ++on_data_sent_count_;
84 }
85
86 void OnTrailersReceived(const SpdyHeaderBlock& trailers) override {
87 CHECK(!not_expect_callback_);
88
89 trailers_ = trailers;
90 if (run_until_completion_)
91 loop_->Quit();
92 }
93
94 void OnFailed(int error) override {
95 CHECK(!not_expect_callback_);
96 CHECK_EQ(OK, error_);
97 CHECK_NE(OK, error);
98
99 error_ = error;
100 if (run_until_completion_)
101 loop_->Quit();
102 }
103
104 void Start(scoped_ptr<BidirectionalStreamRequestInfo> request_info,
105 HttpNetworkSession* session) {
106 stream_.reset(new BidirectionalStream(std::move(request_info), session,
107 this, std::move(timer_)));
108 if (run_until_completion_)
109 loop_->Run();
110 }
111
112 void SendData(IOBuffer* data, int length, bool end_of_stream) {
113 not_expect_callback_ = true;
114 stream_->SendData(data, length, end_of_stream);
115 not_expect_callback_ = false;
116 }
117
118 // Starts or continues reading data from |stream_| until no more bytes
119 // can be read synchronously.
120 void StartOrContinueReading() {
121 int rv = ReadData();
122 while (rv > 0) {
123 rv = ReadData();
124 }
125 if (run_until_completion_ && rv == 0)
126 loop_->Quit();
127 }
128
129 // Calls ReadData on the |stream_| and updates internal states.
130 int ReadData() {
131 not_expect_callback_ = true;
132 int rv = stream_->ReadData(read_buf_.get(), read_buf_len_);
133 not_expect_callback_ = false;
134 if (rv > 0)
135 data_received_.append(read_buf_->data(), rv);
136 return rv;
137 }
138
139 // Cancels |stream_|.
140 void CancelStream() { stream_->Cancel(); }
141
142 // Deletes |stream_|.
143 void DeleteStream() { stream_.reset(); }
144
145 NextProto GetProtocol() const { return stream_->GetProtocol(); }
146
147 int64_t GetTotalReceivedBytes() const {
148 return stream_->GetTotalReceivedBytes();
149 }
150
151 int64_t GetTotalSentBytes() const { return stream_->GetTotalSentBytes(); }
152
153 // Const getters for internal states.
154 const std::string& data_received() const { return data_received_; }
155 int error() const { return error_; }
156 const SpdyHeaderBlock& response_headers() const { return response_headers_; }
157 const SpdyHeaderBlock& trailers() const { return trailers_; }
158 int on_data_read_count() const { return on_data_read_count_; }
159 int on_data_sent_count() const { return on_data_sent_count_; }
160
161 // Sets whether the delegate should automatically start reading.
162 void set_do_not_start_read(bool do_not_start_read) {
163 do_not_start_read_ = do_not_start_read;
164 }
165 // Sets whether the delegate should wait until the completion of the stream.
166 void SetRunUntilCompletion(bool run_until_completion) {
167 run_until_completion_ = run_until_completion;
168 loop_.reset(new base::RunLoop);
169 }
170
171 protected:
172 // Quits |loop_|.
173 void QuitLoop() { loop_->Quit(); }
174
175 private:
176 scoped_ptr<BidirectionalStream> stream_;
177 scoped_refptr<IOBuffer> read_buf_;
178 int read_buf_len_;
179 scoped_ptr<base::Timer> timer_;
180 std::string data_received_;
181 scoped_ptr<base::RunLoop> loop_;
182 SpdyHeaderBlock response_headers_;
183 SpdyHeaderBlock trailers_;
184 int error_;
185 int on_data_read_count_;
186 int on_data_sent_count_;
187 bool do_not_start_read_;
188 bool run_until_completion_;
189 // This is to ensure that delegate callback is not invoked synchronously when
190 // calling into |stream_|.
191 bool not_expect_callback_;
192
193 DISALLOW_COPY_AND_ASSIGN(TestDelegateBase);
194 };
195
196 // A delegate that deletes the stream in a particular callback.
197 class CancelOrDeleteStreamDelegate : public TestDelegateBase {
198 public:
199 // Specifies in which callback the stream can be deleted.
200 enum Phase {
201 ON_HEADERS_RECEIVED,
202 ON_DATA_READ,
203 ON_TRAILERS_RECEIVED,
204 ON_FAILED,
205 };
206
207 CancelOrDeleteStreamDelegate(IOBuffer* buf,
208 int buf_len,
209 Phase phase,
210 bool do_cancel)
211 : TestDelegateBase(buf, buf_len), phase_(phase), do_cancel_(do_cancel) {}
212 ~CancelOrDeleteStreamDelegate() override {}
213
214 void OnHeadersReceived(const SpdyHeaderBlock& response_headers) override {
215 TestDelegateBase::OnHeadersReceived(response_headers);
216 if (phase_ == ON_HEADERS_RECEIVED) {
217 CancelOrDelete();
218 QuitLoop();
219 }
220 }
221
222 void OnDataSent() override { NOTREACHED(); }
223
224 void OnDataRead(int bytes_read) override {
225 if (phase_ == ON_HEADERS_RECEIVED) {
226 NOTREACHED();
227 return;
228 }
229 TestDelegateBase::OnDataRead(bytes_read);
230 if (phase_ == ON_DATA_READ) {
231 CancelOrDelete();
232 QuitLoop();
233 }
234 }
235
236 void OnTrailersReceived(const SpdyHeaderBlock& trailers) override {
237 if (phase_ == ON_HEADERS_RECEIVED || phase_ == ON_DATA_READ) {
238 NOTREACHED();
239 return;
240 }
241 TestDelegateBase::OnTrailersReceived(trailers);
242 if (phase_ == ON_TRAILERS_RECEIVED) {
243 CancelOrDelete();
244 QuitLoop();
245 }
246 }
247
248 void OnFailed(int error) override {
249 if (phase_ != ON_FAILED) {
250 NOTREACHED();
251 return;
252 }
253 TestDelegateBase::OnFailed(error);
254 CancelOrDelete();
255 QuitLoop();
256 }
257
258 private:
259 void CancelOrDelete() {
260 if (do_cancel_) {
261 CancelStream();
262 } else {
263 DeleteStream();
264 }
265 }
266
267 // Indicates in which callback the delegate should cancel or delete the
268 // stream.
269 Phase phase_;
270 // Indicates whether to cancel or delete the stream.
271 bool do_cancel_;
272
273 DISALLOW_COPY_AND_ASSIGN(CancelOrDeleteStreamDelegate);
274 };
275
276 // A Timer that does not start a delayed task unless the timer is fired.
277 class MockTimer : public base::MockTimer {
278 public:
279 MockTimer() : base::MockTimer(false, false) {}
280 ~MockTimer() override {}
281
282 void Start(const tracked_objects::Location& posted_from,
283 base::TimeDelta delay,
284 const base::Closure& user_task) override {
285 // Sets a maximum delay, so the timer does not fire unless it is told to.
286 base::TimeDelta infinite_delay = base::TimeDelta::Max();
287 base::MockTimer::Start(posted_from, infinite_delay, user_task);
288 }
289
290 private:
291 DISALLOW_COPY_AND_ASSIGN(MockTimer);
292 };
293
294 } // namespace
295
296 class BidirectionalStreamTest : public testing::TestWithParam<bool> {
297 public:
298 BidirectionalStreamTest()
299 : spdy_util_(kProtoHTTP2, false),
300 session_deps_(kProtoHTTP2),
301 ssl_data_(SSLSocketDataProvider(ASYNC, OK)) {
302 ssl_data_.SetNextProto(kProtoHTTP2);
303 ssl_data_.cert = ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
304 }
305
306 protected:
307 void TearDown() override {
308 if (sequenced_data_) {
309 EXPECT_TRUE(sequenced_data_->AllReadDataConsumed());
310 EXPECT_TRUE(sequenced_data_->AllWriteDataConsumed());
311 }
312 }
313
314 // Initializes the session using SequencedSocketData.
315 void InitSession(MockRead* reads,
316 size_t reads_count,
317 MockWrite* writes,
318 size_t writes_count,
319 const SpdySessionKey& key) {
320 ASSERT_TRUE(ssl_data_.cert.get());
321 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data_);
322 sequenced_data_.reset(
323 new SequencedSocketData(reads, reads_count, writes, writes_count));
324 session_deps_.socket_factory->AddSocketDataProvider(sequenced_data_.get());
325 http_session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
326 session_ = CreateSecureSpdySession(http_session_.get(), key, BoundNetLog());
327 }
328
329 SpdyTestUtil spdy_util_;
330 SpdySessionDependencies session_deps_;
331 scoped_ptr<SequencedSocketData> sequenced_data_;
332 scoped_ptr<HttpNetworkSession> http_session_;
333
334 private:
335 SSLSocketDataProvider ssl_data_;
336 base::WeakPtr<SpdySession> session_;
337 };
338
339 TEST_F(BidirectionalStreamTest, CreateInsecureStream) {
340 scoped_ptr<BidirectionalStreamRequestInfo> request_info(
341 new BidirectionalStreamRequestInfo);
342 request_info->method = "GET";
343 request_info->url = GURL("http://www.example.org/");
344
345 TestDelegateBase delegate(nullptr, 0);
346 HttpNetworkSession::Params params =
347 SpdySessionDependencies::CreateSessionParams(&session_deps_);
348 scoped_ptr<HttpNetworkSession> session(new HttpNetworkSession(params));
349 delegate.SetRunUntilCompletion(true);
350 delegate.Start(std::move(request_info), session.get());
351
352 EXPECT_EQ(ERR_DISALLOWED_URL_SCHEME, delegate.error());
353 }
354
355 // Simulates user calling ReadData after END_STREAM has been received in
356 // BidirectionalStreamSpdyJob.
357 TEST_F(BidirectionalStreamTest, TestReadDataAfterClose) {
358 scoped_ptr<SpdyFrame> req(
359 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
360 // Empty DATA frame with an END_STREAM flag.
361 scoped_ptr<SpdyFrame> end_stream(
362 spdy_util_.ConstructSpdyBodyFrame(1, nullptr, 0, true));
363 MockWrite writes[] = {
364 CreateMockWrite(*req.get(), 0),
365 };
366
367 const char* const kExtraResponseHeaders[] = {"header-name", "header-value"};
368
369 scoped_ptr<SpdyFrame> resp(
370 spdy_util_.ConstructSpdyGetSynReply(kExtraResponseHeaders, 1, 1));
371
372 scoped_ptr<SpdyFrame> body_frame(spdy_util_.ConstructSpdyBodyFrame(1, false));
373 // Last body frame has END_STREAM flag set.
374 scoped_ptr<SpdyFrame> last_body_frame(
375 spdy_util_.ConstructSpdyBodyFrame(1, true));
376
377 MockRead reads[] = {
378 CreateMockRead(*resp, 1),
379 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause.
380 CreateMockRead(*body_frame, 3),
381 MockRead(ASYNC, ERR_IO_PENDING, 4), // Force a pause.
382 CreateMockRead(*body_frame, 5),
383 CreateMockRead(*last_body_frame, 6),
384 MockRead(SYNCHRONOUS, 0, 7),
385 };
386
387 HostPortPair host_port_pair("www.example.org", 443);
388 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
389 PRIVACY_MODE_DISABLED);
390 InitSession(reads, arraysize(reads), writes, arraysize(writes), key);
391
392 scoped_ptr<BidirectionalStreamRequestInfo> request_info(
393 new BidirectionalStreamRequestInfo);
394 request_info->method = "GET";
395 request_info->url = GURL("https://www.example.org/");
396 request_info->end_stream_on_headers = true;
397 request_info->priority = LOWEST;
398
399 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
400 // Create a MockTimer. Retain a raw pointer since the underlying
401 // BidirectionalStreamJob owns it.
402 MockTimer* timer = new MockTimer();
403 scoped_ptr<TestDelegateBase> delegate(new TestDelegateBase(
404 read_buffer.get(), kReadBufferSize, make_scoped_ptr(timer)));
405 delegate->set_do_not_start_read(true);
406
407 delegate->Start(std::move(request_info), http_session_.get());
408
409 // Write request, and deliver response headers.
410 sequenced_data_->RunUntilPaused();
411 EXPECT_FALSE(timer->IsRunning());
412 // ReadData returns asynchronously because no data is buffered.
413 int rv = delegate->ReadData();
414 EXPECT_EQ(ERR_IO_PENDING, rv);
415 // Deliver a DATA frame.
416 sequenced_data_->Resume();
417 base::RunLoop().RunUntilIdle();
418 timer->Fire();
419 // Asynchronous completion callback is invoke.
420 EXPECT_EQ(1, delegate->on_data_read_count());
421 EXPECT_EQ(kUploadDataSize * 1,
422 static_cast<int>(delegate->data_received().size()));
423
424 // Deliver the rest. Note that user has not called a second ReadData.
425 sequenced_data_->Resume();
426 base::RunLoop().RunUntilIdle();
427 // ReadData now. Read should complete synchronously.
428 rv = delegate->ReadData();
429 EXPECT_EQ(kUploadDataSize * 2, rv);
430 rv = delegate->ReadData();
431 EXPECT_EQ(OK, rv); // EOF.
432
433 const SpdyHeaderBlock response_headers = delegate->response_headers();
434 EXPECT_EQ("200", response_headers.find(":status")->second);
435 EXPECT_EQ("header-value", response_headers.find("header-name")->second);
436 EXPECT_EQ(1, delegate->on_data_read_count());
437 EXPECT_EQ(0, delegate->on_data_sent_count());
438 EXPECT_EQ(kProtoHTTP2, delegate->GetProtocol());
439 EXPECT_EQ(CountWriteBytes(writes, arraysize(writes)),
440 delegate->GetTotalSentBytes());
441 EXPECT_EQ(CountReadBytes(reads, arraysize(reads)),
442 delegate->GetTotalReceivedBytes());
443 }
444
445 TEST_F(BidirectionalStreamTest, TestInterleaveReadDataAndSendData) {
446 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
447
448 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
449 "https://www.example.org", 1, kBodyDataSize * 3, LOWEST, nullptr, 0));
450 scoped_ptr<SpdyFrame> data_frame1(
451 framer.CreateDataFrame(1, kBodyData, kBodyDataSize, DATA_FLAG_NONE));
452 scoped_ptr<SpdyFrame> data_frame2(
453 framer.CreateDataFrame(1, kBodyData, kBodyDataSize, DATA_FLAG_NONE));
454 scoped_ptr<SpdyFrame> data_frame3(
455 framer.CreateDataFrame(1, kBodyData, kBodyDataSize, DATA_FLAG_FIN));
456 MockWrite writes[] = {
457 CreateMockWrite(*req, 0), CreateMockWrite(*data_frame1, 3),
458 CreateMockWrite(*data_frame2, 6), CreateMockWrite(*data_frame3, 9),
459 };
460
461 scoped_ptr<SpdyFrame> resp(
462 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
463 scoped_ptr<SpdyFrame> response_body_frame1(
464 spdy_util_.ConstructSpdyBodyFrame(1, false));
465 scoped_ptr<SpdyFrame> response_body_frame2(
466 spdy_util_.ConstructSpdyBodyFrame(1, true));
467
468 MockRead reads[] = {
469 CreateMockRead(*resp, 1),
470 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause.
471 CreateMockRead(*response_body_frame1, 4),
472 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause.
473 CreateMockRead(*response_body_frame2, 7),
474 MockRead(ASYNC, ERR_IO_PENDING, 8), // Force a pause.
475 MockRead(ASYNC, 0, 10),
476 };
477
478 HostPortPair host_port_pair("www.example.org", 443);
479 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
480 PRIVACY_MODE_DISABLED);
481 InitSession(reads, arraysize(reads), writes, arraysize(writes), key);
482
483 scoped_ptr<BidirectionalStreamRequestInfo> request_info(
484 new BidirectionalStreamRequestInfo);
485 request_info->method = "POST";
486 request_info->url = GURL("https://www.example.org/");
487 request_info->priority = LOWEST;
488 request_info->extra_headers.SetHeader(net::HttpRequestHeaders::kContentLength,
489 base::SizeTToString(kBodyDataSize * 3));
490
491 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
492 MockTimer* timer = new MockTimer();
493 scoped_ptr<TestDelegateBase> delegate(new TestDelegateBase(
494 read_buffer.get(), kReadBufferSize, make_scoped_ptr(timer)));
495 delegate->set_do_not_start_read(true);
496 delegate->Start(std::move(request_info), http_session_.get());
497 // Send the request and receive response headers.
498 sequenced_data_->RunUntilPaused();
499 EXPECT_FALSE(timer->IsRunning());
500
501 // Send a DATA frame.
502 scoped_refptr<StringIOBuffer> buf(
503 new StringIOBuffer(std::string(kBodyData, kBodyDataSize)));
504
505 // Send a DATA frame.
506 delegate->SendData(buf.get(), buf->size(), false);
507 // ReadData and it should return asynchronously because no data is buffered.
508 int rv = delegate->ReadData();
509 EXPECT_EQ(ERR_IO_PENDING, rv);
510 // Deliver a DATA frame, and fire the timer.
511 sequenced_data_->Resume();
512 sequenced_data_->RunUntilPaused();
513 timer->Fire();
514 base::RunLoop().RunUntilIdle();
515 EXPECT_EQ(1, delegate->on_data_sent_count());
516 EXPECT_EQ(1, delegate->on_data_read_count());
517
518 // Send a DATA frame.
519 delegate->SendData(buf.get(), buf->size(), false);
520 // ReadData and it should return asynchronously because no data is buffered.
521 rv = delegate->ReadData();
522 EXPECT_EQ(ERR_IO_PENDING, rv);
523 // Deliver a DATA frame, and fire the timer.
524 sequenced_data_->Resume();
525 sequenced_data_->RunUntilPaused();
526 timer->Fire();
527 base::RunLoop().RunUntilIdle();
528 // Last DATA frame is read. Server half closes.
529 EXPECT_EQ(2, delegate->on_data_read_count());
530 EXPECT_EQ(2, delegate->on_data_sent_count());
531
532 // Send the last body frame. Client half closes.
533 delegate->SendData(buf.get(), buf->size(), true);
534 sequenced_data_->Resume();
535 base::RunLoop().RunUntilIdle();
536 EXPECT_EQ(3, delegate->on_data_sent_count());
537
538 // OnClose is invoked since both sides are closed.
539 rv = delegate->ReadData();
540 EXPECT_EQ(OK, rv);
541
542 EXPECT_EQ("200", delegate->response_headers().find(":status")->second);
543 EXPECT_EQ(2, delegate->on_data_read_count());
544 EXPECT_EQ(3, delegate->on_data_sent_count());
545 EXPECT_EQ(kProtoHTTP2, delegate->GetProtocol());
546 EXPECT_EQ(CountWriteBytes(writes, arraysize(writes)),
547 delegate->GetTotalSentBytes());
548 EXPECT_EQ(CountReadBytes(reads, arraysize(reads)),
549 delegate->GetTotalReceivedBytes());
550 }
551
552 // Tests that BidirectionalStreamSpdyJob::OnClose will complete any remaining
553 // read even if the read queue is empty.
554 TEST_F(BidirectionalStreamTest, TestCompleteAsyncRead) {
555 scoped_ptr<SpdyFrame> req(
556 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
557 // Empty DATA frame with an END_STREAM flag.
558 scoped_ptr<SpdyFrame> end_stream(
559 spdy_util_.ConstructSpdyBodyFrame(1, nullptr, 0, true));
560
561 MockWrite writes[] = {CreateMockWrite(*req.get(), 0)};
562
563 scoped_ptr<SpdyFrame> resp(
564 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
565
566 scoped_ptr<SpdyFrame> response_body_frame(
567 spdy_util_.ConstructSpdyBodyFrame(1, nullptr, 0, true));
568
569 MockRead reads[] = {
570 CreateMockRead(*resp, 1),
571 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause.
572 CreateMockRead(*response_body_frame, 3), MockRead(SYNCHRONOUS, 0, 4),
573 };
574
575 HostPortPair host_port_pair("www.example.org", 443);
576 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
577 PRIVACY_MODE_DISABLED);
578 InitSession(reads, arraysize(reads), writes, arraysize(writes), key);
579
580 scoped_ptr<BidirectionalStreamRequestInfo> request_info(
581 new BidirectionalStreamRequestInfo);
582 request_info->method = "GET";
583 request_info->url = GURL("https://www.example.org/");
584 request_info->priority = LOWEST;
585 request_info->end_stream_on_headers = true;
586
587 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
588 MockTimer* timer = new MockTimer();
589 scoped_ptr<TestDelegateBase> delegate(new TestDelegateBase(
590 read_buffer.get(), kReadBufferSize, make_scoped_ptr(timer)));
591 delegate->set_do_not_start_read(true);
592 delegate->Start(std::move(request_info), http_session_.get());
593 // Write request, and deliver response headers.
594 sequenced_data_->RunUntilPaused();
595 EXPECT_FALSE(timer->IsRunning());
596
597 // ReadData should return asynchronously because no data is buffered.
598 int rv = delegate->ReadData();
599 EXPECT_EQ(ERR_IO_PENDING, rv);
600 // Deliver END_STREAM.
601 // OnClose should trigger completion of the remaining read.
602 sequenced_data_->Resume();
603 base::RunLoop().RunUntilIdle();
604
605 EXPECT_EQ("200", delegate->response_headers().find(":status")->second);
606 EXPECT_EQ(1, delegate->on_data_read_count());
607 EXPECT_EQ(0u, delegate->data_received().size());
608 EXPECT_EQ(0, delegate->on_data_sent_count());
609 EXPECT_EQ(kProtoHTTP2, delegate->GetProtocol());
610 EXPECT_EQ(CountWriteBytes(writes, arraysize(writes)),
611 delegate->GetTotalSentBytes());
612 EXPECT_EQ(CountReadBytes(reads, arraysize(reads)),
613 delegate->GetTotalReceivedBytes());
614 }
615
616 TEST_F(BidirectionalStreamTest, TestBuffering) {
617 scoped_ptr<SpdyFrame> req(
618 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
619 // Empty DATA frame with an END_STREAM flag.
620 scoped_ptr<SpdyFrame> end_stream(
621 spdy_util_.ConstructSpdyBodyFrame(1, nullptr, 0, true));
622
623 MockWrite writes[] = {CreateMockWrite(*req.get(), 0)};
624
625 const char* const kExtraResponseHeaders[] = {"header-name", "header-value"};
626
627 scoped_ptr<SpdyFrame> resp(
628 spdy_util_.ConstructSpdyGetSynReply(kExtraResponseHeaders, 1, 1));
629
630 scoped_ptr<SpdyFrame> body_frame(spdy_util_.ConstructSpdyBodyFrame(1, false));
631 // Last body frame has END_STREAM flag set.
632 scoped_ptr<SpdyFrame> last_body_frame(
633 spdy_util_.ConstructSpdyBodyFrame(1, true));
634
635 MockRead reads[] = {
636 CreateMockRead(*resp, 1),
637 CreateMockRead(*body_frame, 2),
638 CreateMockRead(*body_frame, 3),
639 MockRead(ASYNC, ERR_IO_PENDING, 4), // Force a pause.
640 CreateMockRead(*last_body_frame, 5),
641 MockRead(SYNCHRONOUS, 0, 6),
642 };
643
644 HostPortPair host_port_pair("www.example.org", 443);
645 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
646 PRIVACY_MODE_DISABLED);
647 InitSession(reads, arraysize(reads), writes, arraysize(writes), key);
648
649 scoped_ptr<BidirectionalStreamRequestInfo> request_info(
650 new BidirectionalStreamRequestInfo);
651 request_info->method = "GET";
652 request_info->url = GURL("https://www.example.org/");
653 request_info->priority = LOWEST;
654 request_info->end_stream_on_headers = true;
655
656 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
657 MockTimer* timer = new MockTimer();
658 scoped_ptr<TestDelegateBase> delegate(new TestDelegateBase(
659 read_buffer.get(), kReadBufferSize, make_scoped_ptr(timer)));
660 delegate->Start(std::move(request_info), http_session_.get());
661 // Deliver two DATA frames together.
662 sequenced_data_->RunUntilPaused();
663 EXPECT_TRUE(timer->IsRunning());
664 timer->Fire();
665 base::RunLoop().RunUntilIdle();
666 // This should trigger |more_read_data_pending_| to execute the task at a
667 // later time, and Delegate::OnReadComplete should not have been called.
668 EXPECT_TRUE(timer->IsRunning());
669 EXPECT_EQ(0, delegate->on_data_read_count());
670
671 // Fire the timer now, the two DATA frame should be combined into one
672 // single Delegate::OnReadComplete callback.
673 timer->Fire();
674 base::RunLoop().RunUntilIdle();
675 EXPECT_EQ(1, delegate->on_data_read_count());
676 EXPECT_EQ(kUploadDataSize * 2,
677 static_cast<int>(delegate->data_received().size()));
678
679 // Deliver last DATA frame and EOF. There will be an additional
680 // Delegate::OnReadComplete callback.
681 sequenced_data_->Resume();
682 EXPECT_EQ(2, delegate->on_data_read_count());
683 EXPECT_EQ(kUploadDataSize * 3,
684 static_cast<int>(delegate->data_received().size()));
685
686 const SpdyHeaderBlock response_headers = delegate->response_headers();
687 EXPECT_EQ("200", response_headers.find(":status")->second);
688 EXPECT_EQ("header-value", response_headers.find("header-name")->second);
689 EXPECT_EQ(0, delegate->on_data_sent_count());
690 EXPECT_EQ(kProtoHTTP2, delegate->GetProtocol());
691 EXPECT_EQ(CountWriteBytes(writes, arraysize(writes)),
692 delegate->GetTotalSentBytes());
693 EXPECT_EQ(CountReadBytes(reads, arraysize(reads)),
694 delegate->GetTotalReceivedBytes());
695 }
696
697 TEST_F(BidirectionalStreamTest, TestBufferingWithTrailers) {
698 scoped_ptr<SpdyFrame> req(
699 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
700 // Empty DATA frame with an END_STREAM flag.
701 scoped_ptr<SpdyFrame> end_stream(
702 spdy_util_.ConstructSpdyBodyFrame(1, nullptr, 0, true));
703
704 MockWrite writes[] = {
705 CreateMockWrite(*req.get(), 0),
706 };
707
708 const char* const kExtraResponseHeaders[] = {"header-name", "header-value"};
709
710 scoped_ptr<SpdyFrame> resp(
711 spdy_util_.ConstructSpdyGetSynReply(kExtraResponseHeaders, 1, 1));
712
713 scoped_ptr<SpdyFrame> body_frame(spdy_util_.ConstructSpdyBodyFrame(1, false));
714
715 const char* const kTrailers[] = {"foo", "bar"};
716 scoped_ptr<SpdyFrame> trailers(
717 spdy_util_.ConstructSpdyHeaderFrame(1, kTrailers, 1, true));
718
719 MockRead reads[] = {
720 CreateMockRead(*resp, 1), CreateMockRead(*body_frame, 2),
721 CreateMockRead(*body_frame, 3), CreateMockRead(*body_frame, 4),
722 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause.
723 CreateMockRead(*trailers, 6), MockRead(SYNCHRONOUS, 0, 7),
724 };
725
726 HostPortPair host_port_pair("www.example.org", 443);
727 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
728 PRIVACY_MODE_DISABLED);
729 InitSession(reads, arraysize(reads), writes, arraysize(writes), key);
730
731 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
732 MockTimer* timer = new MockTimer();
733 scoped_ptr<TestDelegateBase> delegate(new TestDelegateBase(
734 read_buffer.get(), kReadBufferSize, make_scoped_ptr(timer)));
735
736 scoped_ptr<BidirectionalStreamRequestInfo> request_info(
737 new BidirectionalStreamRequestInfo);
738 request_info->method = "GET";
739 request_info->url = GURL("https://www.example.org/");
740 request_info->priority = LOWEST;
741 request_info->end_stream_on_headers = true;
742
743 delegate->Start(std::move(request_info), http_session_.get());
744 // Deliver all three DATA frames together.
745 sequenced_data_->RunUntilPaused();
746 EXPECT_TRUE(timer->IsRunning());
747 timer->Fire();
748 base::RunLoop().RunUntilIdle();
749 // This should trigger |more_read_data_pending_| to execute the task at a
750 // later time, and Delegate::OnReadComplete should not have been called.
751 EXPECT_TRUE(timer->IsRunning());
752 EXPECT_EQ(0, delegate->on_data_read_count());
753
754 // Deliver trailers. Remaining read should be completed, since OnClose is
755 // called right after OnTrailersReceived. The three DATA frames should be
756 // delivered in a single OnReadCompleted callback.
757 sequenced_data_->Resume();
758 EXPECT_EQ(1, delegate->on_data_read_count());
759 EXPECT_EQ(kUploadDataSize * 3,
760 static_cast<int>(delegate->data_received().size()));
761 const SpdyHeaderBlock response_headers = delegate->response_headers();
762 EXPECT_EQ("200", response_headers.find(":status")->second);
763 EXPECT_EQ("header-value", response_headers.find("header-name")->second);
764 EXPECT_EQ("bar", delegate->trailers().find("foo")->second);
765 EXPECT_EQ(0, delegate->on_data_sent_count());
766 EXPECT_EQ(kProtoHTTP2, delegate->GetProtocol());
767 EXPECT_EQ(CountWriteBytes(writes, arraysize(writes)),
768 delegate->GetTotalSentBytes());
769 EXPECT_EQ(CountReadBytes(reads, arraysize(reads)),
770 delegate->GetTotalReceivedBytes());
771 }
772
773 TEST_F(BidirectionalStreamTest, CancelStreamAfterSendData) {
774 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
775
776 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
777 "https://www.example.org", 1, kBodyDataSize * 3, LOWEST, nullptr, 0));
778 scoped_ptr<SpdyFrame> data_frame(
779 framer.CreateDataFrame(1, kBodyData, kBodyDataSize, DATA_FLAG_NONE));
780 scoped_ptr<SpdyFrame> rst(
781 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
782
783 MockWrite writes[] = {
784 CreateMockWrite(*req, 0), CreateMockWrite(*data_frame, 3),
785 CreateMockWrite(*rst, 5),
786 };
787
788 scoped_ptr<SpdyFrame> resp(
789 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
790 scoped_ptr<SpdyFrame> response_body_frame(
791 spdy_util_.ConstructSpdyBodyFrame(1, false));
792
793 MockRead reads[] = {
794 CreateMockRead(*resp, 1),
795 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause.
796 MockRead(ASYNC, ERR_IO_PENDING, 4), // Force a pause.
797 MockRead(ASYNC, 0, 6),
798 };
799
800 HostPortPair host_port_pair("www.example.org", 443);
801 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
802 PRIVACY_MODE_DISABLED);
803 InitSession(reads, arraysize(reads), writes, arraysize(writes), key);
804
805 scoped_ptr<BidirectionalStreamRequestInfo> request_info(
806 new BidirectionalStreamRequestInfo);
807 request_info->method = "POST";
808 request_info->url = GURL("https://www.example.org/");
809 request_info->priority = LOWEST;
810 request_info->extra_headers.SetHeader(net::HttpRequestHeaders::kContentLength,
811 base::SizeTToString(kBodyDataSize * 3));
812
813 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
814 scoped_ptr<TestDelegateBase> delegate(
815 new TestDelegateBase(read_buffer.get(), kReadBufferSize));
816 delegate->set_do_not_start_read(true);
817 delegate->Start(std::move(request_info), http_session_.get());
818 // Send the request and receive response headers.
819 sequenced_data_->RunUntilPaused();
820 EXPECT_EQ(kProtoHTTP2, delegate->GetProtocol());
821
822 // Send a DATA frame.
823 scoped_refptr<StringIOBuffer> buf(
824 new StringIOBuffer(std::string(kBodyData, kBodyDataSize)));
825 delegate->SendData(buf.get(), buf->size(), false);
826 sequenced_data_->Resume();
827 base::RunLoop().RunUntilIdle();
828 // Cancel the stream.
829 delegate->CancelStream();
830 sequenced_data_->Resume();
831 base::RunLoop().RunUntilIdle();
832
833 EXPECT_EQ("200", delegate->response_headers().find(":status")->second);
834 EXPECT_EQ(0, delegate->on_data_read_count());
835 // EXPECT_EQ(1, delegate->on_data_send_count());
836 // OnDataSent may or may not have been invoked.
837 // Calling after stream is canceled gives kProtoUnknown.
838 EXPECT_EQ(kProtoUnknown, delegate->GetProtocol());
839 EXPECT_EQ(0, delegate->GetTotalSentBytes());
840 EXPECT_EQ(0, delegate->GetTotalReceivedBytes());
841 }
842
843 TEST_F(BidirectionalStreamTest, CancelStreamDuringReadData) {
844 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
845
846 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
847 "https://www.example.org", 1, kBodyDataSize * 3, LOWEST, nullptr, 0));
848 scoped_ptr<SpdyFrame> data_frame(
849 framer.CreateDataFrame(1, kBodyData, kBodyDataSize, DATA_FLAG_NONE));
850 scoped_ptr<SpdyFrame> rst(
851 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
852
853 MockWrite writes[] = {
854 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4),
855 };
856
857 scoped_ptr<SpdyFrame> resp(
858 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
859 scoped_ptr<SpdyFrame> response_body_frame(
860 spdy_util_.ConstructSpdyBodyFrame(1, false));
861
862 MockRead reads[] = {
863 CreateMockRead(*resp, 1),
864 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause.
865 CreateMockRead(*response_body_frame, 3), MockRead(ASYNC, 0, 5),
866 };
867
868 HostPortPair host_port_pair("www.example.org", 443);
869 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
870 PRIVACY_MODE_DISABLED);
871 InitSession(reads, arraysize(reads), writes, arraysize(writes), key);
872
873 scoped_ptr<BidirectionalStreamRequestInfo> request_info(
874 new BidirectionalStreamRequestInfo);
875 request_info->method = "POST";
876 request_info->url = GURL("https://www.example.org/");
877 request_info->priority = LOWEST;
878 request_info->extra_headers.SetHeader(net::HttpRequestHeaders::kContentLength,
879 base::SizeTToString(kBodyDataSize * 3));
880
881 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
882 scoped_ptr<TestDelegateBase> delegate(
883 new TestDelegateBase(read_buffer.get(), kReadBufferSize));
884 delegate->set_do_not_start_read(true);
885 delegate->Start(std::move(request_info), http_session_.get());
886 // Send the request and receive response headers.
887 base::RunLoop().RunUntilIdle();
888
889 EXPECT_EQ("200", delegate->response_headers().find(":status")->second);
890 // Cancel the stream after ReadData returns ERR_IO_PENDING.
891 int rv = delegate->ReadData();
892 EXPECT_EQ(kProtoHTTP2, delegate->GetProtocol());
893 EXPECT_EQ(ERR_IO_PENDING, rv);
894 delegate->CancelStream();
895 sequenced_data_->Resume();
896 base::RunLoop().RunUntilIdle();
897
898 EXPECT_EQ(0, delegate->on_data_read_count());
899 EXPECT_EQ(0, delegate->on_data_sent_count());
900 // Calling after stream is canceled gives kProtoUnknown.
901 EXPECT_EQ(kProtoUnknown, delegate->GetProtocol());
902 EXPECT_EQ(0, delegate->GetTotalSentBytes());
903 EXPECT_EQ(0, delegate->GetTotalReceivedBytes());
904 }
905
906 // Receiving a header with uppercase ASCII will result in a protocol error,
907 // which should be propagated via Delegate::OnFailed.
908 TEST_F(BidirectionalStreamTest, PropagateProtocolError) {
909 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
910 "https://www.example.org", 1, kBodyDataSize * 3, LOW, nullptr, 0));
911 scoped_ptr<SpdyFrame> rst(
912 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
913
914 MockWrite writes[] = {
915 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 2),
916 };
917
918 const char* const kExtraHeaders[] = {"X-UpperCase", "yes"};
919 scoped_ptr<SpdyFrame> resp(
920 spdy_util_.ConstructSpdyGetSynReply(kExtraHeaders, 1, 1));
921
922 MockRead reads[] = {
923 CreateMockRead(*resp, 1), MockRead(ASYNC, 0, 3),
924 };
925
926 HostPortPair host_port_pair("www.example.org", 443);
927 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
928 PRIVACY_MODE_DISABLED);
929 InitSession(reads, arraysize(reads), writes, arraysize(writes), key);
930
931 scoped_ptr<BidirectionalStreamRequestInfo> request_info(
932 new BidirectionalStreamRequestInfo);
933 request_info->method = "POST";
934 request_info->url = GURL("https://www.example.org/");
935 request_info->extra_headers.SetHeader(net::HttpRequestHeaders::kContentLength,
936 base::SizeTToString(kBodyDataSize * 3));
937
938 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
939 scoped_ptr<TestDelegateBase> delegate(
940 new TestDelegateBase(read_buffer.get(), kReadBufferSize));
941 delegate->SetRunUntilCompletion(true);
942 delegate->Start(std::move(request_info), http_session_.get());
943
944 base::RunLoop().RunUntilIdle();
945 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, delegate->error());
946 EXPECT_EQ(delegate->response_headers().end(),
947 delegate->response_headers().find(":status"));
948 EXPECT_EQ(0, delegate->on_data_read_count());
949 EXPECT_EQ(0, delegate->on_data_sent_count());
950 EXPECT_EQ(kProtoHTTP2, delegate->GetProtocol());
951 // BidirectionalStreamSpdyStreamJob does not count the bytes sent for |rst|
952 // because it is sent after SpdyStream::Delegate::OnClose is called.
953 EXPECT_EQ(CountWriteBytes(writes, 1), delegate->GetTotalSentBytes());
954 EXPECT_EQ(CountReadBytes(reads, arraysize(reads)),
955 delegate->GetTotalReceivedBytes());
956 }
957
958 INSTANTIATE_TEST_CASE_P(CancelOrDeleteTests,
959 BidirectionalStreamTest,
960 ::testing::Values(true, false));
961
962 TEST_P(BidirectionalStreamTest, CancelOrDeleteStreamDuringOnHeadersReceived) {
963 scoped_ptr<SpdyFrame> req(
964 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
965
966 scoped_ptr<SpdyFrame> rst(
967 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
968 MockWrite writes[] = {
969 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 2),
970 };
971
972 const char* const kExtraResponseHeaders[] = {"header-name", "header-value"};
973
974 scoped_ptr<SpdyFrame> resp(
975 spdy_util_.ConstructSpdyGetSynReply(kExtraResponseHeaders, 1, 1));
976
977 MockRead reads[] = {
978 CreateMockRead(*resp, 1), MockRead(ASYNC, 0, 3),
979 };
980
981 HostPortPair host_port_pair("www.example.org", 443);
982 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
983 PRIVACY_MODE_DISABLED);
984 InitSession(reads, arraysize(reads), writes, arraysize(writes), key);
985
986 scoped_ptr<BidirectionalStreamRequestInfo> request_info(
987 new BidirectionalStreamRequestInfo);
988 request_info->method = "GET";
989 request_info->url = GURL("https://www.example.org/");
990 request_info->priority = LOWEST;
991 request_info->end_stream_on_headers = true;
992
993 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
994 scoped_ptr<CancelOrDeleteStreamDelegate> delegate(
995 new CancelOrDeleteStreamDelegate(
996 read_buffer.get(), kReadBufferSize,
997 CancelOrDeleteStreamDelegate::Phase::ON_HEADERS_RECEIVED,
998 GetParam()));
999 delegate->SetRunUntilCompletion(true);
1000 delegate->Start(std::move(request_info), http_session_.get());
1001 // Makes sure delegate does not get called.
1002 base::RunLoop().RunUntilIdle();
1003 const SpdyHeaderBlock response_headers = delegate->response_headers();
1004 EXPECT_EQ("200", response_headers.find(":status")->second);
1005 EXPECT_EQ("header-value", response_headers.find("header-name")->second);
1006 EXPECT_EQ(0u, delegate->data_received().size());
1007 EXPECT_EQ(0, delegate->on_data_sent_count());
1008 EXPECT_EQ(0, delegate->on_data_read_count());
1009
1010 // If stream is destroyed, do not call into stream.
1011 if (!GetParam())
1012 return;
1013 EXPECT_EQ(0, delegate->GetTotalSentBytes());
1014 EXPECT_EQ(0, delegate->GetTotalReceivedBytes());
1015 EXPECT_EQ(kProtoUnknown, delegate->GetProtocol());
1016 }
1017
1018 TEST_P(BidirectionalStreamTest, CancelOrDeleteStreamDuringOnDataRead) {
1019 scoped_ptr<SpdyFrame> req(
1020 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
1021
1022 scoped_ptr<SpdyFrame> rst(
1023 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
1024 MockWrite writes[] = {
1025 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 3),
1026 };
1027
1028 const char* const kExtraResponseHeaders[] = {"header-name", "header-value"};
1029
1030 scoped_ptr<SpdyFrame> resp(
1031 spdy_util_.ConstructSpdyGetSynReply(kExtraResponseHeaders, 1, 1));
1032
1033 scoped_ptr<SpdyFrame> response_body_frame(
1034 spdy_util_.ConstructSpdyBodyFrame(1, false));
1035
1036 MockRead reads[] = {
1037 CreateMockRead(*resp, 1), CreateMockRead(*response_body_frame, 2),
1038 MockRead(ASYNC, 0, 4),
1039 };
1040
1041 HostPortPair host_port_pair("www.example.org", 443);
1042 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
1043 PRIVACY_MODE_DISABLED);
1044 InitSession(reads, arraysize(reads), writes, arraysize(writes), key);
1045
1046 scoped_ptr<BidirectionalStreamRequestInfo> request_info(
1047 new BidirectionalStreamRequestInfo);
1048 request_info->method = "GET";
1049 request_info->url = GURL("https://www.example.org/");
1050 request_info->priority = LOWEST;
1051 request_info->end_stream_on_headers = true;
1052
1053 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
1054 scoped_ptr<CancelOrDeleteStreamDelegate> delegate(
1055 new CancelOrDeleteStreamDelegate(
1056 read_buffer.get(), kReadBufferSize,
1057 CancelOrDeleteStreamDelegate::Phase::ON_DATA_READ, GetParam()));
1058 delegate->SetRunUntilCompletion(true);
1059 delegate->Start(std::move(request_info), http_session_.get());
1060 // Makes sure delegate does not get called.
1061 base::RunLoop().RunUntilIdle();
1062 const SpdyHeaderBlock response_headers = delegate->response_headers();
1063 EXPECT_EQ("200", response_headers.find(":status")->second);
1064 EXPECT_EQ("header-value", response_headers.find("header-name")->second);
1065 EXPECT_EQ(kUploadDataSize * 1,
1066 static_cast<int>(delegate->data_received().size()));
1067 EXPECT_EQ(0, delegate->on_data_sent_count());
1068
1069 // If stream is destroyed, do not call into stream.
1070 if (!GetParam())
1071 return;
1072 EXPECT_EQ(0, delegate->GetTotalSentBytes());
1073 EXPECT_EQ(0, delegate->GetTotalReceivedBytes());
1074 EXPECT_EQ(kProtoUnknown, delegate->GetProtocol());
1075 }
1076
1077 TEST_P(BidirectionalStreamTest, CancelOrDeleteStreamDuringOnTrailersReceived) {
1078 scoped_ptr<SpdyFrame> req(
1079 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
1080
1081 scoped_ptr<SpdyFrame> rst(
1082 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
1083 MockWrite writes[] = {
1084 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 4),
1085 };
1086
1087 const char* const kExtraResponseHeaders[] = {"header-name", "header-value"};
1088
1089 scoped_ptr<SpdyFrame> resp(
1090 spdy_util_.ConstructSpdyGetSynReply(kExtraResponseHeaders, 1, 1));
1091
1092 scoped_ptr<SpdyFrame> response_body_frame(
1093 spdy_util_.ConstructSpdyBodyFrame(1, false));
1094
1095 const char* const kTrailers[] = {"foo", "bar"};
1096 scoped_ptr<SpdyFrame> trailers(
1097 spdy_util_.ConstructSpdyHeaderFrame(1, kTrailers, 1, true));
1098
1099 MockRead reads[] = {
1100 CreateMockRead(*resp, 1), CreateMockRead(*response_body_frame, 2),
1101 CreateMockRead(*trailers, 3), MockRead(ASYNC, 0, 5),
1102 };
1103
1104 HostPortPair host_port_pair("www.example.org", 443);
1105 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
1106 PRIVACY_MODE_DISABLED);
1107 InitSession(reads, arraysize(reads), writes, arraysize(writes), key);
1108
1109 scoped_ptr<BidirectionalStreamRequestInfo> request_info(
1110 new BidirectionalStreamRequestInfo);
1111 request_info->method = "GET";
1112 request_info->url = GURL("https://www.example.org/");
1113 request_info->priority = LOWEST;
1114 request_info->end_stream_on_headers = true;
1115
1116 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
1117 scoped_ptr<CancelOrDeleteStreamDelegate> delegate(
1118 new CancelOrDeleteStreamDelegate(
1119 read_buffer.get(), kReadBufferSize,
1120 CancelOrDeleteStreamDelegate::Phase::ON_TRAILERS_RECEIVED,
1121 GetParam()));
1122 delegate->SetRunUntilCompletion(true);
1123 delegate->Start(std::move(request_info), http_session_.get());
1124 // Makes sure delegate does not get called.
1125 base::RunLoop().RunUntilIdle();
1126 const SpdyHeaderBlock response_headers = delegate->response_headers();
1127 EXPECT_EQ("200", response_headers.find(":status")->second);
1128 EXPECT_EQ("header-value", response_headers.find("header-name")->second);
1129 EXPECT_EQ("bar", delegate->trailers().find("foo")->second);
1130 EXPECT_EQ(0, delegate->on_data_sent_count());
1131 // OnDataRead may or may not have been fired before the stream is
1132 // canceled/deleted.
1133
1134 // If stream is destroyed, do not call into stream.
1135 if (!GetParam())
1136 return;
1137 EXPECT_EQ(0, delegate->GetTotalSentBytes());
1138 EXPECT_EQ(0, delegate->GetTotalReceivedBytes());
1139 EXPECT_EQ(kProtoUnknown, delegate->GetProtocol());
1140 }
1141
1142 TEST_P(BidirectionalStreamTest, CancelOrDeleteStreamDuringOnFailed) {
1143 scoped_ptr<SpdyFrame> req(
1144 spdy_util_.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST));
1145
1146 scoped_ptr<SpdyFrame> rst(
1147 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
1148
1149 MockWrite writes[] = {
1150 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 2),
1151 };
1152
1153 const char* const kExtraHeaders[] = {"X-UpperCase", "yes"};
1154 scoped_ptr<SpdyFrame> resp(
1155 spdy_util_.ConstructSpdyGetSynReply(kExtraHeaders, 1, 1));
1156
1157 MockRead reads[] = {
1158 CreateMockRead(*resp, 1), MockRead(ASYNC, 0, 3),
1159 };
1160
1161 HostPortPair host_port_pair("www.example.org", 443);
1162 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
1163 PRIVACY_MODE_DISABLED);
1164 InitSession(reads, arraysize(reads), writes, arraysize(writes), key);
1165
1166 scoped_ptr<BidirectionalStreamRequestInfo> request_info(
1167 new BidirectionalStreamRequestInfo);
1168 request_info->method = "GET";
1169 request_info->url = GURL("https://www.example.org/");
1170 request_info->priority = LOWEST;
1171 request_info->end_stream_on_headers = true;
1172
1173 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
1174 scoped_ptr<CancelOrDeleteStreamDelegate> delegate(
1175 new CancelOrDeleteStreamDelegate(
1176 read_buffer.get(), kReadBufferSize,
1177 CancelOrDeleteStreamDelegate::Phase::ON_FAILED, GetParam()));
1178 delegate->SetRunUntilCompletion(true);
1179 delegate->Start(std::move(request_info), http_session_.get());
1180 // Makes sure delegate does not get called.
1181 base::RunLoop().RunUntilIdle();
1182 EXPECT_EQ(delegate->response_headers().end(),
1183 delegate->response_headers().find(":status"));
1184 EXPECT_EQ(0, delegate->on_data_sent_count());
1185 EXPECT_EQ(0, delegate->on_data_read_count());
1186 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, delegate->error());
1187
1188 // If stream is destroyed, do not call into stream.
1189 if (!GetParam())
1190 return;
1191 EXPECT_EQ(0, delegate->GetTotalSentBytes());
1192 EXPECT_EQ(0, delegate->GetTotalReceivedBytes());
1193 EXPECT_EQ(kProtoUnknown, delegate->GetProtocol());
1194 }
1195
1196 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698