OLD | NEW |
| (Empty) |
1 // 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/quic/bidirectional_stream_quic_impl.h" | |
6 | |
7 #include <stdint.h> | |
8 #include <vector> | |
9 | |
10 #include "base/callback_helpers.h" | |
11 #include "base/memory/scoped_ptr.h" | |
12 #include "base/message_loop/message_loop.h" | |
13 #include "base/run_loop.h" | |
14 #include "base/strings/string_number_conversions.h" | |
15 #include "net/base/net_errors.h" | |
16 #include "net/http/bidirectional_stream_request_info.h" | |
17 #include "net/http/transport_security_state.h" | |
18 #include "net/quic/crypto/crypto_protocol.h" | |
19 #include "net/quic/crypto/quic_decrypter.h" | |
20 #include "net/quic/crypto/quic_encrypter.h" | |
21 #include "net/quic/crypto/quic_server_info.h" | |
22 #include "net/quic/quic_chromium_client_session.h" | |
23 #include "net/quic/quic_chromium_client_stream.h" | |
24 #include "net/quic/quic_chromium_connection_helper.h" | |
25 #include "net/quic/quic_chromium_packet_reader.h" | |
26 #include "net/quic/quic_chromium_packet_writer.h" | |
27 #include "net/quic/quic_connection.h" | |
28 #include "net/quic/quic_http_utils.h" | |
29 #include "net/quic/spdy_utils.h" | |
30 #include "net/quic/test_tools/crypto_test_utils.h" | |
31 #include "net/quic/test_tools/mock_clock.h" | |
32 #include "net/quic/test_tools/mock_crypto_client_stream_factory.h" | |
33 #include "net/quic/test_tools/mock_random.h" | |
34 #include "net/quic/test_tools/quic_connection_peer.h" | |
35 #include "net/quic/test_tools/quic_test_packet_maker.h" | |
36 #include "net/quic/test_tools/quic_test_utils.h" | |
37 #include "net/quic/test_tools/test_task_runner.h" | |
38 #include "net/socket/socket_test_util.h" | |
39 #include "testing/gmock/include/gmock/gmock.h" | |
40 #include "testing/gtest/include/gtest/gtest.h" | |
41 | |
42 namespace net { | |
43 | |
44 namespace test { | |
45 | |
46 namespace { | |
47 | |
48 const char kUploadData[] = "Really nifty data!"; | |
49 const char kDefaultServerHostName[] = "www.google.com"; | |
50 const uint16_t kDefaultServerPort = 80; | |
51 // Size of the buffer to be allocated for each read. | |
52 const size_t kReadBufferSize = 4096; | |
53 | |
54 class TestDelegateBase : public BidirectionalStreamJob::Delegate { | |
55 public: | |
56 TestDelegateBase(IOBuffer* read_buf, int read_buf_len) | |
57 : TestDelegateBase(read_buf, | |
58 read_buf_len, | |
59 make_scoped_ptr(new base::Timer(false, false))) {} | |
60 | |
61 TestDelegateBase(IOBuffer* read_buf, | |
62 int read_buf_len, | |
63 scoped_ptr<base::Timer> timer) | |
64 : read_buf_(read_buf), | |
65 read_buf_len_(read_buf_len), | |
66 timer_(std::move(timer)), | |
67 loop_(nullptr), | |
68 error_(OK), | |
69 on_data_read_count_(0), | |
70 on_data_sent_count_(0), | |
71 not_expect_callback_(false) { | |
72 loop_.reset(new base::RunLoop); | |
73 } | |
74 | |
75 ~TestDelegateBase() override {} | |
76 | |
77 void OnHeadersSent() override { | |
78 CHECK(!not_expect_callback_); | |
79 loop_->Quit(); | |
80 } | |
81 | |
82 void OnHeadersReceived(const SpdyHeaderBlock& response_headers) override { | |
83 CHECK(!not_expect_callback_); | |
84 | |
85 response_headers_ = response_headers; | |
86 loop_->Quit(); | |
87 } | |
88 | |
89 void OnDataRead(int bytes_read) override { | |
90 CHECK(!not_expect_callback_); | |
91 CHECK(!callback_.is_null()); | |
92 | |
93 ++on_data_read_count_; | |
94 CHECK_GE(bytes_read, OK); | |
95 data_received_.append(read_buf_->data(), bytes_read); | |
96 base::ResetAndReturn(&callback_).Run(bytes_read); | |
97 } | |
98 | |
99 void OnDataSent() override { | |
100 CHECK(!not_expect_callback_); | |
101 | |
102 ++on_data_sent_count_; | |
103 loop_->Quit(); | |
104 } | |
105 | |
106 void OnTrailersReceived(const SpdyHeaderBlock& trailers) override { | |
107 CHECK(!not_expect_callback_); | |
108 | |
109 trailers_ = trailers; | |
110 loop_->Quit(); | |
111 } | |
112 | |
113 void OnFailed(int error) override { | |
114 CHECK(!not_expect_callback_); | |
115 CHECK_EQ(OK, error_); | |
116 CHECK_NE(OK, error); | |
117 | |
118 error_ = error; | |
119 loop_->Quit(); | |
120 } | |
121 | |
122 void Start(const BidirectionalStreamRequestInfo* request_info, | |
123 const BoundNetLog& net_log, | |
124 const base::WeakPtr<QuicChromiumClientSession> session) { | |
125 stream_job_.reset(new BidirectionalStreamQuicImpl(session)); | |
126 stream_job_->Start(request_info, net_log, this, nullptr); | |
127 } | |
128 | |
129 void SendData(IOBuffer* data, int length, bool end_of_stream) { | |
130 not_expect_callback_ = true; | |
131 stream_job_->SendData(data, length, end_of_stream); | |
132 not_expect_callback_ = false; | |
133 } | |
134 | |
135 // Waits until next Delegate callback. | |
136 void WaitUntilNextCallback() { | |
137 loop_->Run(); | |
138 loop_.reset(new base::RunLoop); | |
139 } | |
140 | |
141 // Calls ReadData on the |stream_| and updates |data_received_|. | |
142 int ReadData(const CompletionCallback& callback) { | |
143 not_expect_callback_ = true; | |
144 int rv = stream_job_->ReadData(read_buf_.get(), read_buf_len_); | |
145 not_expect_callback_ = false; | |
146 if (rv > 0) | |
147 data_received_.append(read_buf_->data(), rv); | |
148 if (rv == ERR_IO_PENDING) | |
149 callback_ = callback; | |
150 return rv; | |
151 } | |
152 | |
153 // Cancels |stream_|. | |
154 void CancelStream() { stream_job_->Cancel(); } | |
155 | |
156 NextProto GetProtocol() const { return stream_job_->GetProtocol(); } | |
157 | |
158 int64_t GetTotalReceivedBytes() const { | |
159 return stream_job_->GetTotalReceivedBytes(); | |
160 } | |
161 | |
162 int64_t GetTotalSentBytes() const { return stream_job_->GetTotalSentBytes(); } | |
163 | |
164 // Const getters for internal states. | |
165 const std::string& data_received() const { return data_received_; } | |
166 int error() const { return error_; } | |
167 const SpdyHeaderBlock& response_headers() const { return response_headers_; } | |
168 const SpdyHeaderBlock& trailers() const { return trailers_; } | |
169 int on_data_read_count() const { return on_data_read_count_; } | |
170 int on_data_sent_count() const { return on_data_sent_count_; } | |
171 | |
172 protected: | |
173 // Quits |loop_|. | |
174 void QuitLoop() { loop_->Quit(); } | |
175 | |
176 // Deletes |stream_|. | |
177 void DeleteStream() { stream_job_.reset(); } | |
178 | |
179 private: | |
180 scoped_ptr<BidirectionalStreamQuicImpl> stream_job_; | |
181 scoped_refptr<IOBuffer> read_buf_; | |
182 int read_buf_len_; | |
183 scoped_ptr<base::Timer> timer_; | |
184 std::string data_received_; | |
185 scoped_ptr<base::RunLoop> loop_; | |
186 SpdyHeaderBlock response_headers_; | |
187 SpdyHeaderBlock trailers_; | |
188 int error_; | |
189 int on_data_read_count_; | |
190 int on_data_sent_count_; | |
191 // This is to ensure that delegate callback is not invoked synchronously when | |
192 // calling into |stream_|. | |
193 bool not_expect_callback_; | |
194 CompletionCallback callback_; | |
195 | |
196 DISALLOW_COPY_AND_ASSIGN(TestDelegateBase); | |
197 }; | |
198 | |
199 // A delegate that deletes the stream in a particular callback. | |
200 class DeleteStreamDelegate : public TestDelegateBase { | |
201 public: | |
202 // Specifies in which callback the stream can be deleted. | |
203 enum Phase { | |
204 ON_HEADERS_RECEIVED, | |
205 ON_DATA_READ, | |
206 ON_TRAILERS_RECEIVED, | |
207 ON_FAILED, | |
208 }; | |
209 | |
210 DeleteStreamDelegate(IOBuffer* buf, int buf_len, Phase phase, bool do_cancel) | |
211 : TestDelegateBase(buf, buf_len), phase_(phase), do_cancel_(do_cancel) {} | |
212 ~DeleteStreamDelegate() override {} | |
213 | |
214 void OnHeadersReceived(const SpdyHeaderBlock& response_headers) override { | |
215 if (phase_ == ON_HEADERS_RECEIVED) { | |
216 DeleteStream(); | |
217 } | |
218 TestDelegateBase::OnHeadersReceived(response_headers); | |
219 } | |
220 | |
221 void OnDataSent() override { NOTREACHED(); } | |
222 | |
223 void OnDataRead(int bytes_read) override { | |
224 DCHECK_NE(ON_HEADERS_RECEIVED, phase_); | |
225 if (phase_ == ON_DATA_READ) | |
226 DeleteStream(); | |
227 TestDelegateBase::OnDataRead(bytes_read); | |
228 } | |
229 | |
230 void OnTrailersReceived(const SpdyHeaderBlock& trailers) override { | |
231 DCHECK_NE(ON_HEADERS_RECEIVED, phase_); | |
232 DCHECK_NE(ON_DATA_READ, phase_); | |
233 if (phase_ == ON_TRAILERS_RECEIVED) | |
234 DeleteStream(); | |
235 TestDelegateBase::OnTrailersReceived(trailers); | |
236 } | |
237 | |
238 void OnFailed(int error) override { | |
239 DCHECK_EQ(ON_FAILED, phase_); | |
240 DeleteStream(); | |
241 TestDelegateBase::OnFailed(error); | |
242 } | |
243 | |
244 private: | |
245 // Indicates in which callback the delegate should cancel or delete the | |
246 // stream. | |
247 Phase phase_; | |
248 // Indicates whether to cancel or delete the stream. | |
249 bool do_cancel_; | |
250 | |
251 DISALLOW_COPY_AND_ASSIGN(DeleteStreamDelegate); | |
252 }; | |
253 | |
254 } // namespace | |
255 | |
256 class BidirectionalStreamQuicImplTest | |
257 : public ::testing::TestWithParam<QuicVersion> { | |
258 protected: | |
259 static const bool kFin = true; | |
260 static const bool kIncludeVersion = true; | |
261 static const bool kIncludeCongestionFeedback = true; | |
262 | |
263 // Holds a packet to be written to the wire, and the IO mode that should | |
264 // be used by the mock socket when performing the write. | |
265 struct PacketToWrite { | |
266 PacketToWrite(IoMode mode, QuicEncryptedPacket* packet) | |
267 : mode(mode), packet(packet) {} | |
268 PacketToWrite(IoMode mode, int rv) : mode(mode), packet(nullptr), rv(rv) {} | |
269 IoMode mode; | |
270 QuicEncryptedPacket* packet; | |
271 int rv; | |
272 }; | |
273 | |
274 BidirectionalStreamQuicImplTest() | |
275 : net_log_(BoundNetLog()), | |
276 crypto_config_(CryptoTestUtils::ProofVerifierForTesting()), | |
277 read_buffer_(new IOBufferWithSize(4096)), | |
278 connection_id_(2), | |
279 stream_id_(kClientDataStreamId1), | |
280 maker_(GetParam(), connection_id_, &clock_, kDefaultServerHostName), | |
281 random_generator_(0) { | |
282 IPAddressNumber ip; | |
283 CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip)); | |
284 peer_addr_ = IPEndPoint(ip, 443); | |
285 self_addr_ = IPEndPoint(ip, 8435); | |
286 clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(20)); | |
287 } | |
288 | |
289 ~BidirectionalStreamQuicImplTest() { | |
290 session_->CloseSessionOnError(ERR_ABORTED, QUIC_INTERNAL_ERROR); | |
291 for (size_t i = 0; i < writes_.size(); i++) { | |
292 delete writes_[i].packet; | |
293 } | |
294 } | |
295 | |
296 void TearDown() override { | |
297 EXPECT_TRUE(socket_data_->AllReadDataConsumed()); | |
298 EXPECT_TRUE(socket_data_->AllWriteDataConsumed()); | |
299 } | |
300 | |
301 // Adds a packet to the list of expected writes. | |
302 void AddWrite(scoped_ptr<QuicEncryptedPacket> packet) { | |
303 writes_.push_back(PacketToWrite(SYNCHRONOUS, packet.release())); | |
304 } | |
305 | |
306 void ProcessPacket(scoped_ptr<QuicEncryptedPacket> packet) { | |
307 connection_->ProcessUdpPacket(self_addr_, peer_addr_, *packet); | |
308 } | |
309 | |
310 // Configures the test fixture to use the list of expected writes. | |
311 void Initialize() { | |
312 mock_writes_.reset(new MockWrite[writes_.size()]); | |
313 for (size_t i = 0; i < writes_.size(); i++) { | |
314 if (writes_[i].packet == nullptr) { | |
315 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].rv, i); | |
316 } else { | |
317 mock_writes_[i] = MockWrite(writes_[i].mode, writes_[i].packet->data(), | |
318 writes_[i].packet->length()); | |
319 } | |
320 }; | |
321 | |
322 socket_data_.reset(new StaticSocketDataProvider( | |
323 nullptr, 0, mock_writes_.get(), writes_.size())); | |
324 | |
325 MockUDPClientSocket* socket = | |
326 new MockUDPClientSocket(socket_data_.get(), net_log_.net_log()); | |
327 socket->Connect(peer_addr_); | |
328 runner_ = new TestTaskRunner(&clock_); | |
329 helper_.reset(new QuicChromiumConnectionHelper(runner_.get(), &clock_, | |
330 &random_generator_)); | |
331 connection_ = new QuicConnection( | |
332 connection_id_, peer_addr_, helper_.get(), | |
333 new QuicChromiumPacketWriter(socket), true /* owns_writer */, | |
334 Perspective::IS_CLIENT, SupportedVersions(GetParam())); | |
335 | |
336 session_.reset(new QuicChromiumClientSession( | |
337 connection_, scoped_ptr<DatagramClientSocket>(socket), | |
338 /*stream_factory=*/nullptr, &crypto_client_stream_factory_, &clock_, | |
339 &transport_security_state_, make_scoped_ptr((QuicServerInfo*)nullptr), | |
340 QuicServerId(kDefaultServerHostName, kDefaultServerPort, | |
341 PRIVACY_MODE_DISABLED), | |
342 kQuicYieldAfterPacketsRead, | |
343 QuicTime::Delta::FromMilliseconds(kQuicYieldAfterDurationMilliseconds), | |
344 /*cert_verify_flags=*/0, DefaultQuicConfig(), &crypto_config_, | |
345 "CONNECTION_UNKNOWN", base::TimeTicks::Now(), &push_promise_index_, | |
346 base::ThreadTaskRunnerHandle::Get().get(), | |
347 /*socket_performance_watcher=*/nullptr, nullptr)); | |
348 session_->Initialize(); | |
349 session_->GetCryptoStream()->CryptoConnect(); | |
350 EXPECT_TRUE(session_->IsCryptoHandshakeConfirmed()); | |
351 } | |
352 | |
353 void SetRequest(const std::string& method, | |
354 const std::string& path, | |
355 RequestPriority priority) { | |
356 request_headers_ = maker_.GetRequestHeaders(method, "http", path); | |
357 } | |
358 | |
359 SpdyHeaderBlock ConstructResponseHeaders(const std::string& response_code) { | |
360 return maker_.GetResponseHeaders(response_code); | |
361 } | |
362 | |
363 scoped_ptr<QuicEncryptedPacket> ConstructDataPacket( | |
364 QuicPacketNumber packet_number, | |
365 bool should_include_version, | |
366 bool fin, | |
367 QuicStreamOffset offset, | |
368 base::StringPiece data) { | |
369 scoped_ptr<QuicEncryptedPacket> packet(maker_.MakeDataPacket( | |
370 packet_number, stream_id_, should_include_version, fin, offset, data)); | |
371 DVLOG(2) << "packet(" << packet_number << "): " << std::endl | |
372 << QuicUtils::StringToHexASCIIDump(packet->AsStringPiece()); | |
373 return packet; | |
374 } | |
375 | |
376 scoped_ptr<QuicEncryptedPacket> ConstructRequestHeadersPacket( | |
377 QuicPacketNumber packet_number, | |
378 bool fin, | |
379 RequestPriority request_priority, | |
380 size_t* spdy_headers_frame_length) { | |
381 SpdyPriority priority = | |
382 ConvertRequestPriorityToQuicPriority(request_priority); | |
383 return maker_.MakeRequestHeadersPacket( | |
384 packet_number, stream_id_, kIncludeVersion, fin, priority, | |
385 request_headers_, spdy_headers_frame_length); | |
386 } | |
387 | |
388 scoped_ptr<QuicEncryptedPacket> ConstructResponseHeadersPacket( | |
389 QuicPacketNumber packet_number, | |
390 bool fin, | |
391 const SpdyHeaderBlock& response_headers, | |
392 size_t* spdy_headers_frame_length, | |
393 QuicStreamOffset* offset) { | |
394 return maker_.MakeResponseHeadersPacket( | |
395 packet_number, stream_id_, !kIncludeVersion, fin, response_headers, | |
396 spdy_headers_frame_length, offset); | |
397 } | |
398 | |
399 scoped_ptr<QuicEncryptedPacket> ConstructResponseTrailersPacket( | |
400 QuicPacketNumber packet_number, | |
401 bool fin, | |
402 const SpdyHeaderBlock& trailers, | |
403 size_t* spdy_headers_frame_length, | |
404 QuicStreamOffset* offset) { | |
405 return maker_.MakeResponseHeadersPacket(packet_number, stream_id_, | |
406 !kIncludeVersion, fin, trailers, | |
407 spdy_headers_frame_length, offset); | |
408 } | |
409 | |
410 scoped_ptr<QuicEncryptedPacket> ConstructRstStreamPacket( | |
411 QuicPacketNumber packet_number) { | |
412 return ConstructRstStreamCancelledPacket(packet_number, 0); | |
413 } | |
414 | |
415 scoped_ptr<QuicEncryptedPacket> ConstructRstStreamCancelledPacket( | |
416 QuicPacketNumber packet_number, | |
417 size_t bytes_written) { | |
418 scoped_ptr<QuicEncryptedPacket> packet( | |
419 maker_.MakeRstPacket(packet_number, !kIncludeVersion, stream_id_, | |
420 QUIC_STREAM_CANCELLED, bytes_written)); | |
421 DVLOG(2) << "packet(" << packet_number << "): " << std::endl | |
422 << QuicUtils::StringToHexASCIIDump(packet->AsStringPiece()); | |
423 return packet; | |
424 } | |
425 | |
426 scoped_ptr<QuicEncryptedPacket> ConstructAckAndRstStreamPacket( | |
427 QuicPacketNumber packet_number, | |
428 QuicPacketNumber largest_received, | |
429 QuicPacketNumber ack_least_unacked, | |
430 QuicPacketNumber stop_least_unacked) { | |
431 return maker_.MakeAckAndRstPacket( | |
432 packet_number, !kIncludeVersion, stream_id_, QUIC_STREAM_CANCELLED, | |
433 largest_received, ack_least_unacked, stop_least_unacked, | |
434 !kIncludeCongestionFeedback); | |
435 } | |
436 | |
437 scoped_ptr<QuicEncryptedPacket> ConstructAckAndDataPacket( | |
438 QuicPacketNumber packet_number, | |
439 bool should_include_version, | |
440 QuicPacketNumber largest_received, | |
441 QuicPacketNumber least_unacked, | |
442 bool fin, | |
443 QuicStreamOffset offset, | |
444 base::StringPiece data) { | |
445 scoped_ptr<QuicEncryptedPacket> packet(maker_.MakeAckAndDataPacket( | |
446 packet_number, should_include_version, stream_id_, largest_received, | |
447 least_unacked, fin, offset, data)); | |
448 DVLOG(2) << "packet(" << packet_number << "): " << std::endl | |
449 << QuicUtils::StringToHexASCIIDump(packet->AsStringPiece()); | |
450 return packet; | |
451 } | |
452 | |
453 scoped_ptr<QuicEncryptedPacket> ConstructAckPacket( | |
454 QuicPacketNumber packet_number, | |
455 QuicPacketNumber largest_received, | |
456 QuicPacketNumber least_unacked) { | |
457 return maker_.MakeAckPacket(packet_number, largest_received, least_unacked, | |
458 !kIncludeCongestionFeedback); | |
459 } | |
460 | |
461 const BoundNetLog& net_log() const { return net_log_; } | |
462 | |
463 QuicChromiumClientSession* session() const { return session_.get(); } | |
464 | |
465 private: | |
466 BoundNetLog net_log_; | |
467 scoped_refptr<TestTaskRunner> runner_; | |
468 scoped_ptr<MockWrite[]> mock_writes_; | |
469 MockClock clock_; | |
470 QuicConnection* connection_; | |
471 scoped_ptr<QuicChromiumConnectionHelper> helper_; | |
472 TransportSecurityState transport_security_state_; | |
473 scoped_ptr<QuicChromiumClientSession> session_; | |
474 QuicCryptoClientConfig crypto_config_; | |
475 HttpRequestHeaders headers_; | |
476 HttpResponseInfo response_; | |
477 scoped_refptr<IOBufferWithSize> read_buffer_; | |
478 SpdyHeaderBlock request_headers_; | |
479 const QuicConnectionId connection_id_; | |
480 const QuicStreamId stream_id_; | |
481 QuicTestPacketMaker maker_; | |
482 IPEndPoint self_addr_; | |
483 IPEndPoint peer_addr_; | |
484 MockRandom random_generator_; | |
485 MockCryptoClientStreamFactory crypto_client_stream_factory_; | |
486 scoped_ptr<StaticSocketDataProvider> socket_data_; | |
487 std::vector<PacketToWrite> writes_; | |
488 QuicClientPushPromiseIndex push_promise_index_; | |
489 }; | |
490 | |
491 INSTANTIATE_TEST_CASE_P(Version, | |
492 BidirectionalStreamQuicImplTest, | |
493 ::testing::ValuesIn(QuicSupportedVersions())); | |
494 | |
495 TEST_P(BidirectionalStreamQuicImplTest, GetRequest) { | |
496 SetRequest("GET", "/", DEFAULT_PRIORITY); | |
497 size_t spdy_request_headers_frame_length; | |
498 AddWrite(ConstructRequestHeadersPacket(1, kFin, DEFAULT_PRIORITY, | |
499 &spdy_request_headers_frame_length)); | |
500 | |
501 AddWrite(ConstructAckPacket(2, 3, 1)); | |
502 Initialize(); | |
503 | |
504 BidirectionalStreamRequestInfo request; | |
505 request.method = "GET"; | |
506 request.url = GURL("http://www.google.com/"); | |
507 request.end_stream_on_headers = true; | |
508 request.priority = DEFAULT_PRIORITY; | |
509 | |
510 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize)); | |
511 scoped_ptr<TestDelegateBase> delegate( | |
512 new TestDelegateBase(read_buffer.get(), kReadBufferSize)); | |
513 delegate->Start(&request, net_log(), session()->GetWeakPtr()); | |
514 delegate->WaitUntilNextCallback(); // OnHeadersSent | |
515 | |
516 // Server acks the request. | |
517 ProcessPacket(ConstructAckPacket(1, 0, 0)); | |
518 | |
519 // Server sends the response headers. | |
520 SpdyHeaderBlock response_headers = ConstructResponseHeaders("200"); | |
521 | |
522 size_t spdy_response_headers_frame_length; | |
523 QuicStreamOffset offset = 0; | |
524 ProcessPacket(ConstructResponseHeadersPacket( | |
525 2, !kFin, response_headers, &spdy_response_headers_frame_length, | |
526 &offset)); | |
527 | |
528 delegate->WaitUntilNextCallback(); // OnHeadersReceived | |
529 TestCompletionCallback cb; | |
530 int rv = delegate->ReadData(cb.callback()); | |
531 EXPECT_EQ(ERR_IO_PENDING, rv); | |
532 EXPECT_EQ("200", delegate->response_headers().find(":status")->second); | |
533 const char kResponseBody[] = "Hello world!"; | |
534 // Server sends data. | |
535 ProcessPacket( | |
536 ConstructDataPacket(3, !kIncludeVersion, !kFin, 0, kResponseBody)); | |
537 EXPECT_EQ(12, cb.WaitForResult()); | |
538 | |
539 EXPECT_EQ(std::string(kResponseBody), delegate->data_received()); | |
540 TestCompletionCallback cb2; | |
541 EXPECT_EQ(ERR_IO_PENDING, delegate->ReadData(cb2.callback())); | |
542 | |
543 SpdyHeaderBlock trailers; | |
544 size_t spdy_trailers_frame_length; | |
545 trailers["foo"] = "bar"; | |
546 trailers[kFinalOffsetHeaderKey] = base::IntToString(strlen(kResponseBody)); | |
547 // Server sends trailers. | |
548 ProcessPacket(ConstructResponseTrailersPacket( | |
549 4, kFin, trailers, &spdy_trailers_frame_length, &offset)); | |
550 | |
551 delegate->WaitUntilNextCallback(); // OnTrailersReceived | |
552 EXPECT_EQ(OK, cb2.WaitForResult()); | |
553 trailers.erase(kFinalOffsetHeaderKey); | |
554 EXPECT_EQ(trailers, delegate->trailers()); | |
555 | |
556 EXPECT_EQ(OK, delegate->ReadData(cb2.callback())); | |
557 base::MessageLoop::current()->RunUntilIdle(); | |
558 | |
559 EXPECT_EQ(2, delegate->on_data_read_count()); | |
560 EXPECT_EQ(0, delegate->on_data_sent_count()); | |
561 EXPECT_EQ(kProtoQUIC1SPDY3, delegate->GetProtocol()); | |
562 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length), | |
563 delegate->GetTotalSentBytes()); | |
564 EXPECT_EQ( | |
565 static_cast<int64_t>(spdy_response_headers_frame_length + | |
566 strlen(kResponseBody) + spdy_trailers_frame_length), | |
567 delegate->GetTotalReceivedBytes()); | |
568 } | |
569 | |
570 TEST_P(BidirectionalStreamQuicImplTest, PostRequest) { | |
571 SetRequest("POST", "/", DEFAULT_PRIORITY); | |
572 size_t spdy_request_headers_frame_length; | |
573 AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY, | |
574 &spdy_request_headers_frame_length)); | |
575 AddWrite(ConstructDataPacket(2, kIncludeVersion, kFin, 0, kUploadData)); | |
576 AddWrite(ConstructAckPacket(3, 3, 1)); | |
577 | |
578 Initialize(); | |
579 | |
580 BidirectionalStreamRequestInfo request; | |
581 request.method = "POST"; | |
582 request.url = GURL("http://www.google.com/"); | |
583 request.end_stream_on_headers = false; | |
584 request.priority = DEFAULT_PRIORITY; | |
585 | |
586 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize)); | |
587 scoped_ptr<TestDelegateBase> delegate( | |
588 new TestDelegateBase(read_buffer.get(), kReadBufferSize)); | |
589 delegate->Start(&request, net_log(), session()->GetWeakPtr()); | |
590 delegate->WaitUntilNextCallback(); // OnHeadersSent | |
591 | |
592 // Send a DATA frame. | |
593 scoped_refptr<StringIOBuffer> buf(new StringIOBuffer(kUploadData)); | |
594 | |
595 delegate->SendData(buf.get(), buf->size(), true); | |
596 delegate->WaitUntilNextCallback(); // OnDataSent | |
597 | |
598 // Server acks the request. | |
599 ProcessPacket(ConstructAckPacket(1, 0, 0)); | |
600 | |
601 // Server sends the response headers. | |
602 SpdyHeaderBlock response_headers = ConstructResponseHeaders("200"); | |
603 size_t spdy_response_headers_frame_length; | |
604 QuicStreamOffset offset = 0; | |
605 ProcessPacket(ConstructResponseHeadersPacket( | |
606 2, !kFin, response_headers, &spdy_response_headers_frame_length, | |
607 &offset)); | |
608 | |
609 delegate->WaitUntilNextCallback(); // OnHeadersReceived | |
610 TestCompletionCallback cb; | |
611 int rv = delegate->ReadData(cb.callback()); | |
612 EXPECT_EQ(ERR_IO_PENDING, rv); | |
613 EXPECT_EQ("200", delegate->response_headers().find(":status")->second); | |
614 const char kResponseBody[] = "Hello world!"; | |
615 // Server sends data. | |
616 ProcessPacket( | |
617 ConstructDataPacket(3, !kIncludeVersion, !kFin, 0, kResponseBody)); | |
618 | |
619 EXPECT_EQ(static_cast<int>(strlen(kResponseBody)), cb.WaitForResult()); | |
620 | |
621 size_t spdy_trailers_frame_length; | |
622 SpdyHeaderBlock trailers; | |
623 trailers["foo"] = "bar"; | |
624 trailers[kFinalOffsetHeaderKey] = base::IntToString(strlen(kResponseBody)); | |
625 // Server sends trailers. | |
626 ProcessPacket(ConstructResponseTrailersPacket( | |
627 4, kFin, trailers, &spdy_trailers_frame_length, &offset)); | |
628 | |
629 delegate->WaitUntilNextCallback(); // OnTrailersReceived | |
630 trailers.erase(kFinalOffsetHeaderKey); | |
631 EXPECT_EQ(trailers, delegate->trailers()); | |
632 EXPECT_EQ(OK, delegate->ReadData(cb.callback())); | |
633 | |
634 EXPECT_EQ(1, delegate->on_data_read_count()); | |
635 EXPECT_EQ(1, delegate->on_data_sent_count()); | |
636 EXPECT_EQ(kProtoQUIC1SPDY3, delegate->GetProtocol()); | |
637 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length + | |
638 strlen(kUploadData)), | |
639 delegate->GetTotalSentBytes()); | |
640 EXPECT_EQ( | |
641 static_cast<int64_t>(spdy_response_headers_frame_length + | |
642 strlen(kResponseBody) + spdy_trailers_frame_length), | |
643 delegate->GetTotalReceivedBytes()); | |
644 } | |
645 | |
646 TEST_P(BidirectionalStreamQuicImplTest, InterleaveReadDataAndSendData) { | |
647 SetRequest("POST", "/", DEFAULT_PRIORITY); | |
648 size_t spdy_request_headers_frame_length; | |
649 AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY, | |
650 &spdy_request_headers_frame_length)); | |
651 AddWrite(ConstructAckAndDataPacket(2, !kIncludeVersion, 2, 1, !kFin, 0, | |
652 kUploadData)); | |
653 AddWrite(ConstructAckAndDataPacket(3, !kIncludeVersion, 3, 3, kFin, | |
654 strlen(kUploadData), kUploadData)); | |
655 Initialize(); | |
656 | |
657 BidirectionalStreamRequestInfo request; | |
658 request.method = "POST"; | |
659 request.url = GURL("http://www.google.com/"); | |
660 request.end_stream_on_headers = false; | |
661 request.priority = DEFAULT_PRIORITY; | |
662 | |
663 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize)); | |
664 scoped_ptr<TestDelegateBase> delegate( | |
665 new TestDelegateBase(read_buffer.get(), kReadBufferSize)); | |
666 delegate->Start(&request, net_log(), session()->GetWeakPtr()); | |
667 delegate->WaitUntilNextCallback(); // OnHeadersSent | |
668 | |
669 // Server acks the request. | |
670 ProcessPacket(ConstructAckPacket(1, 0, 0)); | |
671 | |
672 // Server sends the response headers. | |
673 SpdyHeaderBlock response_headers = ConstructResponseHeaders("200"); | |
674 size_t spdy_response_headers_frame_length; | |
675 ProcessPacket(ConstructResponseHeadersPacket( | |
676 2, !kFin, response_headers, &spdy_response_headers_frame_length, 0)); | |
677 | |
678 delegate->WaitUntilNextCallback(); // OnHeadersReceived | |
679 EXPECT_EQ("200", delegate->response_headers().find(":status")->second); | |
680 | |
681 // Client sends a data packet. | |
682 scoped_refptr<StringIOBuffer> buf(new StringIOBuffer(kUploadData)); | |
683 | |
684 delegate->SendData(buf.get(), buf->size(), false); | |
685 delegate->WaitUntilNextCallback(); // OnDataSent | |
686 | |
687 TestCompletionCallback cb; | |
688 int rv = delegate->ReadData(cb.callback()); | |
689 EXPECT_EQ(ERR_IO_PENDING, rv); | |
690 const char kResponseBody[] = "Hello world!"; | |
691 | |
692 // Server sends a data packet. | |
693 ProcessPacket(ConstructAckAndDataPacket(3, !kIncludeVersion, 2, 1, !kFin, 0, | |
694 kResponseBody)); | |
695 | |
696 EXPECT_EQ(static_cast<int64_t>(strlen(kResponseBody)), cb.WaitForResult()); | |
697 EXPECT_EQ(std::string(kResponseBody), delegate->data_received()); | |
698 | |
699 // Client sends a data packet. | |
700 delegate->SendData(buf.get(), buf->size(), true); | |
701 delegate->WaitUntilNextCallback(); // OnDataSent | |
702 | |
703 TestCompletionCallback cb2; | |
704 rv = delegate->ReadData(cb2.callback()); | |
705 EXPECT_EQ(ERR_IO_PENDING, rv); | |
706 ProcessPacket(ConstructAckAndDataPacket( | |
707 4, !kIncludeVersion, 3, 1, kFin, strlen(kResponseBody), kResponseBody)); | |
708 | |
709 EXPECT_EQ(static_cast<int64_t>(strlen(kResponseBody)), cb2.WaitForResult()); | |
710 | |
711 std::string expected_body(kResponseBody); | |
712 expected_body.append(kResponseBody); | |
713 EXPECT_EQ(expected_body, delegate->data_received()); | |
714 | |
715 EXPECT_EQ(OK, delegate->ReadData(cb.callback())); | |
716 EXPECT_EQ(2, delegate->on_data_read_count()); | |
717 EXPECT_EQ(2, delegate->on_data_sent_count()); | |
718 EXPECT_EQ(kProtoQUIC1SPDY3, delegate->GetProtocol()); | |
719 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length + | |
720 2 * strlen(kUploadData)), | |
721 delegate->GetTotalSentBytes()); | |
722 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length + | |
723 2 * strlen(kResponseBody)), | |
724 delegate->GetTotalReceivedBytes()); | |
725 } | |
726 | |
727 TEST_P(BidirectionalStreamQuicImplTest, ServerSendsRstAfterHeaders) { | |
728 SetRequest("GET", "/", DEFAULT_PRIORITY); | |
729 size_t spdy_request_headers_frame_length; | |
730 AddWrite(ConstructRequestHeadersPacket(1, kFin, DEFAULT_PRIORITY, | |
731 &spdy_request_headers_frame_length)); | |
732 Initialize(); | |
733 | |
734 BidirectionalStreamRequestInfo request; | |
735 request.method = "GET"; | |
736 request.url = GURL("http://www.google.com/"); | |
737 request.end_stream_on_headers = true; | |
738 request.priority = DEFAULT_PRIORITY; | |
739 | |
740 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize)); | |
741 scoped_ptr<TestDelegateBase> delegate( | |
742 new TestDelegateBase(read_buffer.get(), kReadBufferSize)); | |
743 delegate->Start(&request, net_log(), session()->GetWeakPtr()); | |
744 delegate->WaitUntilNextCallback(); // OnHeadersSent | |
745 | |
746 // Server sends a Rst. | |
747 ProcessPacket(ConstructRstStreamPacket(1)); | |
748 | |
749 delegate->WaitUntilNextCallback(); // OnFailed | |
750 TestCompletionCallback cb; | |
751 EXPECT_EQ(ERR_QUIC_PROTOCOL_ERROR, delegate->ReadData(cb.callback())); | |
752 | |
753 base::MessageLoop::current()->RunUntilIdle(); | |
754 | |
755 EXPECT_EQ(ERR_QUIC_PROTOCOL_ERROR, delegate->error()); | |
756 EXPECT_EQ(0, delegate->on_data_read_count()); | |
757 EXPECT_EQ(0, delegate->on_data_sent_count()); | |
758 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length), | |
759 delegate->GetTotalSentBytes()); | |
760 EXPECT_EQ(0, delegate->GetTotalReceivedBytes()); | |
761 } | |
762 | |
763 TEST_P(BidirectionalStreamQuicImplTest, ServerSendsRstAfterReadData) { | |
764 SetRequest("GET", "/", DEFAULT_PRIORITY); | |
765 size_t spdy_request_headers_frame_length; | |
766 AddWrite(ConstructRequestHeadersPacket(1, kFin, DEFAULT_PRIORITY, | |
767 &spdy_request_headers_frame_length)); | |
768 // Why does QUIC ack Rst? Is this expected? | |
769 AddWrite(ConstructAckPacket(2, 3, 1)); | |
770 | |
771 Initialize(); | |
772 | |
773 BidirectionalStreamRequestInfo request; | |
774 request.method = "GET"; | |
775 request.url = GURL("http://www.google.com/"); | |
776 request.end_stream_on_headers = true; | |
777 request.priority = DEFAULT_PRIORITY; | |
778 | |
779 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize)); | |
780 scoped_ptr<TestDelegateBase> delegate( | |
781 new TestDelegateBase(read_buffer.get(), kReadBufferSize)); | |
782 delegate->Start(&request, net_log(), session()->GetWeakPtr()); | |
783 delegate->WaitUntilNextCallback(); // OnHeadersSent | |
784 | |
785 // Server acks the request. | |
786 ProcessPacket(ConstructAckPacket(1, 0, 0)); | |
787 | |
788 // Server sends the response headers. | |
789 SpdyHeaderBlock response_headers = ConstructResponseHeaders("200"); | |
790 | |
791 size_t spdy_response_headers_frame_length; | |
792 QuicStreamOffset offset = 0; | |
793 ProcessPacket(ConstructResponseHeadersPacket( | |
794 2, !kFin, response_headers, &spdy_response_headers_frame_length, | |
795 &offset)); | |
796 | |
797 delegate->WaitUntilNextCallback(); // OnHeadersReceived | |
798 EXPECT_EQ("200", delegate->response_headers().find(":status")->second); | |
799 | |
800 TestCompletionCallback cb; | |
801 int rv = delegate->ReadData(cb.callback()); | |
802 EXPECT_EQ(ERR_IO_PENDING, rv); | |
803 | |
804 // Server sends a Rst. | |
805 ProcessPacket(ConstructRstStreamPacket(3)); | |
806 | |
807 delegate->WaitUntilNextCallback(); // OnFailed | |
808 | |
809 EXPECT_EQ(ERR_QUIC_PROTOCOL_ERROR, delegate->ReadData(cb.callback())); | |
810 EXPECT_EQ(ERR_QUIC_PROTOCOL_ERROR, delegate->error()); | |
811 EXPECT_EQ(0, delegate->on_data_read_count()); | |
812 EXPECT_EQ(0, delegate->on_data_sent_count()); | |
813 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length), | |
814 delegate->GetTotalSentBytes()); | |
815 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length), | |
816 delegate->GetTotalReceivedBytes()); | |
817 } | |
818 | |
819 TEST_P(BidirectionalStreamQuicImplTest, CancelStreamAfterSendData) { | |
820 SetRequest("POST", "/", DEFAULT_PRIORITY); | |
821 size_t spdy_request_headers_frame_length; | |
822 AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY, | |
823 &spdy_request_headers_frame_length)); | |
824 AddWrite(ConstructAckAndDataPacket(2, !kIncludeVersion, 2, 1, !kFin, 0, | |
825 kUploadData)); | |
826 AddWrite(ConstructRstStreamCancelledPacket(3, strlen(kUploadData))); | |
827 | |
828 Initialize(); | |
829 | |
830 BidirectionalStreamRequestInfo request; | |
831 request.method = "POST"; | |
832 request.url = GURL("http://www.google.com/"); | |
833 request.end_stream_on_headers = false; | |
834 request.priority = DEFAULT_PRIORITY; | |
835 | |
836 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize)); | |
837 scoped_ptr<TestDelegateBase> delegate( | |
838 new TestDelegateBase(read_buffer.get(), kReadBufferSize)); | |
839 delegate->Start(&request, net_log(), session()->GetWeakPtr()); | |
840 delegate->WaitUntilNextCallback(); // OnHeadersSent | |
841 | |
842 // Server acks the request. | |
843 ProcessPacket(ConstructAckPacket(1, 0, 0)); | |
844 | |
845 // Server sends the response headers. | |
846 SpdyHeaderBlock response_headers = ConstructResponseHeaders("200"); | |
847 size_t spdy_response_headers_frame_length; | |
848 ProcessPacket(ConstructResponseHeadersPacket( | |
849 2, !kFin, response_headers, &spdy_response_headers_frame_length, 0)); | |
850 | |
851 delegate->WaitUntilNextCallback(); // OnHeadersReceived | |
852 EXPECT_EQ("200", delegate->response_headers().find(":status")->second); | |
853 | |
854 // Send a DATA frame. | |
855 scoped_refptr<StringIOBuffer> buf(new StringIOBuffer(kUploadData)); | |
856 | |
857 delegate->SendData(buf.get(), buf->size(), false); | |
858 delegate->WaitUntilNextCallback(); // OnDataSent | |
859 | |
860 delegate->CancelStream(); | |
861 base::MessageLoop::current()->RunUntilIdle(); | |
862 | |
863 EXPECT_EQ(0, delegate->on_data_read_count()); | |
864 EXPECT_EQ(1, delegate->on_data_sent_count()); | |
865 EXPECT_EQ(kProtoQUIC1SPDY3, delegate->GetProtocol()); | |
866 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length + | |
867 strlen(kUploadData)), | |
868 delegate->GetTotalSentBytes()); | |
869 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length), | |
870 delegate->GetTotalReceivedBytes()); | |
871 } | |
872 | |
873 TEST_P(BidirectionalStreamQuicImplTest, SessionClosedBeforeReadData) { | |
874 SetRequest("GET", "/", DEFAULT_PRIORITY); | |
875 size_t spdy_request_headers_frame_length; | |
876 AddWrite(ConstructRequestHeadersPacket(1, kFin, DEFAULT_PRIORITY, | |
877 &spdy_request_headers_frame_length)); | |
878 Initialize(); | |
879 | |
880 BidirectionalStreamRequestInfo request; | |
881 request.method = "GET"; | |
882 request.url = GURL("http://www.google.com/"); | |
883 request.end_stream_on_headers = true; | |
884 request.priority = DEFAULT_PRIORITY; | |
885 | |
886 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize)); | |
887 scoped_ptr<TestDelegateBase> delegate( | |
888 new TestDelegateBase(read_buffer.get(), kReadBufferSize)); | |
889 delegate->Start(&request, net_log(), session()->GetWeakPtr()); | |
890 delegate->WaitUntilNextCallback(); // OnHeadersSent | |
891 | |
892 // Server acks the request. | |
893 ProcessPacket(ConstructAckPacket(1, 0, 0)); | |
894 | |
895 // Server sends the response headers. | |
896 SpdyHeaderBlock response_headers = ConstructResponseHeaders("200"); | |
897 | |
898 size_t spdy_response_headers_frame_length; | |
899 QuicStreamOffset offset = 0; | |
900 ProcessPacket(ConstructResponseHeadersPacket( | |
901 2, !kFin, response_headers, &spdy_response_headers_frame_length, | |
902 &offset)); | |
903 | |
904 delegate->WaitUntilNextCallback(); // OnHeadersReceived | |
905 TestCompletionCallback cb; | |
906 int rv = delegate->ReadData(cb.callback()); | |
907 EXPECT_EQ(ERR_IO_PENDING, rv); | |
908 session()->connection()->CloseConnection(QUIC_NO_ERROR, | |
909 ConnectionCloseSource::FROM_PEER); | |
910 delegate->WaitUntilNextCallback(); // OnFailed | |
911 | |
912 base::MessageLoop::current()->RunUntilIdle(); | |
913 | |
914 EXPECT_EQ(ERR_UNEXPECTED, delegate->ReadData(cb.callback())); | |
915 EXPECT_EQ(ERR_UNEXPECTED, delegate->error()); | |
916 EXPECT_EQ(0, delegate->on_data_read_count()); | |
917 EXPECT_EQ(0, delegate->on_data_sent_count()); | |
918 EXPECT_EQ(kProtoQUIC1SPDY3, delegate->GetProtocol()); | |
919 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length), | |
920 delegate->GetTotalSentBytes()); | |
921 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length), | |
922 delegate->GetTotalReceivedBytes()); | |
923 } | |
924 | |
925 TEST_P(BidirectionalStreamQuicImplTest, CancelStreamAfterReadData) { | |
926 SetRequest("POST", "/", DEFAULT_PRIORITY); | |
927 size_t spdy_request_headers_frame_length; | |
928 AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY, | |
929 &spdy_request_headers_frame_length)); | |
930 AddWrite(ConstructAckAndRstStreamPacket(2, 2, 1, 1)); | |
931 | |
932 Initialize(); | |
933 | |
934 BidirectionalStreamRequestInfo request; | |
935 request.method = "POST"; | |
936 request.url = GURL("http://www.google.com/"); | |
937 request.end_stream_on_headers = false; | |
938 request.priority = DEFAULT_PRIORITY; | |
939 | |
940 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize)); | |
941 scoped_ptr<TestDelegateBase> delegate( | |
942 new TestDelegateBase(read_buffer.get(), kReadBufferSize)); | |
943 delegate->Start(&request, net_log(), session()->GetWeakPtr()); | |
944 delegate->WaitUntilNextCallback(); // OnHeadersSent | |
945 | |
946 // Server acks the request. | |
947 ProcessPacket(ConstructAckPacket(1, 0, 0)); | |
948 | |
949 // Server sends the response headers. | |
950 SpdyHeaderBlock response_headers = ConstructResponseHeaders("200"); | |
951 size_t spdy_response_headers_frame_length; | |
952 ProcessPacket(ConstructResponseHeadersPacket( | |
953 2, !kFin, response_headers, &spdy_response_headers_frame_length, 0)); | |
954 | |
955 delegate->WaitUntilNextCallback(); // OnHeadersReceived | |
956 EXPECT_EQ("200", delegate->response_headers().find(":status")->second); | |
957 | |
958 // Cancel the stream after ReadData returns ERR_IO_PENDING. | |
959 TestCompletionCallback cb; | |
960 EXPECT_EQ(ERR_IO_PENDING, delegate->ReadData(cb.callback())); | |
961 delegate->CancelStream(); | |
962 | |
963 base::MessageLoop::current()->RunUntilIdle(); | |
964 | |
965 EXPECT_EQ(0, delegate->on_data_read_count()); | |
966 EXPECT_EQ(0, delegate->on_data_sent_count()); | |
967 EXPECT_EQ(kProtoQUIC1SPDY3, delegate->GetProtocol()); | |
968 EXPECT_EQ(static_cast<int64_t>(spdy_request_headers_frame_length), | |
969 delegate->GetTotalSentBytes()); | |
970 EXPECT_EQ(static_cast<int64_t>(spdy_response_headers_frame_length), | |
971 delegate->GetTotalReceivedBytes()); | |
972 } | |
973 | |
974 TEST_P(BidirectionalStreamQuicImplTest, DeleteStreamDuringOnHeadersReceived) { | |
975 SetRequest("POST", "/", DEFAULT_PRIORITY); | |
976 size_t spdy_request_headers_frame_length; | |
977 AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY, | |
978 &spdy_request_headers_frame_length)); | |
979 AddWrite(ConstructAckAndRstStreamPacket(2, 2, 1, 1)); | |
980 | |
981 Initialize(); | |
982 | |
983 BidirectionalStreamRequestInfo request; | |
984 request.method = "POST"; | |
985 request.url = GURL("http://www.google.com/"); | |
986 request.end_stream_on_headers = false; | |
987 request.priority = DEFAULT_PRIORITY; | |
988 | |
989 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize)); | |
990 scoped_ptr<DeleteStreamDelegate> delegate(new DeleteStreamDelegate( | |
991 read_buffer.get(), kReadBufferSize, | |
992 DeleteStreamDelegate::ON_HEADERS_RECEIVED, true)); | |
993 delegate->Start(&request, net_log(), session()->GetWeakPtr()); | |
994 delegate->WaitUntilNextCallback(); // OnHeadersSent | |
995 | |
996 // Server acks the request. | |
997 ProcessPacket(ConstructAckPacket(1, 0, 0)); | |
998 | |
999 // Server sends the response headers. | |
1000 SpdyHeaderBlock response_headers = ConstructResponseHeaders("200"); | |
1001 | |
1002 size_t spdy_response_headers_frame_length; | |
1003 ProcessPacket(ConstructResponseHeadersPacket( | |
1004 2, !kFin, response_headers, &spdy_response_headers_frame_length, | |
1005 nullptr)); | |
1006 | |
1007 delegate->WaitUntilNextCallback(); // OnHeadersReceived | |
1008 EXPECT_EQ("200", delegate->response_headers().find(":status")->second); | |
1009 | |
1010 base::MessageLoop::current()->RunUntilIdle(); | |
1011 | |
1012 EXPECT_EQ(0, delegate->on_data_read_count()); | |
1013 EXPECT_EQ(0, delegate->on_data_sent_count()); | |
1014 } | |
1015 | |
1016 TEST_P(BidirectionalStreamQuicImplTest, DeleteStreamDuringOnDataRead) { | |
1017 SetRequest("POST", "/", DEFAULT_PRIORITY); | |
1018 size_t spdy_request_headers_frame_length; | |
1019 AddWrite(ConstructRequestHeadersPacket(1, !kFin, DEFAULT_PRIORITY, | |
1020 &spdy_request_headers_frame_length)); | |
1021 AddWrite(ConstructAckPacket(2, 3, 1)); | |
1022 AddWrite(ConstructRstStreamPacket(3)); | |
1023 | |
1024 Initialize(); | |
1025 | |
1026 BidirectionalStreamRequestInfo request; | |
1027 request.method = "POST"; | |
1028 request.url = GURL("http://www.google.com/"); | |
1029 request.end_stream_on_headers = false; | |
1030 request.priority = DEFAULT_PRIORITY; | |
1031 | |
1032 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize)); | |
1033 scoped_ptr<DeleteStreamDelegate> delegate( | |
1034 new DeleteStreamDelegate(read_buffer.get(), kReadBufferSize, | |
1035 DeleteStreamDelegate::ON_DATA_READ, true)); | |
1036 delegate->Start(&request, net_log(), session()->GetWeakPtr()); | |
1037 delegate->WaitUntilNextCallback(); // OnHeadersSent | |
1038 | |
1039 // Server acks the request. | |
1040 ProcessPacket(ConstructAckPacket(1, 0, 0)); | |
1041 | |
1042 // Server sends the response headers. | |
1043 SpdyHeaderBlock response_headers = ConstructResponseHeaders("200"); | |
1044 | |
1045 size_t spdy_response_headers_frame_length; | |
1046 ProcessPacket(ConstructResponseHeadersPacket( | |
1047 2, !kFin, response_headers, &spdy_response_headers_frame_length, | |
1048 nullptr)); | |
1049 | |
1050 delegate->WaitUntilNextCallback(); // OnHeadersReceived | |
1051 | |
1052 EXPECT_EQ("200", delegate->response_headers().find(":status")->second); | |
1053 | |
1054 TestCompletionCallback cb; | |
1055 int rv = delegate->ReadData(cb.callback()); | |
1056 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1057 const char kResponseBody[] = "Hello world!"; | |
1058 // Server sends data. | |
1059 ProcessPacket( | |
1060 ConstructDataPacket(3, !kIncludeVersion, !kFin, 0, kResponseBody)); | |
1061 EXPECT_EQ(static_cast<int64_t>(strlen(kResponseBody)), cb.WaitForResult()); | |
1062 | |
1063 base::MessageLoop::current()->RunUntilIdle(); | |
1064 | |
1065 EXPECT_EQ(1, delegate->on_data_read_count()); | |
1066 EXPECT_EQ(0, delegate->on_data_sent_count()); | |
1067 } | |
1068 | |
1069 TEST_P(BidirectionalStreamQuicImplTest, DeleteStreamDuringOnTrailersReceived) { | |
1070 SetRequest("GET", "/", DEFAULT_PRIORITY); | |
1071 size_t spdy_request_headers_frame_length; | |
1072 AddWrite(ConstructRequestHeadersPacket(1, kFin, DEFAULT_PRIORITY, | |
1073 &spdy_request_headers_frame_length)); | |
1074 AddWrite(ConstructAckPacket(2, 3, 1)); // Ack the data packet | |
1075 | |
1076 Initialize(); | |
1077 | |
1078 BidirectionalStreamRequestInfo request; | |
1079 request.method = "GET"; | |
1080 request.url = GURL("http://www.google.com/"); | |
1081 request.end_stream_on_headers = true; | |
1082 request.priority = DEFAULT_PRIORITY; | |
1083 | |
1084 scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize)); | |
1085 scoped_ptr<DeleteStreamDelegate> delegate(new DeleteStreamDelegate( | |
1086 read_buffer.get(), kReadBufferSize, | |
1087 DeleteStreamDelegate::ON_TRAILERS_RECEIVED, true)); | |
1088 delegate->Start(&request, net_log(), session()->GetWeakPtr()); | |
1089 delegate->WaitUntilNextCallback(); // OnHeadersSent | |
1090 | |
1091 // Server acks the request. | |
1092 ProcessPacket(ConstructAckPacket(1, 0, 0)); | |
1093 | |
1094 // Server sends the response headers. | |
1095 SpdyHeaderBlock response_headers = ConstructResponseHeaders("200"); | |
1096 | |
1097 QuicStreamOffset offset = 0; | |
1098 size_t spdy_response_headers_frame_length; | |
1099 ProcessPacket(ConstructResponseHeadersPacket( | |
1100 2, !kFin, response_headers, &spdy_response_headers_frame_length, | |
1101 &offset)); | |
1102 | |
1103 delegate->WaitUntilNextCallback(); // OnHeadersReceived | |
1104 | |
1105 EXPECT_EQ("200", delegate->response_headers().find(":status")->second); | |
1106 | |
1107 TestCompletionCallback cb; | |
1108 int rv = delegate->ReadData(cb.callback()); | |
1109 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1110 const char kResponseBody[] = "Hello world!"; | |
1111 // Server sends data. | |
1112 ProcessPacket( | |
1113 ConstructDataPacket(3, !kIncludeVersion, !kFin, 0, kResponseBody)); | |
1114 | |
1115 EXPECT_EQ(static_cast<int64_t>(strlen(kResponseBody)), cb.WaitForResult()); | |
1116 EXPECT_EQ(std::string(kResponseBody), delegate->data_received()); | |
1117 | |
1118 size_t spdy_trailers_frame_length; | |
1119 SpdyHeaderBlock trailers; | |
1120 trailers["foo"] = "bar"; | |
1121 trailers[kFinalOffsetHeaderKey] = base::IntToString(strlen(kResponseBody)); | |
1122 // Server sends trailers. | |
1123 ProcessPacket(ConstructResponseTrailersPacket( | |
1124 4, kFin, trailers, &spdy_trailers_frame_length, &offset)); | |
1125 | |
1126 delegate->WaitUntilNextCallback(); // OnTrailersReceived | |
1127 trailers.erase(kFinalOffsetHeaderKey); | |
1128 EXPECT_EQ(trailers, delegate->trailers()); | |
1129 | |
1130 base::MessageLoop::current()->RunUntilIdle(); | |
1131 | |
1132 EXPECT_EQ(1, delegate->on_data_read_count()); | |
1133 EXPECT_EQ(0, delegate->on_data_sent_count()); | |
1134 } | |
1135 | |
1136 } // namespace test | |
1137 | |
1138 } // namespace net | |
OLD | NEW |