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

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

Issue 1856073002: Coalesce small buffers in net::BidirectionalStream (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address Andrei's comments Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/http/bidirectional_stream.h" 5 #include "net/http/bidirectional_stream.h"
6 6
7 #include "base/macros.h" 7 #include "base/macros.h"
8 #include "base/memory/scoped_ptr.h" 8 #include "base/memory/scoped_ptr.h"
9 #include "base/run_loop.h" 9 #include "base/run_loop.h"
10 #include "base/strings/string_number_conversions.h" 10 #include "base/strings/string_number_conversions.h"
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
47 scoped_ptr<base::Timer> timer) 47 scoped_ptr<base::Timer> timer)
48 : read_buf_(read_buf), 48 : read_buf_(read_buf),
49 read_buf_len_(read_buf_len), 49 read_buf_len_(read_buf_len),
50 timer_(std::move(timer)), 50 timer_(std::move(timer)),
51 loop_(nullptr), 51 loop_(nullptr),
52 error_(OK), 52 error_(OK),
53 on_data_read_count_(0), 53 on_data_read_count_(0),
54 on_data_sent_count_(0), 54 on_data_sent_count_(0),
55 do_not_start_read_(false), 55 do_not_start_read_(false),
56 run_until_completion_(false), 56 run_until_completion_(false),
57 not_expect_callback_(false) {} 57 not_expect_callback_(false),
58 disable_auto_flush_(false) {}
58 59
59 ~TestDelegateBase() override {} 60 ~TestDelegateBase() override {}
60 61
61 void OnHeadersSent() override { CHECK(!not_expect_callback_); } 62 void OnStreamReady() override {
63 if (callback_.is_null())
64 return;
65 callback_.Run(OK);
66 }
62 67
63 void OnHeadersReceived(const SpdyHeaderBlock& response_headers) override { 68 void OnHeadersReceived(const SpdyHeaderBlock& response_headers) override {
64 CHECK(!not_expect_callback_); 69 CHECK(!not_expect_callback_);
65 70
66 response_headers_ = response_headers; 71 response_headers_ = response_headers;
67 if (!do_not_start_read_) 72 if (!do_not_start_read_)
68 StartOrContinueReading(); 73 StartOrContinueReading();
69 } 74 }
70 75
71 void OnDataRead(int bytes_read) override { 76 void OnDataRead(int bytes_read) override {
(...skipping 23 matching lines...) Expand all
95 void OnFailed(int error) override { 100 void OnFailed(int error) override {
96 CHECK(!not_expect_callback_); 101 CHECK(!not_expect_callback_);
97 CHECK_EQ(OK, error_); 102 CHECK_EQ(OK, error_);
98 CHECK_NE(OK, error); 103 CHECK_NE(OK, error);
99 104
100 error_ = error; 105 error_ = error;
101 if (run_until_completion_) 106 if (run_until_completion_)
102 loop_->Quit(); 107 loop_->Quit();
103 } 108 }
104 109
110 void DisableAutoFlush() { disable_auto_flush_ = true; }
111
105 void Start(scoped_ptr<BidirectionalStreamRequestInfo> request_info, 112 void Start(scoped_ptr<BidirectionalStreamRequestInfo> request_info,
106 HttpNetworkSession* session) { 113 HttpNetworkSession* session) {
107 stream_.reset(new BidirectionalStream(std::move(request_info), session, 114 stream_.reset(new BidirectionalStream(std::move(request_info), session,
108 this, std::move(timer_))); 115 disable_auto_flush_, this,
116 std::move(timer_)));
109 if (run_until_completion_) 117 if (run_until_completion_)
110 loop_->Run(); 118 loop_->Run();
111 } 119 }
120
121 void Start(scoped_ptr<BidirectionalStreamRequestInfo> request_info,
122 HttpNetworkSession* session,
123 const CompletionCallback& cb) {
124 callback_ = cb;
125 stream_.reset(new BidirectionalStream(std::move(request_info), session,
126 disable_auto_flush_, this,
127 std::move(timer_)));
128 if (run_until_completion_)
129 loop_->Run();
130 }
112 131
113 void SendData(IOBuffer* data, int length, bool end_of_stream) { 132 void SendData(IOBuffer* data, int length, bool end_of_stream) {
114 not_expect_callback_ = true; 133 not_expect_callback_ = true;
115 stream_->SendData(data, length, end_of_stream); 134 stream_->SendData(data, length, end_of_stream);
116 not_expect_callback_ = false; 135 not_expect_callback_ = false;
117 } 136 }
118 137
138 void SendvData(const std::vector<IOBuffer*>& data,
139 const std::vector<int>& length,
140 bool end_of_stream) {
141 not_expect_callback_ = true;
142 stream_->SendvData(data, length, end_of_stream);
143 not_expect_callback_ = false;
144 }
145
119 // Starts or continues reading data from |stream_| until no more bytes 146 // Starts or continues reading data from |stream_| until no more bytes
120 // can be read synchronously. 147 // can be read synchronously.
121 void StartOrContinueReading() { 148 void StartOrContinueReading() {
122 int rv = ReadData(); 149 int rv = ReadData();
123 while (rv > 0) { 150 while (rv > 0) {
124 rv = ReadData(); 151 rv = ReadData();
125 } 152 }
126 if (run_until_completion_ && rv == 0) 153 if (run_until_completion_ && rv == 0)
127 loop_->Quit(); 154 loop_->Quit();
128 } 155 }
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 SpdyHeaderBlock response_headers_; 210 SpdyHeaderBlock response_headers_;
184 SpdyHeaderBlock trailers_; 211 SpdyHeaderBlock trailers_;
185 int error_; 212 int error_;
186 int on_data_read_count_; 213 int on_data_read_count_;
187 int on_data_sent_count_; 214 int on_data_sent_count_;
188 bool do_not_start_read_; 215 bool do_not_start_read_;
189 bool run_until_completion_; 216 bool run_until_completion_;
190 // This is to ensure that delegate callback is not invoked synchronously when 217 // This is to ensure that delegate callback is not invoked synchronously when
191 // calling into |stream_|. 218 // calling into |stream_|.
192 bool not_expect_callback_; 219 bool not_expect_callback_;
220 bool disable_auto_flush_;
193 221
222 CompletionCallback callback_;
194 DISALLOW_COPY_AND_ASSIGN(TestDelegateBase); 223 DISALLOW_COPY_AND_ASSIGN(TestDelegateBase);
195 }; 224 };
196 225
197 // A delegate that deletes the stream in a particular callback. 226 // A delegate that deletes the stream in a particular callback.
198 class CancelOrDeleteStreamDelegate : public TestDelegateBase { 227 class CancelOrDeleteStreamDelegate : public TestDelegateBase {
199 public: 228 public:
200 // Specifies in which callback the stream can be deleted. 229 // Specifies in which callback the stream can be deleted.
201 enum Phase { 230 enum Phase {
202 ON_HEADERS_RECEIVED, 231 ON_HEADERS_RECEIVED,
203 ON_DATA_READ, 232 ON_DATA_READ,
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after
544 EXPECT_EQ("200", delegate->response_headers().find(":status")->second); 573 EXPECT_EQ("200", delegate->response_headers().find(":status")->second);
545 EXPECT_EQ(2, delegate->on_data_read_count()); 574 EXPECT_EQ(2, delegate->on_data_read_count());
546 EXPECT_EQ(3, delegate->on_data_sent_count()); 575 EXPECT_EQ(3, delegate->on_data_sent_count());
547 EXPECT_EQ(kProtoHTTP2, delegate->GetProtocol()); 576 EXPECT_EQ(kProtoHTTP2, delegate->GetProtocol());
548 EXPECT_EQ(CountWriteBytes(writes, arraysize(writes)), 577 EXPECT_EQ(CountWriteBytes(writes, arraysize(writes)),
549 delegate->GetTotalSentBytes()); 578 delegate->GetTotalSentBytes());
550 EXPECT_EQ(CountReadBytes(reads, arraysize(reads)), 579 EXPECT_EQ(CountReadBytes(reads, arraysize(reads)),
551 delegate->GetTotalReceivedBytes()); 580 delegate->GetTotalReceivedBytes());
552 } 581 }
553 582
583 TEST_F(BidirectionalStreamTest, TestCoalesceSmallDataBuffers) {
584 BufferedSpdyFramer framer(spdy_util_.spdy_version());
585
586 scoped_ptr<SpdySerializedFrame> req(spdy_util_.ConstructSpdyPost(
587 "https://www.example.org", 1, kBodyDataSize * 1, LOWEST, nullptr, 0));
588 std::string body_data = "some really long piece of data";
589 scoped_ptr<SpdySerializedFrame> data_frame1(framer.CreateDataFrame(
590 1, body_data.c_str(), body_data.size(), DATA_FLAG_FIN));
591 MockWrite writes[] = {
592 CreateMockWrite(*req, 0), CreateMockWrite(*data_frame1, 1),
593 };
594
595 scoped_ptr<SpdySerializedFrame> resp(
596 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
597 scoped_ptr<SpdySerializedFrame> response_body_frame1(
598 spdy_util_.ConstructSpdyBodyFrame(1, true));
599 MockRead reads[] = {
600 CreateMockRead(*resp, 2),
601 MockRead(ASYNC, ERR_IO_PENDING, 3), // Force a pause.
602 CreateMockRead(*response_body_frame1, 4), MockRead(ASYNC, 0, 5),
603 };
604
605 HostPortPair host_port_pair("www.example.org", 443);
606 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
607 PRIVACY_MODE_DISABLED);
608 InitSession(reads, arraysize(reads), writes, arraysize(writes), key);
609
610 scoped_ptr<BidirectionalStreamRequestInfo> request_info(
611 new BidirectionalStreamRequestInfo);
612 request_info->method = "POST";
613 request_info->url = GURL("https://www.example.org/");
614 request_info->priority = LOWEST;
615 request_info->extra_headers.SetHeader(net::HttpRequestHeaders::kContentLength,
616 base::SizeTToString(kBodyDataSize * 1));
617
618 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
619 MockTimer* timer = new MockTimer();
620 scoped_ptr<TestDelegateBase> delegate(new TestDelegateBase(
621 read_buffer.get(), kReadBufferSize, make_scoped_ptr(timer)));
622 delegate->set_do_not_start_read(true);
623 delegate->DisableAutoFlush();
624 TestCompletionCallback callback;
625 delegate->Start(std::move(request_info), http_session_.get(),
626 callback.callback());
627 // Wait until the stream is ready.
628 callback.WaitForResult();
629 // Send a DATA frame.
630 scoped_refptr<StringIOBuffer> buf(new StringIOBuffer(body_data.substr(0, 5)));
631 scoped_refptr<StringIOBuffer> buf2(
632 new StringIOBuffer(body_data.substr(5, body_data.size() - 5)));
633 delegate->SendvData({buf.get(), buf2.get()}, {buf->size(), buf2->size()},
634 true);
635 sequenced_data_->RunUntilPaused(); // OnHeadersReceived.
636 // ReadData and it should return asynchronously because no data is buffered.
637 EXPECT_EQ(ERR_IO_PENDING, delegate->ReadData());
638 sequenced_data_->Resume();
639 base::RunLoop().RunUntilIdle();
640 EXPECT_EQ(1, delegate->on_data_sent_count());
641 EXPECT_EQ(1, delegate->on_data_read_count());
642
643 EXPECT_EQ("200", delegate->response_headers().find(":status")->second);
644 EXPECT_EQ(1, delegate->on_data_read_count());
645 EXPECT_EQ(1, delegate->on_data_sent_count());
646 EXPECT_EQ(kProtoHTTP2, delegate->GetProtocol());
647 EXPECT_EQ(CountWriteBytes(writes, arraysize(writes)),
648 delegate->GetTotalSentBytes());
649 EXPECT_EQ(CountReadBytes(reads, arraysize(reads)),
650 delegate->GetTotalReceivedBytes());
651 }
652
554 // Tests that BidirectionalStreamSpdyImpl::OnClose will complete any remaining 653 // Tests that BidirectionalStreamSpdyImpl::OnClose will complete any remaining
555 // read even if the read queue is empty. 654 // read even if the read queue is empty.
556 TEST_F(BidirectionalStreamTest, TestCompleteAsyncRead) { 655 TEST_F(BidirectionalStreamTest, TestCompleteAsyncRead) {
557 scoped_ptr<SpdySerializedFrame> req( 656 scoped_ptr<SpdySerializedFrame> req(
558 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST)); 657 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
559 // Empty DATA frame with an END_STREAM flag. 658 // Empty DATA frame with an END_STREAM flag.
560 scoped_ptr<SpdySerializedFrame> end_stream( 659 scoped_ptr<SpdySerializedFrame> end_stream(
561 spdy_util_.ConstructSpdyBodyFrame(1, nullptr, 0, true)); 660 spdy_util_.ConstructSpdyBodyFrame(1, nullptr, 0, true));
562 661
563 MockWrite writes[] = {CreateMockWrite(*req.get(), 0)}; 662 MockWrite writes[] = {CreateMockWrite(*req.get(), 0)};
(...skipping 697 matching lines...) Expand 10 before | Expand all | Expand 10 after
1261 http_session_->http_server_properties()->GetAlternativeServices( 1360 http_session_->http_server_properties()->GetAlternativeServices(
1262 host_port_pair); 1361 host_port_pair);
1263 ASSERT_EQ(1u, alternative_service_vector.size()); 1362 ASSERT_EQ(1u, alternative_service_vector.size());
1264 EXPECT_EQ(AlternateProtocolFromNextProto(kProtoQUIC1SPDY3), 1363 EXPECT_EQ(AlternateProtocolFromNextProto(kProtoQUIC1SPDY3),
1265 alternative_service_vector[0].protocol); 1364 alternative_service_vector[0].protocol);
1266 EXPECT_EQ("www.example.org", alternative_service_vector[0].host); 1365 EXPECT_EQ("www.example.org", alternative_service_vector[0].host);
1267 EXPECT_EQ(443, alternative_service_vector[0].port); 1366 EXPECT_EQ(443, alternative_service_vector[0].port);
1268 } 1367 }
1269 1368
1270 } // namespace net 1369 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698