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

Side by Side Diff: net/spdy/bidirectional_stream_spdy_job_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: Get rid of Delegate::OnClose 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/spdy/bidirectional_stream_spdy_job.h"
6
7 #include <string>
8
9 #include "base/macros.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/run_loop.h"
12 #include "base/strings/string_piece.h"
13 #include "base/time/time.h"
14 #include "base/timer/mock_timer.h"
15 #include "net/base/net_errors.h"
16 #include "net/http/http_request_info.h"
17 #include "net/http/http_response_headers.h"
18 #include "net/http/http_response_info.h"
19 #include "net/socket/socket_test_util.h"
20 #include "net/spdy/spdy_read_queue.h"
21 #include "net/spdy/spdy_session.h"
22 #include "net/spdy/spdy_test_util_common.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24
25 namespace net {
26
27 namespace {
28
29 const char kBodyData[] = "Body data";
30 const size_t kBodyDataSize = arraysize(kBodyData);
31 // Size of the buffer to be allocated for each read.
32 const size_t kReadBufferSize = 4096;
33 // Size of the small buffer used for each read. This is to test the case where
34 // the entire response body does not fit in one buffer.
35 const size_t kSmallReadBufferSize = 4;
36
37 // Delegate that reads data but does not send any data.
38 class TestDelegateBase : public BidirectionalStreamJob::Delegate {
39 public:
40 TestDelegateBase(base::WeakPtr<SpdySession> session,
41 IOBuffer* read_buf,
42 int read_buf_len)
43 : TestDelegateBase(session,
44 read_buf,
45 read_buf_len,
46 make_scoped_ptr(new base::Timer(false, false))) {}
47
48 TestDelegateBase(base::WeakPtr<SpdySession> session,
49 IOBuffer* read_buf,
50 int read_buf_len,
51 scoped_ptr<base::Timer> timer)
52 : stream_(new BidirectionalStreamSpdyJob(session, timer.Pass())),
53 read_buf_(read_buf),
54 read_buf_len_(read_buf_len),
55 loop_(nullptr),
56 error_(OK),
57 bytes_read_(0),
58 on_read_complete_count_(0),
59 do_not_start_read_(false),
60 run_until_completion_(false) {}
61
62 ~TestDelegateBase() override {}
63
64 void OnRequestHeadersSent() override {}
65
66 void OnHeaders(const SpdyHeaderBlock& response_headers) override {
67 response_headers_ = response_headers;
68 if (!do_not_start_read_)
69 StartOrContinueReading();
70 }
71
72 void OnReadCompleted(int bytes_read) override {
73 on_read_complete_count_++;
74 CHECK_GT(bytes_read, OK);
75 bytes_read_ += bytes_read;
76 data_received_.append(read_buf_->data(), bytes_read);
77 if (!do_not_start_read_)
78 StartOrContinueReading();
79 }
80
81 void OnDataSent() override {}
82
83 void OnTrailers(const SpdyHeaderBlock& trailers) override {
84 trailers_ = trailers;
85 if (run_until_completion_)
86 loop_->Quit();
87 }
88
89 void OnFailed(int error) override {
90 CHECK_NE(OK, error);
91 error_ = error;
92 if (run_until_completion_)
93 loop_->Quit();
94 }
95
96 void Start(const HttpRequestInfo& request,
97 RequestPriority priority,
98 const BoundNetLog& net_log) {
99 stream_->Start(request, priority, net_log, this);
100 if (run_until_completion_)
101 loop_->Run();
102 }
103
104 void SendData(IOBuffer* data, int length, bool end_of_stream) {
105 stream_->SendData(data, length, end_of_stream);
106 }
107
108 // Starts or continues read data from |stream_| until there is no more byte
109 // can be read synchronously.
110 void StartOrContinueReading() {
111 int rv = ReadData();
112 while (rv > 0) {
113 rv = ReadData();
114 }
115 if (run_until_completion_ && rv == 0)
116 loop_->Quit();
117 }
118
119 // Calls ReadData on the |stream_| and updates internal states.
120 int ReadData() {
121 int rv = stream_->ReadData(read_buf_.get(), read_buf_len_);
122 if (rv > 0) {
123 data_received_.append(read_buf_->data(), rv);
124 bytes_read_ += rv;
125 }
126 return rv;
127 }
128
129 // Const getters for internal states.
130 const std::string& data_received() const { return data_received_; }
131 int bytes_read() const { return bytes_read_; }
132 int error() const { return error_; }
133 const SpdyHeaderBlock response_headers() const { return response_headers_; }
134 const SpdyHeaderBlock trailers() const { return trailers_; }
135 int on_read_complete_count() const { return on_read_complete_count_; }
136
137 // Sets whether the delegate should automatically start reading.
138 void set_do_not_start_read(bool do_not_start_read) {
139 do_not_start_read_ = do_not_start_read;
140 }
141 // Sets whether the delegate should wait until the completion of the stream.
142 void SetRunUntilCompletion(bool run_until_completion) {
143 run_until_completion_ = run_until_completion;
144 loop_.reset(new base::RunLoop);
145 }
146
147 protected:
148 // Cancels |stream_|.
149 void CancelStream() { stream_->Cancel(); }
150 // Quits |loop_|.
151 void QuitLoop() { loop_->Quit(); }
152
153 private:
154 scoped_ptr<BidirectionalStreamSpdyJob> stream_;
155 scoped_refptr<IOBuffer> read_buf_;
156 int read_buf_len_;
157 std::string data_received_;
158 scoped_ptr<base::RunLoop> loop_;
159 SpdyHeaderBlock response_headers_;
160 SpdyHeaderBlock trailers_;
161 int error_;
162 int bytes_read_;
163 int on_read_complete_count_;
164 bool do_not_start_read_;
165 bool run_until_completion_;
166
167 DISALLOW_COPY_AND_ASSIGN(TestDelegateBase);
168 };
169
170 // A delegate that sends data after request headers are sent.
171 class SendDataDelegate : public TestDelegateBase {
172 public:
173 SendDataDelegate(base::WeakPtr<SpdySession> session,
174 IOBuffer* buf,
175 int buf_len,
176 base::StringPiece data)
177 : TestDelegateBase(session, buf, buf_len), data_(data) {}
178
179 ~SendDataDelegate() override {}
180
181 void OnRequestHeadersSent() override {
182 TestDelegateBase::OnRequestHeadersSent();
183 if (data_.data()) {
184 scoped_refptr<StringIOBuffer> buf(new StringIOBuffer(data_.as_string()));
185 SendData(buf.get(), buf->size(), NO_MORE_DATA_TO_SEND);
186 }
187 }
188
189 private:
190 base::StringPiece data_;
191
192 DISALLOW_COPY_AND_ASSIGN(SendDataDelegate);
193 };
194
195 // A delegate that cancels the request after response headers are received.
196 class CancelStreamDelegate : public TestDelegateBase {
197 public:
198 CancelStreamDelegate(base::WeakPtr<SpdySession> session,
199 IOBuffer* buf,
200 int buf_len)
201 : TestDelegateBase(session, buf, buf_len) {}
202
203 ~CancelStreamDelegate() override {}
204
205 void OnHeaders(const SpdyHeaderBlock& response_headers) override {
206 TestDelegateBase::OnHeaders(response_headers);
207 CancelStream();
208 QuitLoop();
209 }
210
211 void OnDataSent() override { NOTREACHED(); }
212
213 void OnReadCompleted(int bytes_read) override { NOTREACHED(); }
214
215 void OnTrailers(const SpdyHeaderBlock& trailers) override { NOTREACHED(); }
216
217 void OnFailed(int error) override { NOTREACHED(); }
218
219 private:
220 DISALLOW_COPY_AND_ASSIGN(CancelStreamDelegate);
221 };
222
223 // A Timer that does not start a delayed task unless the timer is fired.
224 class MockTimer : public base::MockTimer {
225 public:
226 MockTimer() : base::MockTimer(false, false) {}
227 ~MockTimer() override {}
228
229 void Start(const tracked_objects::Location& posted_from,
230 base::TimeDelta delay,
231 const base::Closure& user_task) override {
232 // Sets a maximum delay, so the timer does not fire unless it is told to.
233 base::TimeDelta infinite_delay = base::TimeDelta::Max();
234 base::MockTimer::Start(posted_from, infinite_delay, user_task);
235 }
236
237 private:
238 DISALLOW_COPY_AND_ASSIGN(MockTimer);
239 };
240
241 } // namespace
242
243 class BidirectionalStreamSpdyJobTest : public testing::Test {
244 public:
245 BidirectionalStreamSpdyJobTest()
246 : spdy_util_(kProtoHTTP2, false), session_deps_(kProtoHTTP2) {}
247
248 protected:
249 void TearDown() override {
250 if (sequenced_data_) {
251 EXPECT_TRUE(sequenced_data_->AllReadDataConsumed());
252 EXPECT_TRUE(sequenced_data_->AllWriteDataConsumed());
253 }
254 if (deterministic_data_) {
255 EXPECT_TRUE(deterministic_data_->AllReadDataConsumed());
256 EXPECT_TRUE(deterministic_data_->AllWriteDataConsumed());
257 }
258 }
259
260 // Initializes the session using SequencedSocketData.
261 void InitSession(MockRead* reads,
262 size_t reads_count,
263 MockWrite* writes,
264 size_t writes_count,
265 const SpdySessionKey& key) {
266 sequenced_data_.reset(
267 new SequencedSocketData(reads, reads_count, writes, writes_count));
268 session_deps_.socket_factory->AddSocketDataProvider(sequenced_data_.get());
269 http_session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
270 session_ =
271 CreateInsecureSpdySession(http_session_.get(), key, BoundNetLog());
272 }
273
274 // Initializes the session using DeterministicSocketData.
275 void InitSessionDeterministic(MockRead* reads,
276 size_t reads_count,
277 MockWrite* writes,
278 size_t writes_count,
279 const SpdySessionKey& key) {
280 MockConnect connect_data(SYNCHRONOUS, OK);
281 deterministic_data_.reset(
282 new DeterministicSocketData(reads, reads_count, writes, writes_count));
283 deterministic_data_->set_connect_data(connect_data);
284 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
285 deterministic_data_.get());
286 http_session_ =
287 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
288 session_ =
289 CreateInsecureSpdySession(http_session_.get(), key, BoundNetLog());
290 }
291
292 SpdyTestUtil spdy_util_;
293 SpdySessionDependencies session_deps_;
294 scoped_ptr<SequencedSocketData> sequenced_data_;
295 scoped_ptr<DeterministicSocketData> deterministic_data_;
296 scoped_ptr<HttpNetworkSession> http_session_;
297 base::WeakPtr<SpdySession> session_;
298 };
299
300 // Simulates user calling ReadData after END_STREAM has been received in
301 // BidirectionalStreamSpdyJob.
302 TEST_F(BidirectionalStreamSpdyJobTest, TestReadDataAfterClose) {
303 scoped_ptr<SpdyFrame> req(
304 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
305 MockWrite writes[] = {
306 CreateMockWrite(*req.get(), 0),
307 };
308
309 const char* const kExtraResponseHeaders[] = {"header-name", "header-value"};
310
311 scoped_ptr<SpdyFrame> resp(
312 spdy_util_.ConstructSpdyGetSynReply(kExtraResponseHeaders, 1, 1));
313
314 scoped_ptr<SpdyFrame> body_frame(spdy_util_.ConstructSpdyBodyFrame(1, false));
315 // Last body frame has END_STREAM flag set.
316 scoped_ptr<SpdyFrame> last_body_frame(
317 spdy_util_.ConstructSpdyBodyFrame(1, true));
318
319 MockRead reads[] = {
320 CreateMockRead(*resp, 1), CreateMockRead(*body_frame, 2),
321 CreateMockRead(*body_frame, 3), CreateMockRead(*last_body_frame, 4),
322 MockRead(SYNCHRONOUS, 0, 5),
323 };
324
325 HostPortPair host_port_pair("www.example.org", 80);
326 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
327 PRIVACY_MODE_DISABLED);
328 InitSessionDeterministic(reads, arraysize(reads), writes, arraysize(writes),
329 key);
330
331 HttpRequestInfo request;
332 request.method = "GET";
333 request.url = GURL("http://www.example.org/");
334
335 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
336 MockTimer* timer = new MockTimer();
337 scoped_ptr<TestDelegateBase> delegate(new TestDelegateBase(
338 session_, read_buffer.get(), kReadBufferSize, make_scoped_ptr(timer)));
339 delegate->set_do_not_start_read(true);
340 BoundNetLog net_log;
341 delegate->Start(request, DEFAULT_PRIORITY, net_log);
342 // Deliver header frame.
343 deterministic_data_->RunFor(2);
344 base::RunLoop().RunUntilIdle();
345 EXPECT_FALSE(timer->IsRunning());
346 // ReadData returns asynchronously because no data is buffered.
347 int rv = delegate->ReadData();
348 EXPECT_EQ(ERR_IO_PENDING, rv);
349 // Deliver a data frame.
350 deterministic_data_->RunFor(1);
351 base::RunLoop().RunUntilIdle();
352 timer->Fire();
353 // Asynchronous completion callback is invoke.
354 EXPECT_EQ(1, delegate->on_read_complete_count());
355 EXPECT_EQ(kUploadDataSize * 1, delegate->bytes_read());
356
357 // Deliver the rest. Note that user has not called a second ReadData.
358 deterministic_data_->RunFor(4);
359 base::RunLoop().RunUntilIdle();
360 // ReadData now. Read should complete synchronously.
361 rv = delegate->ReadData();
362 EXPECT_EQ(kUploadDataSize * 2, rv);
363 rv = delegate->ReadData();
364 EXPECT_EQ(OK, rv); // EOF.
365 EXPECT_EQ(1, delegate->on_read_complete_count());
366 }
367
368 TEST_F(BidirectionalStreamSpdyJobTest, TestBuffering) {
369 scoped_ptr<SpdyFrame> req(
370 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
371 MockWrite writes[] = {
372 CreateMockWrite(*req.get(), 0),
373 };
374
375 const char* const kExtraResponseHeaders[] = {"header-name", "header-value"};
376
377 scoped_ptr<SpdyFrame> resp(
378 spdy_util_.ConstructSpdyGetSynReply(kExtraResponseHeaders, 1, 1));
379
380 scoped_ptr<SpdyFrame> body_frame(spdy_util_.ConstructSpdyBodyFrame(1, false));
381 // Last body frame has END_STREAM flag set.
382 scoped_ptr<SpdyFrame> last_body_frame(
383 spdy_util_.ConstructSpdyBodyFrame(1, true));
384
385 MockRead reads[] = {
386 CreateMockRead(*resp, 1), CreateMockRead(*body_frame, 2),
387 CreateMockRead(*body_frame, 3), CreateMockRead(*last_body_frame, 4),
388 MockRead(SYNCHRONOUS, 0, 5),
389 };
390
391 HostPortPair host_port_pair("www.example.org", 80);
392 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
393 PRIVACY_MODE_DISABLED);
394 InitSessionDeterministic(reads, arraysize(reads), writes, arraysize(writes),
395 key);
396
397 HttpRequestInfo request;
398 request.method = "GET";
399 request.url = GURL("http://www.example.org/");
400
401 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
402 MockTimer* timer = new MockTimer();
403 scoped_ptr<TestDelegateBase> delegate(new TestDelegateBase(
404 session_, read_buffer.get(), kReadBufferSize, make_scoped_ptr(timer)));
405 BoundNetLog net_log;
406 delegate->Start(request, DEFAULT_PRIORITY, net_log);
407 // Deliver two data frames together.
408 deterministic_data_->RunFor(4);
409 base::RunLoop().RunUntilIdle();
410 EXPECT_TRUE(timer->IsRunning());
411 timer->Fire();
412 base::RunLoop().RunUntilIdle();
413 // This should trigger |more_read_data_pending_| to execute the task at a
414 // later time, and Delegate::OnReadComplete should not have been called.
415 EXPECT_TRUE(timer->IsRunning());
416 EXPECT_EQ(0, delegate->on_read_complete_count());
417
418 // Fire the timer now, the two data frame should be combined into one
419 // single Delegate::OnReadComplete callback.
420 timer->Fire();
421 base::RunLoop().RunUntilIdle();
422 EXPECT_EQ(1, delegate->on_read_complete_count());
423 EXPECT_EQ(kUploadDataSize * 2, delegate->bytes_read());
424
425 // Read last data frame and EOF. There will be an additional
426 // Delegate::OnReadComplete callback.
427 deterministic_data_->RunFor(2);
428 EXPECT_EQ(2, delegate->on_read_complete_count());
429 const SpdyHeaderBlock response_headers = delegate->response_headers();
430 EXPECT_EQ("200", response_headers.find(":status")->second);
431 EXPECT_EQ("header-value", response_headers.find("header-name")->second);
432
433 EXPECT_EQ(kUploadDataSize * 3, delegate->bytes_read());
434 }
435
436 TEST_F(BidirectionalStreamSpdyJobTest, TestBufferingWithTrailers) {
437 scoped_ptr<SpdyFrame> req(
438 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
439 MockWrite writes[] = {
440 CreateMockWrite(*req.get(), 0),
441 };
442
443 const char* const kExtraResponseHeaders[] = {"header-name", "header-value"};
444
445 scoped_ptr<SpdyFrame> resp(
446 spdy_util_.ConstructSpdyGetSynReply(kExtraResponseHeaders, 1, 1));
447
448 scoped_ptr<SpdyFrame> body_frame(spdy_util_.ConstructSpdyBodyFrame(1, false));
449
450 const char* const kTrailers[] = {"foo", "bar"};
451 scoped_ptr<SpdyFrame> trailers(
452 spdy_util_.ConstructSpdyHeaderFrame(1, kTrailers, 1, true));
453
454 MockRead reads[] = {
455 CreateMockRead(*resp, 1), CreateMockRead(*body_frame, 2),
456 CreateMockRead(*body_frame, 3), CreateMockRead(*body_frame, 4),
457 CreateMockRead(*trailers, 5), MockRead(SYNCHRONOUS, 0, 6),
458 };
459
460 HostPortPair host_port_pair("www.example.org", 80);
461 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
462 PRIVACY_MODE_DISABLED);
463 InitSessionDeterministic(reads, arraysize(reads), writes, arraysize(writes),
464 key);
465
466 HttpRequestInfo request;
467 request.method = "GET";
468 request.url = GURL("http://www.example.org/");
469
470 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
471 MockTimer* timer = new MockTimer();
472 scoped_ptr<TestDelegateBase> delegate(new TestDelegateBase(
473 session_, read_buffer.get(), kReadBufferSize, make_scoped_ptr(timer)));
474 BoundNetLog net_log;
475 delegate->Start(request, DEFAULT_PRIORITY, net_log);
476 // Deliver all three data frames together.
477 deterministic_data_->RunFor(5);
478 base::RunLoop().RunUntilIdle();
479 EXPECT_TRUE(timer->IsRunning());
480 timer->Fire();
481 base::RunLoop().RunUntilIdle();
482 // This should trigger |more_read_data_pending_| to execute the task at a
483 // later time, and Delegate::OnReadComplete should not have been called.
484 EXPECT_TRUE(timer->IsRunning());
485 EXPECT_EQ(0, delegate->on_read_complete_count());
486
487 // Deliver trailers. Remaining read should be completed, since OnClose is
488 // called right after OnTrailers. The three data frames should be delivered
489 // in a single OnReadCompleted callback.
490 deterministic_data_->RunFor(2);
491 base::RunLoop().RunUntilIdle();
492 EXPECT_FALSE(timer->IsRunning());
493 EXPECT_EQ(1, delegate->on_read_complete_count());
494 EXPECT_EQ(kUploadDataSize * 3, delegate->bytes_read());
495 const SpdyHeaderBlock response_headers = delegate->response_headers();
496 EXPECT_EQ("200", response_headers.find(":status")->second);
497 EXPECT_EQ("header-value", response_headers.find("header-name")->second);
498 }
499
500 TEST_F(BidirectionalStreamSpdyJobTest, SendGetRequest) {
501 scoped_ptr<SpdyFrame> req(
502 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
503 MockWrite writes[] = {
504 CreateMockWrite(*req.get(), 0),
505 };
506
507 const char* const kExtraResponseHeaders[] = {"header-name", "header-value"};
508
509 scoped_ptr<SpdyFrame> resp(
510 spdy_util_.ConstructSpdyGetSynReply(kExtraResponseHeaders, 1, 1));
511
512 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
513
514 const char* const kTrailers[] = {"foo", "bar"};
515 scoped_ptr<SpdyFrame> trailers(
516 spdy_util_.ConstructSpdyHeaderFrame(1, kTrailers, 1, true));
517
518 MockRead reads[] = {
519 CreateMockRead(*resp, 1), CreateMockRead(*body, 2),
520 CreateMockRead(*trailers, 3), MockRead(SYNCHRONOUS, 0, 4),
521 };
522
523 HostPortPair host_port_pair("www.example.org", 80);
524 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
525 PRIVACY_MODE_DISABLED);
526 InitSession(reads, arraysize(reads), writes, arraysize(writes), key);
527
528 HttpRequestInfo request;
529 request.method = "GET";
530 request.url = GURL("http://www.example.org/");
531
532 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
533 scoped_ptr<TestDelegateBase> delegate(
534 new TestDelegateBase(session_, read_buffer.get(), kReadBufferSize));
535 delegate->SetRunUntilCompletion(true);
536 BoundNetLog net_log;
537 delegate->Start(request, DEFAULT_PRIORITY, net_log);
538 const SpdyHeaderBlock response_headers = delegate->response_headers();
539 EXPECT_EQ("200", response_headers.find(":status")->second);
540 EXPECT_EQ("header-value", response_headers.find("header-name")->second);
541 EXPECT_EQ(kUploadDataSize, delegate->bytes_read());
542 EXPECT_EQ(kUploadData, delegate->data_received());
543 EXPECT_EQ("bar", delegate->trailers().find("foo")->second);
544 }
545
546 TEST_F(BidirectionalStreamSpdyJobTest, SendGetRequestSmallReadBuffer) {
547 scoped_ptr<SpdyFrame> req(
548 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
549 MockWrite writes[] = {
550 CreateMockWrite(*req.get(), 0),
551 };
552
553 const char* const kExtraResponseHeaders[] = {"header-name", "header-value"};
554
555 scoped_ptr<SpdyFrame> resp(
556 spdy_util_.ConstructSpdyGetSynReply(kExtraResponseHeaders, 1, 1));
557
558 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
559
560 const char* const kTrailers[] = {"foo", "bar"};
561 scoped_ptr<SpdyFrame> trailers(
562 spdy_util_.ConstructSpdyHeaderFrame(1, kTrailers, 1, true));
563
564 MockRead reads[] = {
565 CreateMockRead(*resp, 1), CreateMockRead(*body, 2),
566 CreateMockRead(*trailers, 3), MockRead(SYNCHRONOUS, 0, 4),
567 };
568
569 HostPortPair host_port_pair("www.example.org", 80);
570 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
571 PRIVACY_MODE_DISABLED);
572 InitSession(reads, arraysize(reads), writes, arraysize(writes), key);
573
574 HttpRequestInfo request;
575 request.method = "GET";
576 request.url = GURL("http://www.example.org/");
577
578 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kSmallReadBufferSize));
579 scoped_ptr<TestDelegateBase> delegate(
580 new TestDelegateBase(session_, read_buffer.get(), kSmallReadBufferSize));
581 delegate->SetRunUntilCompletion(true);
582 BoundNetLog net_log;
583 delegate->Start(request, DEFAULT_PRIORITY, net_log);
584 const SpdyHeaderBlock response_headers = delegate->response_headers();
585 EXPECT_EQ("200", response_headers.find(":status")->second);
586 EXPECT_EQ("header-value", response_headers.find("header-name")->second);
587 EXPECT_EQ(kUploadDataSize, delegate->bytes_read());
588 EXPECT_EQ(kUploadData, delegate->data_received());
589 EXPECT_EQ("bar", delegate->trailers().find("foo")->second);
590 }
591
592 TEST_F(BidirectionalStreamSpdyJobTest, SendGetRequestNoTrailers) {
593 scoped_ptr<SpdyFrame> req(
594 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
595 MockWrite writes[] = {
596 CreateMockWrite(*req.get(), 0),
597 };
598
599 const char* const kExtraResponseHeaders[] = {"header-name", "header-value"};
600
601 scoped_ptr<SpdyFrame> resp(
602 spdy_util_.ConstructSpdyGetSynReply(kExtraResponseHeaders, 1, 1));
603
604 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
605
606 MockRead reads[] = {
607 CreateMockRead(*resp, 1), CreateMockRead(*body, 2),
608 MockRead(SYNCHRONOUS, 0, 3),
609 };
610
611 HostPortPair host_port_pair("www.example.org", 80);
612 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
613 PRIVACY_MODE_DISABLED);
614 InitSession(reads, arraysize(reads), writes, arraysize(writes), key);
615
616 HttpRequestInfo request;
617 request.method = "GET";
618 request.url = GURL("http://www.example.org/");
619
620 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
621 scoped_ptr<TestDelegateBase> delegate(
622 new TestDelegateBase(session_, read_buffer.get(), kReadBufferSize));
623 delegate->SetRunUntilCompletion(true);
624 BoundNetLog net_log;
625 delegate->Start(request, DEFAULT_PRIORITY, net_log);
626 const SpdyHeaderBlock response_headers = delegate->response_headers();
627 EXPECT_EQ("200", response_headers.find(":status")->second);
628 EXPECT_EQ("header-value", response_headers.find("header-name")->second);
629 EXPECT_EQ(kUploadDataSize, delegate->bytes_read());
630 EXPECT_EQ(kUploadData, delegate->data_received());
631 }
632
633 TEST_F(BidirectionalStreamSpdyJobTest, CancelStream) {
634 scoped_ptr<SpdyFrame> req(
635 spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, LOWEST, true));
636 scoped_ptr<SpdyFrame> rst(
637 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
638 MockWrite writes[] = {
639 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 2),
640 };
641
642 const char* const kExtraResponseHeaders[] = {"header-name", "header-value"};
643
644 scoped_ptr<SpdyFrame> resp(
645 spdy_util_.ConstructSpdyGetSynReply(kExtraResponseHeaders, 1, 1));
646
647 MockRead reads[] = {
648 CreateMockRead(*resp, 1), MockRead(ASYNC, 0, 3),
649 };
650
651 HostPortPair host_port_pair("www.example.org", 80);
652 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
653 PRIVACY_MODE_DISABLED);
654 InitSession(reads, arraysize(reads), writes, arraysize(writes), key);
655
656 HttpRequestInfo request;
657 request.method = "GET";
658 request.url = GURL("http://www.example.org/");
659
660 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
661 scoped_ptr<CancelStreamDelegate> delegate(
662 new CancelStreamDelegate(session_, read_buffer.get(), kReadBufferSize));
663 delegate->SetRunUntilCompletion(true);
664 BoundNetLog net_log;
665 delegate->Start(request, DEFAULT_PRIORITY, net_log);
666 // Makes sure delegate does not get called.
667 base::RunLoop().RunUntilIdle();
668 const SpdyHeaderBlock response_headers = delegate->response_headers();
669 EXPECT_EQ("200", response_headers.find(":status")->second);
670 EXPECT_EQ("header-value", response_headers.find("header-name")->second);
671 EXPECT_EQ(0, delegate->bytes_read());
672 }
673
674 TEST_F(BidirectionalStreamSpdyJobTest, SendPostRequest) {
675 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
676
677 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(nullptr, 0));
678 scoped_ptr<SpdyFrame> body(
679 framer.CreateDataFrame(1, kBodyData, kBodyDataSize, DATA_FLAG_FIN));
680 MockWrite writes[] = {
681 CreateMockWrite(*req, 0), // request
682 CreateMockWrite(*body, 1), // POST upload frame
683 };
684 const char* const kExtraResponseHeaders[] = {"header-name", "header-value"};
685 scoped_ptr<SpdyFrame> resp(
686 spdy_util_.ConstructSpdyPostSynReply(kExtraResponseHeaders, 1));
687
688 scoped_ptr<SpdyFrame> resp_data(
689 framer.CreateDataFrame(1, kBodyData, kBodyDataSize, DATA_FLAG_NONE));
690
691 const char* const kExtraHeaders[] = {"foo", "bar"};
692 scoped_ptr<SpdyFrame> trailers(
693 spdy_util_.ConstructSpdyHeaderFrame(1, kExtraHeaders, 1, true));
694
695 MockRead reads[] = {
696 CreateMockRead(*resp, 2), CreateMockRead(*resp_data, 3),
697 CreateMockRead(*trailers, 4), MockRead(SYNCHRONOUS, 0, 5) // EOF
698 };
699
700 HostPortPair host_port_pair("www.example.org", 80);
701 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
702 PRIVACY_MODE_DISABLED);
703 InitSession(reads, arraysize(reads), writes, arraysize(writes), key);
704
705 HttpRequestInfo request;
706 request.method = "POST";
707 request.url = GURL("http://www.example.org/");
708
709 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
710 scoped_ptr<SendDataDelegate> delegate(
711 new SendDataDelegate(session_, read_buffer.get(), kReadBufferSize,
712 base::StringPiece(kBodyData, kBodyDataSize)));
713 delegate->SetRunUntilCompletion(true);
714 BoundNetLog net_log;
715 delegate->Start(request, DEFAULT_PRIORITY, net_log);
716
717 const SpdyHeaderBlock response_headers = delegate->response_headers();
718 EXPECT_EQ("200", response_headers.find(":status")->second);
719 EXPECT_EQ("header-value", response_headers.find("header-name")->second);
720 EXPECT_EQ(static_cast<int>(kBodyDataSize), delegate->bytes_read());
721 EXPECT_EQ(std::string(kBodyData, kBodyDataSize), delegate->data_received());
722 EXPECT_EQ("bar", delegate->trailers().find("foo")->second);
723 }
724
725 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698