blob: 86ffbfda8e012c00bc7e1f059a6a4cff9a213307 [file] [log] [blame]
xunjieli707f8952016-06-06 15:22:061// Copyright 2016 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_impl.h"
6
7#include <memory>
8#include <string>
9
10#include "base/macros.h"
11#include "base/memory/ptr_util.h"
12#include "base/run_loop.h"
13#include "base/strings/string_number_conversions.h"
14#include "base/strings/string_piece.h"
15#include "base/time/time.h"
16#include "base/timer/mock_timer.h"
17#include "net/base/net_errors.h"
xunjieli707f8952016-06-06 15:22:0618#include "net/http/http_request_info.h"
19#include "net/http/http_response_headers.h"
20#include "net/http/http_response_info.h"
21#include "net/log/net_log.h"
22#include "net/log/test_net_log.h"
23#include "net/socket/socket_test_util.h"
24#include "net/spdy/spdy_session.h"
25#include "net/spdy/spdy_test_util_common.h"
26#include "net/test/cert_test_util.h"
rsleevia69c79a2016-06-22 03:28:4327#include "net/test/test_data_directory.h"
xunjieli707f8952016-06-06 15:22:0628#include "testing/gtest/include/gtest/gtest.h"
29
30namespace net {
31
32namespace {
33
34const char kBodyData[] = "Body data";
35const size_t kBodyDataSize = arraysize(kBodyData);
36// Size of the buffer to be allocated for each read.
37const size_t kReadBufferSize = 4096;
38
39class TestDelegateBase : public BidirectionalStreamImpl::Delegate {
40 public:
41 TestDelegateBase(base::WeakPtr<SpdySession> session,
42 IOBuffer* read_buf,
43 int read_buf_len)
44 : stream_(new BidirectionalStreamSpdyImpl(session)),
45 read_buf_(read_buf),
46 read_buf_len_(read_buf_len),
47 loop_(nullptr),
48 error_(OK),
49 bytes_read_(0),
50 on_data_read_count_(0),
51 on_data_sent_count_(0),
52 do_not_start_read_(false),
53 run_until_completion_(false),
54 not_expect_callback_(false),
55 on_failed_called_(false) {}
56
57 ~TestDelegateBase() override {}
58
59 void OnStreamReady(bool request_headers_sent) override {
60 CHECK(!on_failed_called_);
61 }
62
63 void OnHeadersReceived(const SpdyHeaderBlock& response_headers) override {
64 CHECK(!on_failed_called_);
65 CHECK(!not_expect_callback_);
bnc94893a72016-06-30 13:45:2566 response_headers_ = response_headers.Clone();
xunjieli707f8952016-06-06 15:22:0667 if (!do_not_start_read_)
68 StartOrContinueReading();
69 }
70
71 void OnDataRead(int bytes_read) override {
72 CHECK(!on_failed_called_);
73 CHECK(!not_expect_callback_);
74 on_data_read_count_++;
75 CHECK_GE(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 {
83 CHECK(!on_failed_called_);
84 CHECK(!not_expect_callback_);
85 on_data_sent_count_++;
86 }
87
88 void OnTrailersReceived(const SpdyHeaderBlock& trailers) override {
89 CHECK(!on_failed_called_);
bnc94893a72016-06-30 13:45:2590 trailers_ = trailers.Clone();
xunjieli707f8952016-06-06 15:22:0691 if (run_until_completion_)
92 loop_->Quit();
93 }
94
95 void OnFailed(int error) override {
96 CHECK(!on_failed_called_);
97 CHECK(!not_expect_callback_);
98 CHECK_NE(OK, error);
99 error_ = error;
100 on_failed_called_ = true;
101 if (run_until_completion_)
102 loop_->Quit();
103 }
104
105 void Start(const BidirectionalStreamRequestInfo* request,
106 const BoundNetLog& net_log) {
107 stream_->Start(request, net_log,
108 /*send_request_headers_automatically=*/false, this,
109 base::WrapUnique(new base::Timer(false, false)));
110 not_expect_callback_ = false;
111 }
112
113 void SendData(IOBuffer* data, int length, bool end_of_stream) {
114 not_expect_callback_ = true;
115 stream_->SendData(data, length, end_of_stream);
116 not_expect_callback_ = false;
117 }
118
119 void SendvData(const std::vector<scoped_refptr<IOBuffer>>& data,
120 const std::vector<int>& length,
121 bool end_of_stream) {
122 not_expect_callback_ = true;
123 stream_->SendvData(data, length, end_of_stream);
124 not_expect_callback_ = false;
125 }
126
127 // Sets whether the delegate should wait until the completion of the stream.
128 void SetRunUntilCompletion(bool run_until_completion) {
129 run_until_completion_ = run_until_completion;
130 loop_.reset(new base::RunLoop);
131 }
132
133 // Starts or continues read data from |stream_| until there is no more
134 // byte can be read synchronously.
135 void StartOrContinueReading() {
136 int rv = ReadData();
137 while (rv > 0) {
138 rv = ReadData();
139 }
140 if (run_until_completion_ && rv == 0)
141 loop_->Quit();
142 }
143
144 // Calls ReadData on the |stream_| and updates internal states.
145 int ReadData() {
146 int rv = stream_->ReadData(read_buf_.get(), read_buf_len_);
147 if (rv > 0) {
148 data_received_.append(read_buf_->data(), rv);
149 bytes_read_ += rv;
150 }
151 return rv;
152 }
153
154 NextProto GetProtocol() const { return stream_->GetProtocol(); }
155
156 int64_t GetTotalReceivedBytes() const {
157 return stream_->GetTotalReceivedBytes();
158 }
159
160 int64_t GetTotalSentBytes() const { return stream_->GetTotalSentBytes(); }
161
162 // Const getters for internal states.
163 const std::string& data_received() const { return data_received_; }
164 int bytes_read() const { return bytes_read_; }
165 int error() const { return error_; }
bnc94893a72016-06-30 13:45:25166 const SpdyHeaderBlock& response_headers() const { return response_headers_; }
167 const SpdyHeaderBlock& trailers() const { return trailers_; }
xunjieli707f8952016-06-06 15:22:06168 int on_data_read_count() const { return on_data_read_count_; }
169 int on_data_sent_count() const { return on_data_sent_count_; }
170 bool on_failed_called() const { return on_failed_called_; }
171
172 // Sets whether the delegate should automatically start reading.
173 void set_do_not_start_read(bool do_not_start_read) {
174 do_not_start_read_ = do_not_start_read;
175 }
176
177 // Cancels |stream_|.
178 void CancelStream() { stream_->Cancel(); }
179
180 private:
181 std::unique_ptr<BidirectionalStreamSpdyImpl> stream_;
182 scoped_refptr<IOBuffer> read_buf_;
183 int read_buf_len_;
184 std::string data_received_;
185 std::unique_ptr<base::RunLoop> loop_;
186 SpdyHeaderBlock response_headers_;
187 SpdyHeaderBlock trailers_;
188 int error_;
189 int bytes_read_;
190 int on_data_read_count_;
191 int on_data_sent_count_;
192 bool do_not_start_read_;
193 bool run_until_completion_;
194 bool not_expect_callback_;
195 bool on_failed_called_;
196
197 DISALLOW_COPY_AND_ASSIGN(TestDelegateBase);
198};
199
200} // namespace
201
202class BidirectionalStreamSpdyImplTest : public testing::Test {
203 public:
204 BidirectionalStreamSpdyImplTest()
205 : spdy_util_(kProtoHTTP2, true),
206 session_deps_(kProtoHTTP2),
bnc3d9035b32016-06-30 18:18:48207 default_url_(kDefaultUrl),
208 host_port_pair_(HostPortPair::FromURL(default_url_)),
209 key_(host_port_pair_, ProxyServer::Direct(), PRIVACY_MODE_DISABLED),
xunjieli707f8952016-06-06 15:22:06210 ssl_data_(SSLSocketDataProvider(ASYNC, OK)) {
211 ssl_data_.SetNextProto(kProtoHTTP2);
212 ssl_data_.cert = ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
213 }
214
215 protected:
216 void TearDown() override {
217 if (sequenced_data_) {
218 EXPECT_TRUE(sequenced_data_->AllReadDataConsumed());
219 EXPECT_TRUE(sequenced_data_->AllWriteDataConsumed());
220 }
221 }
222
223 // Initializes the session using SequencedSocketData.
224 void InitSession(MockRead* reads,
225 size_t reads_count,
226 MockWrite* writes,
bnc3d9035b32016-06-30 18:18:48227 size_t writes_count) {
xunjieli707f8952016-06-06 15:22:06228 ASSERT_TRUE(ssl_data_.cert.get());
229 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data_);
230 sequenced_data_.reset(
231 new SequencedSocketData(reads, reads_count, writes, writes_count));
232 session_deps_.socket_factory->AddSocketDataProvider(sequenced_data_.get());
233 session_deps_.net_log = net_log_.bound().net_log();
234 http_session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
235 session_ =
bnc3d9035b32016-06-30 18:18:48236 CreateSecureSpdySession(http_session_.get(), key_, net_log_.bound());
xunjieli707f8952016-06-06 15:22:06237 }
238
239 BoundTestNetLog net_log_;
240 SpdyTestUtil spdy_util_;
241 SpdySessionDependencies session_deps_;
bnc3d9035b32016-06-30 18:18:48242 const GURL default_url_;
243 const HostPortPair host_port_pair_;
244 const SpdySessionKey key_;
xunjieli707f8952016-06-06 15:22:06245 std::unique_ptr<SequencedSocketData> sequenced_data_;
246 std::unique_ptr<HttpNetworkSession> http_session_;
247 base::WeakPtr<SpdySession> session_;
248
249 private:
250 SSLSocketDataProvider ssl_data_;
251};
252
253TEST_F(BidirectionalStreamSpdyImplTest, SendDataAfterStreamFailed) {
254 std::unique_ptr<SpdySerializedFrame> req(spdy_util_.ConstructSpdyPost(
bnc3d9035b32016-06-30 18:18:48255 kDefaultUrl, 1, kBodyDataSize * 3, LOW, nullptr, 0));
xunjieli707f8952016-06-06 15:22:06256 std::unique_ptr<SpdySerializedFrame> rst(
257 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
258
259 MockWrite writes[] = {
260 CreateMockWrite(*req, 0), CreateMockWrite(*rst, 2),
261 };
262
263 const char* const kExtraHeaders[] = {"X-UpperCase", "yes"};
264 std::unique_ptr<SpdySerializedFrame> resp(
265 spdy_util_.ConstructSpdyGetSynReply(kExtraHeaders, 1, 1));
266
267 MockRead reads[] = {
268 CreateMockRead(*resp, 1), MockRead(ASYNC, 0, 3),
269 };
270
bnc3d9035b32016-06-30 18:18:48271 InitSession(reads, arraysize(reads), writes, arraysize(writes));
xunjieli707f8952016-06-06 15:22:06272
273 BidirectionalStreamRequestInfo request_info;
274 request_info.method = "POST";
bnc3d9035b32016-06-30 18:18:48275 request_info.url = default_url_;
xunjieli707f8952016-06-06 15:22:06276 request_info.extra_headers.SetHeader(net::HttpRequestHeaders::kContentLength,
277 base::SizeTToString(kBodyDataSize * 3));
278
279 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
280 std::unique_ptr<TestDelegateBase> delegate(
281 new TestDelegateBase(session_, read_buffer.get(), kReadBufferSize));
282 delegate->SetRunUntilCompletion(true);
283 delegate->Start(&request_info, net_log_.bound());
284 base::RunLoop().RunUntilIdle();
285
286 EXPECT_TRUE(delegate->on_failed_called());
287
288 // Try to send data after OnFailed(), should not get called back.
289 scoped_refptr<StringIOBuffer> buf(new StringIOBuffer("dummy"));
290 delegate->SendData(buf.get(), buf->size(), false);
291 base::RunLoop().RunUntilIdle();
292
293 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, delegate->error());
294 EXPECT_EQ(0, delegate->on_data_read_count());
295 EXPECT_EQ(0, delegate->on_data_sent_count());
296 EXPECT_EQ(kProtoHTTP2, delegate->GetProtocol());
297 // BidirectionalStreamSpdyStreamJob does not count the bytes sent for |rst|
298 // because it is sent after SpdyStream::Delegate::OnClose is called.
299 EXPECT_EQ(CountWriteBytes(writes, 1), delegate->GetTotalSentBytes());
300 EXPECT_EQ(CountReadBytes(reads, arraysize(reads)),
301 delegate->GetTotalReceivedBytes());
302}
303
304TEST_F(BidirectionalStreamSpdyImplTest, SendDataAfterCancelStream) {
305 BufferedSpdyFramer framer(spdy_util_.spdy_version());
306
307 std::unique_ptr<SpdySerializedFrame> req(spdy_util_.ConstructSpdyPost(
bnc3d9035b32016-06-30 18:18:48308 kDefaultUrl, 1, kBodyDataSize * 3, LOWEST, nullptr, 0));
xunjieli707f8952016-06-06 15:22:06309 std::unique_ptr<SpdySerializedFrame> data_frame(
310 framer.CreateDataFrame(1, kBodyData, kBodyDataSize, DATA_FLAG_NONE));
311 std::unique_ptr<SpdySerializedFrame> rst(
312 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
313
314 MockWrite writes[] = {
315 CreateMockWrite(*req, 0), CreateMockWrite(*data_frame, 3),
316 CreateMockWrite(*rst, 5),
317 };
318
319 std::unique_ptr<SpdySerializedFrame> resp(
320 spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1));
321 std::unique_ptr<SpdySerializedFrame> response_body_frame(
322 spdy_util_.ConstructSpdyBodyFrame(1, false));
323
324 MockRead reads[] = {
325 CreateMockRead(*resp, 1),
326 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause.
327 MockRead(ASYNC, ERR_IO_PENDING, 4), // Force a pause.
328 MockRead(ASYNC, 0, 6),
329 };
330
bnc3d9035b32016-06-30 18:18:48331 InitSession(reads, arraysize(reads), writes, arraysize(writes));
xunjieli707f8952016-06-06 15:22:06332
333 BidirectionalStreamRequestInfo request_info;
334 request_info.method = "POST";
bnc3d9035b32016-06-30 18:18:48335 request_info.url = default_url_;
xunjieli707f8952016-06-06 15:22:06336 request_info.priority = LOWEST;
337 request_info.extra_headers.SetHeader(net::HttpRequestHeaders::kContentLength,
338 base::SizeTToString(kBodyDataSize * 3));
339
340 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
341 std::unique_ptr<TestDelegateBase> delegate(
342 new TestDelegateBase(session_, read_buffer.get(), kReadBufferSize));
343 delegate->set_do_not_start_read(true);
344 delegate->Start(&request_info, net_log_.bound());
345 // Send the request and receive response headers.
346 sequenced_data_->RunUntilPaused();
347 EXPECT_EQ(kProtoHTTP2, delegate->GetProtocol());
348
349 // Send a DATA frame.
350 scoped_refptr<StringIOBuffer> buf(
351 new StringIOBuffer(std::string(kBodyData, kBodyDataSize)));
352 delegate->SendData(buf.get(), buf->size(), false);
353 sequenced_data_->Resume();
354 base::RunLoop().RunUntilIdle();
355 // Cancel the stream.
356 delegate->CancelStream();
357 sequenced_data_->Resume();
358 base::RunLoop().RunUntilIdle();
359
360 // Try to send data after Cancel(), should not get called back.
361 delegate->SendData(buf.get(), buf->size(), false);
fdoray92e35a72016-06-10 15:54:55362 base::RunLoop().RunUntilIdle();
xunjieli707f8952016-06-06 15:22:06363 EXPECT_FALSE(delegate->on_failed_called());
364
365 EXPECT_EQ("200", delegate->response_headers().find(":status")->second);
366 EXPECT_EQ(0, delegate->on_data_read_count());
367 EXPECT_EQ(kProtoHTTP2, delegate->GetProtocol());
368 EXPECT_EQ(0, delegate->GetTotalSentBytes());
369 EXPECT_EQ(0, delegate->GetTotalReceivedBytes());
370}
371
372} // namespace net