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

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

Powered by Google App Engine
This is Rietveld 408576698