OLD | NEW |
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 <memory> | 7 #include <memory> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/macros.h" | 10 #include "base/macros.h" |
11 #include "base/memory/ptr_util.h" | 11 #include "base/memory/ptr_util.h" |
12 #include "base/run_loop.h" | 12 #include "base/run_loop.h" |
13 #include "base/strings/string_number_conversions.h" | 13 #include "base/strings/string_number_conversions.h" |
14 #include "base/strings/string_piece.h" | 14 #include "base/strings/string_piece.h" |
15 #include "base/time/time.h" | 15 #include "base/time/time.h" |
16 #include "base/timer/mock_timer.h" | 16 #include "base/timer/mock_timer.h" |
| 17 #include "net/base/load_timing_info.h" |
| 18 #include "net/base/load_timing_info_test_util.h" |
17 #include "net/base/net_errors.h" | 19 #include "net/base/net_errors.h" |
18 #include "net/http/bidirectional_stream_request_info.h" | 20 #include "net/http/bidirectional_stream_request_info.h" |
19 #include "net/http/http_network_session.h" | 21 #include "net/http/http_network_session.h" |
20 #include "net/http/http_response_headers.h" | 22 #include "net/http/http_response_headers.h" |
21 #include "net/http/http_server_properties.h" | 23 #include "net/http/http_server_properties.h" |
22 #include "net/log/net_log.h" | 24 #include "net/log/net_log.h" |
23 #include "net/log/net_log_event_type.h" | 25 #include "net/log/net_log_event_type.h" |
24 #include "net/log/net_log_source_type.h" | 26 #include "net/log/net_log_source_type.h" |
25 #include "net/log/test_net_log.h" | 27 #include "net/log/test_net_log.h" |
26 #include "net/log/test_net_log_util.h" | 28 #include "net/log/test_net_log_util.h" |
(...skipping 12 matching lines...) Expand all Loading... |
39 | 41 |
40 namespace net { | 42 namespace net { |
41 | 43 |
42 namespace { | 44 namespace { |
43 | 45 |
44 const char kBodyData[] = "Body data"; | 46 const char kBodyData[] = "Body data"; |
45 const size_t kBodyDataSize = arraysize(kBodyData); | 47 const size_t kBodyDataSize = arraysize(kBodyData); |
46 // Size of the buffer to be allocated for each read. | 48 // Size of the buffer to be allocated for each read. |
47 const size_t kReadBufferSize = 4096; | 49 const size_t kReadBufferSize = 4096; |
48 | 50 |
| 51 // Expects that fields of |load_timing_info| are valid time stamps. |
| 52 void ExpectLoadTimingValid(const LoadTimingInfo& load_timing_info) { |
| 53 EXPECT_FALSE(load_timing_info.request_start.is_null()); |
| 54 EXPECT_FALSE(load_timing_info.request_start_time.is_null()); |
| 55 EXPECT_FALSE(load_timing_info.receive_headers_end.is_null()); |
| 56 EXPECT_FALSE(load_timing_info.send_start.is_null()); |
| 57 EXPECT_FALSE(load_timing_info.send_end.is_null()); |
| 58 EXPECT_TRUE(load_timing_info.request_start < |
| 59 load_timing_info.receive_headers_end); |
| 60 EXPECT_TRUE(load_timing_info.send_start <= load_timing_info.send_end); |
| 61 } |
| 62 |
| 63 // Tests the load timing of a stream that's connected and is not the first |
| 64 // request sent on a connection. |
| 65 void TestLoadTimingReused(const LoadTimingInfo& load_timing_info) { |
| 66 EXPECT_TRUE(load_timing_info.socket_reused); |
| 67 |
| 68 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing); |
| 69 ExpectLoadTimingValid(load_timing_info); |
| 70 } |
| 71 |
| 72 // Tests the load timing of a stream that's connected and using a fresh |
| 73 // connection. |
| 74 void TestLoadTimingNotReused(const LoadTimingInfo& load_timing_info) { |
| 75 EXPECT_FALSE(load_timing_info.socket_reused); |
| 76 |
| 77 ExpectConnectTimingHasTimes( |
| 78 load_timing_info.connect_timing, |
| 79 CONNECT_TIMING_HAS_SSL_TIMES | CONNECT_TIMING_HAS_DNS_TIMES); |
| 80 ExpectLoadTimingValid(load_timing_info); |
| 81 } |
| 82 |
49 // Delegate that reads data but does not send any data. | 83 // Delegate that reads data but does not send any data. |
50 class TestDelegateBase : public BidirectionalStream::Delegate { | 84 class TestDelegateBase : public BidirectionalStream::Delegate { |
51 public: | 85 public: |
52 TestDelegateBase(IOBuffer* read_buf, int read_buf_len) | 86 TestDelegateBase(IOBuffer* read_buf, int read_buf_len) |
53 : TestDelegateBase(read_buf, | 87 : TestDelegateBase(read_buf, |
54 read_buf_len, | 88 read_buf_len, |
55 base::MakeUnique<base::Timer>(false, false)) {} | 89 base::MakeUnique<base::Timer>(false, false)) {} |
56 | 90 |
57 TestDelegateBase(IOBuffer* read_buf, | 91 TestDelegateBase(IOBuffer* read_buf, |
58 int read_buf_len, | 92 int read_buf_len, |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
133 loop_->Run(); | 167 loop_->Run(); |
134 } | 168 } |
135 | 169 |
136 void Start(std::unique_ptr<BidirectionalStreamRequestInfo> request_info, | 170 void Start(std::unique_ptr<BidirectionalStreamRequestInfo> request_info, |
137 HttpNetworkSession* session, | 171 HttpNetworkSession* session, |
138 const CompletionCallback& cb) { | 172 const CompletionCallback& cb) { |
139 callback_ = cb; | 173 callback_ = cb; |
140 stream_.reset(new BidirectionalStream(std::move(request_info), session, | 174 stream_.reset(new BidirectionalStream(std::move(request_info), session, |
141 true, this, std::move(timer_))); | 175 true, this, std::move(timer_))); |
142 if (run_until_completion_) | 176 if (run_until_completion_) |
143 loop_->Run(); | 177 WaitUntilCompletion(); |
144 } | 178 } |
145 | 179 |
| 180 void WaitUntilCompletion() { loop_->Run(); } |
| 181 |
146 void SendData(const scoped_refptr<IOBuffer>& data, | 182 void SendData(const scoped_refptr<IOBuffer>& data, |
147 int length, | 183 int length, |
148 bool end_of_stream) { | 184 bool end_of_stream) { |
149 not_expect_callback_ = true; | 185 not_expect_callback_ = true; |
150 stream_->SendData(data, length, end_of_stream); | 186 stream_->SendData(data, length, end_of_stream); |
151 not_expect_callback_ = false; | 187 not_expect_callback_ = false; |
152 } | 188 } |
153 | 189 |
154 void SendvData(const std::vector<scoped_refptr<IOBuffer>>& data, | 190 void SendvData(const std::vector<scoped_refptr<IOBuffer>>& data, |
155 const std::vector<int>& length, | 191 const std::vector<int>& length, |
(...skipping 22 matching lines...) Expand all Loading... |
178 if (rv > 0) | 214 if (rv > 0) |
179 data_received_.append(read_buf_->data(), rv); | 215 data_received_.append(read_buf_->data(), rv); |
180 return rv; | 216 return rv; |
181 } | 217 } |
182 | 218 |
183 // Deletes |stream_|. | 219 // Deletes |stream_|. |
184 void DeleteStream() { | 220 void DeleteStream() { |
185 next_proto_ = stream_->GetProtocol(); | 221 next_proto_ = stream_->GetProtocol(); |
186 received_bytes_ = stream_->GetTotalReceivedBytes(); | 222 received_bytes_ = stream_->GetTotalReceivedBytes(); |
187 sent_bytes_ = stream_->GetTotalSentBytes(); | 223 sent_bytes_ = stream_->GetTotalSentBytes(); |
| 224 stream_->GetLoadTimingInfo(&load_timing_info_); |
188 stream_.reset(); | 225 stream_.reset(); |
189 } | 226 } |
190 | 227 |
191 NextProto GetProtocol() const { | 228 NextProto GetProtocol() const { |
192 if (stream_) | 229 if (stream_) |
193 return stream_->GetProtocol(); | 230 return stream_->GetProtocol(); |
194 return next_proto_; | 231 return next_proto_; |
195 } | 232 } |
196 | 233 |
197 int64_t GetTotalReceivedBytes() const { | 234 int64_t GetTotalReceivedBytes() const { |
198 if (stream_) | 235 if (stream_) |
199 return stream_->GetTotalReceivedBytes(); | 236 return stream_->GetTotalReceivedBytes(); |
200 return received_bytes_; | 237 return received_bytes_; |
201 } | 238 } |
202 | 239 |
203 int64_t GetTotalSentBytes() const { | 240 int64_t GetTotalSentBytes() const { |
204 if (stream_) | 241 if (stream_) |
205 return stream_->GetTotalSentBytes(); | 242 return stream_->GetTotalSentBytes(); |
206 return sent_bytes_; | 243 return sent_bytes_; |
207 } | 244 } |
208 | 245 |
| 246 void GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const { |
| 247 if (stream_) { |
| 248 stream_->GetLoadTimingInfo(load_timing_info); |
| 249 return; |
| 250 } |
| 251 *load_timing_info = load_timing_info_; |
| 252 } |
| 253 |
209 // Const getters for internal states. | 254 // Const getters for internal states. |
210 const std::string& data_received() const { return data_received_; } | 255 const std::string& data_received() const { return data_received_; } |
211 int error() const { return error_; } | 256 int error() const { return error_; } |
212 const SpdyHeaderBlock& response_headers() const { return response_headers_; } | 257 const SpdyHeaderBlock& response_headers() const { return response_headers_; } |
213 const SpdyHeaderBlock& trailers() const { return trailers_; } | 258 const SpdyHeaderBlock& trailers() const { return trailers_; } |
214 int on_data_read_count() const { return on_data_read_count_; } | 259 int on_data_read_count() const { return on_data_read_count_; } |
215 int on_data_sent_count() const { return on_data_sent_count_; } | 260 int on_data_sent_count() const { return on_data_sent_count_; } |
216 | 261 |
217 // Sets whether the delegate should automatically start reading. | 262 // Sets whether the delegate should automatically start reading. |
218 void set_do_not_start_read(bool do_not_start_read) { | 263 void set_do_not_start_read(bool do_not_start_read) { |
(...skipping 14 matching lines...) Expand all Loading... |
233 scoped_refptr<IOBuffer> read_buf_; | 278 scoped_refptr<IOBuffer> read_buf_; |
234 int read_buf_len_; | 279 int read_buf_len_; |
235 std::unique_ptr<base::Timer> timer_; | 280 std::unique_ptr<base::Timer> timer_; |
236 std::string data_received_; | 281 std::string data_received_; |
237 std::unique_ptr<base::RunLoop> loop_; | 282 std::unique_ptr<base::RunLoop> loop_; |
238 SpdyHeaderBlock response_headers_; | 283 SpdyHeaderBlock response_headers_; |
239 SpdyHeaderBlock trailers_; | 284 SpdyHeaderBlock trailers_; |
240 NextProto next_proto_; | 285 NextProto next_proto_; |
241 int64_t received_bytes_; | 286 int64_t received_bytes_; |
242 int64_t sent_bytes_; | 287 int64_t sent_bytes_; |
| 288 LoadTimingInfo load_timing_info_; |
243 int error_; | 289 int error_; |
244 int on_data_read_count_; | 290 int on_data_read_count_; |
245 int on_data_sent_count_; | 291 int on_data_sent_count_; |
246 bool do_not_start_read_; | 292 bool do_not_start_read_; |
247 bool run_until_completion_; | 293 bool run_until_completion_; |
248 // This is to ensure that delegate callback is not invoked synchronously when | 294 // This is to ensure that delegate callback is not invoked synchronously when |
249 // calling into |stream_|. | 295 // calling into |stream_|. |
250 bool not_expect_callback_; | 296 bool not_expect_callback_; |
251 | 297 |
252 CompletionCallback callback_; | 298 CompletionCallback callback_; |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
399 TestDelegateBase delegate(nullptr, 0); | 445 TestDelegateBase delegate(nullptr, 0); |
400 HttpNetworkSession::Params params = | 446 HttpNetworkSession::Params params = |
401 SpdySessionDependencies::CreateSessionParams(&session_deps_); | 447 SpdySessionDependencies::CreateSessionParams(&session_deps_); |
402 std::unique_ptr<HttpNetworkSession> session(new HttpNetworkSession(params)); | 448 std::unique_ptr<HttpNetworkSession> session(new HttpNetworkSession(params)); |
403 delegate.SetRunUntilCompletion(true); | 449 delegate.SetRunUntilCompletion(true); |
404 delegate.Start(std::move(request_info), session.get()); | 450 delegate.Start(std::move(request_info), session.get()); |
405 | 451 |
406 EXPECT_THAT(delegate.error(), IsError(ERR_DISALLOWED_URL_SCHEME)); | 452 EXPECT_THAT(delegate.error(), IsError(ERR_DISALLOWED_URL_SCHEME)); |
407 } | 453 } |
408 | 454 |
| 455 TEST_F(BidirectionalStreamTest, SimplePostRequest) { |
| 456 SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( |
| 457 kDefaultUrl, 1, kBodyDataSize, LOW, nullptr, 0)); |
| 458 SpdySerializedFrame data_frame(spdy_util_.ConstructSpdyDataFrame( |
| 459 1, kBodyData, kBodyDataSize, /*fin=*/true)); |
| 460 MockWrite writes[] = { |
| 461 CreateMockWrite(req, 0), CreateMockWrite(data_frame, 3), |
| 462 }; |
| 463 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); |
| 464 SpdySerializedFrame response_body_frame( |
| 465 spdy_util_.ConstructSpdyDataFrame(1, /*fin=*/true)); |
| 466 MockRead reads[] = { |
| 467 CreateMockRead(resp, 1), |
| 468 MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause. |
| 469 CreateMockRead(response_body_frame, 4), MockRead(ASYNC, 0, 5), |
| 470 }; |
| 471 InitSession(reads, arraysize(reads), writes, arraysize(writes)); |
| 472 |
| 473 std::unique_ptr<BidirectionalStreamRequestInfo> request_info( |
| 474 new BidirectionalStreamRequestInfo); |
| 475 request_info->method = "POST"; |
| 476 request_info->url = default_url_; |
| 477 request_info->extra_headers.SetHeader(net::HttpRequestHeaders::kContentLength, |
| 478 base::SizeTToString(kBodyDataSize)); |
| 479 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize)); |
| 480 std::unique_ptr<TestDelegateBase> delegate( |
| 481 new TestDelegateBase(read_buffer.get(), kReadBufferSize)); |
| 482 delegate->Start(std::move(request_info), http_session_.get()); |
| 483 sequenced_data_->RunUntilPaused(); |
| 484 |
| 485 scoped_refptr<StringIOBuffer> write_buffer( |
| 486 new StringIOBuffer(std::string(kBodyData, kBodyDataSize))); |
| 487 delegate->SendData(write_buffer.get(), write_buffer->size(), true); |
| 488 sequenced_data_->Resume(); |
| 489 base::RunLoop().RunUntilIdle(); |
| 490 LoadTimingInfo load_timing_info; |
| 491 delegate->GetLoadTimingInfo(&load_timing_info); |
| 492 TestLoadTimingNotReused(load_timing_info); |
| 493 |
| 494 EXPECT_EQ(1, delegate->on_data_read_count()); |
| 495 EXPECT_EQ(1, delegate->on_data_sent_count()); |
| 496 EXPECT_EQ(kProtoHTTP2, delegate->GetProtocol()); |
| 497 EXPECT_EQ(CountWriteBytes(writes, arraysize(writes)), |
| 498 delegate->GetTotalSentBytes()); |
| 499 EXPECT_EQ(CountReadBytes(reads, arraysize(reads)), |
| 500 delegate->GetTotalReceivedBytes()); |
| 501 } |
| 502 |
| 503 TEST_F(BidirectionalStreamTest, LoadTimingTwoRequests) { |
| 504 SpdySerializedFrame req( |
| 505 spdy_util_.ConstructSpdyGet(nullptr, 0, /*stream_id=*/1, LOW, true)); |
| 506 SpdySerializedFrame req2( |
| 507 spdy_util_.ConstructSpdyGet(nullptr, 0, /*stream_id=*/3, LOW, true)); |
| 508 MockWrite writes[] = { |
| 509 CreateMockWrite(req, 0), CreateMockWrite(req2, 2), |
| 510 }; |
| 511 SpdySerializedFrame resp( |
| 512 spdy_util_.ConstructSpdyGetReply(nullptr, 0, /*stream_id=*/1)); |
| 513 SpdySerializedFrame resp2( |
| 514 spdy_util_.ConstructSpdyGetReply(nullptr, 0, /*stream_id=*/3)); |
| 515 SpdySerializedFrame resp_body( |
| 516 spdy_util_.ConstructSpdyDataFrame(/*stream_id=*/1, /*fin=*/true)); |
| 517 SpdySerializedFrame resp_body2( |
| 518 spdy_util_.ConstructSpdyDataFrame(/*stream_id=*/3, /*fin=*/true)); |
| 519 MockRead reads[] = {CreateMockRead(resp, 1), CreateMockRead(resp_body, 3), |
| 520 CreateMockRead(resp2, 4), CreateMockRead(resp_body2, 5), |
| 521 MockRead(ASYNC, 0, 6)}; |
| 522 InitSession(reads, arraysize(reads), writes, arraysize(writes)); |
| 523 |
| 524 std::unique_ptr<BidirectionalStreamRequestInfo> request_info( |
| 525 new BidirectionalStreamRequestInfo); |
| 526 request_info->method = "GET"; |
| 527 request_info->url = default_url_; |
| 528 request_info->end_stream_on_headers = true; |
| 529 std::unique_ptr<BidirectionalStreamRequestInfo> request_info2( |
| 530 new BidirectionalStreamRequestInfo); |
| 531 request_info2->method = "GET"; |
| 532 request_info2->url = default_url_; |
| 533 request_info2->end_stream_on_headers = true; |
| 534 |
| 535 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize)); |
| 536 scoped_refptr<IOBuffer> read_buffer2(new IOBuffer(kReadBufferSize)); |
| 537 std::unique_ptr<TestDelegateBase> delegate( |
| 538 new TestDelegateBase(read_buffer.get(), kReadBufferSize)); |
| 539 std::unique_ptr<TestDelegateBase> delegate2( |
| 540 new TestDelegateBase(read_buffer2.get(), kReadBufferSize)); |
| 541 delegate->Start(std::move(request_info), http_session_.get()); |
| 542 delegate2->Start(std::move(request_info2), http_session_.get()); |
| 543 delegate->SetRunUntilCompletion(true); |
| 544 delegate2->SetRunUntilCompletion(true); |
| 545 base::RunLoop().RunUntilIdle(); |
| 546 |
| 547 delegate->WaitUntilCompletion(); |
| 548 delegate2->WaitUntilCompletion(); |
| 549 LoadTimingInfo load_timing_info; |
| 550 delegate->GetLoadTimingInfo(&load_timing_info); |
| 551 TestLoadTimingNotReused(load_timing_info); |
| 552 LoadTimingInfo load_timing_info2; |
| 553 delegate2->GetLoadTimingInfo(&load_timing_info2); |
| 554 TestLoadTimingReused(load_timing_info2); |
| 555 } |
| 556 |
409 // Creates a BidirectionalStream with an insecure scheme. Destroy the stream | 557 // Creates a BidirectionalStream with an insecure scheme. Destroy the stream |
410 // without waiting for the OnFailed task to be executed. | 558 // without waiting for the OnFailed task to be executed. |
411 TEST_F(BidirectionalStreamTest, | 559 TEST_F(BidirectionalStreamTest, |
412 CreateInsecureStreamAndDestroyStreamRightAfter) { | 560 CreateInsecureStreamAndDestroyStreamRightAfter) { |
413 std::unique_ptr<BidirectionalStreamRequestInfo> request_info( | 561 std::unique_ptr<BidirectionalStreamRequestInfo> request_info( |
414 new BidirectionalStreamRequestInfo); | 562 new BidirectionalStreamRequestInfo); |
415 request_info->method = "GET"; | 563 request_info->method = "GET"; |
416 request_info->url = GURL("http://www.example.org/"); | 564 request_info->url = GURL("http://www.example.org/"); |
417 | 565 |
418 std::unique_ptr<TestDelegateBase> delegate(new TestDelegateBase(nullptr, 0)); | 566 std::unique_ptr<TestDelegateBase> delegate(new TestDelegateBase(nullptr, 0)); |
(...skipping 1118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1537 http_session_->http_server_properties()->GetAlternativeServices( | 1685 http_session_->http_server_properties()->GetAlternativeServices( |
1538 url::SchemeHostPort(default_url_)); | 1686 url::SchemeHostPort(default_url_)); |
1539 ASSERT_EQ(1u, alternative_service_vector.size()); | 1687 ASSERT_EQ(1u, alternative_service_vector.size()); |
1540 EXPECT_EQ(AlternateProtocolFromNextProto(kProtoQUIC1SPDY3), | 1688 EXPECT_EQ(AlternateProtocolFromNextProto(kProtoQUIC1SPDY3), |
1541 alternative_service_vector[0].protocol); | 1689 alternative_service_vector[0].protocol); |
1542 EXPECT_EQ("www.example.org", alternative_service_vector[0].host); | 1690 EXPECT_EQ("www.example.org", alternative_service_vector[0].host); |
1543 EXPECT_EQ(443, alternative_service_vector[0].port); | 1691 EXPECT_EQ(443, alternative_service_vector[0].port); |
1544 } | 1692 } |
1545 | 1693 |
1546 } // namespace net | 1694 } // namespace net |
OLD | NEW |