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

Side by Side Diff: net/spdy/spdy_stream_unittest.cc

Issue 2832973003: Split net/spdy into core and chromium subdirectories. (Closed)
Patch Set: Fix some more build rules. Created 3 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
« no previous file with comments | « net/spdy/spdy_stream_test_util.cc ('k') | net/spdy/spdy_test_util_common.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2013 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/spdy_stream.h"
6
7 #include <stdint.h>
8
9 #include <algorithm>
10 #include <cstddef>
11 #include <limits>
12 #include <memory>
13 #include <utility>
14 #include <vector>
15
16 #include "base/memory/ref_counted.h"
17 #include "base/run_loop.h"
18 #include "net/base/completion_callback.h"
19 #include "net/base/request_priority.h"
20 #include "net/log/net_log_event_type.h"
21 #include "net/log/test_net_log.h"
22 #include "net/log/test_net_log_entry.h"
23 #include "net/log/test_net_log_util.h"
24 #include "net/socket/socket_test_util.h"
25 #include "net/spdy/buffered_spdy_framer.h"
26 #include "net/spdy/platform/api/spdy_string_piece.h"
27 #include "net/spdy/spdy_http_utils.h"
28 #include "net/spdy/spdy_protocol.h"
29 #include "net/spdy/spdy_session.h"
30 #include "net/spdy/spdy_stream_test_util.h"
31 #include "net/spdy/spdy_test_util_common.h"
32 #include "net/test/cert_test_util.h"
33 #include "net/test/gtest_util.h"
34 #include "net/test/test_data_directory.h"
35 #include "testing/gmock/include/gmock/gmock.h"
36 #include "testing/gtest/include/gtest/gtest.h"
37
38 // TODO(ukai): factor out common part with spdy_http_stream_unittest.cc
39 //
40 namespace net {
41
42 namespace test {
43
44 namespace {
45
46 const char kPushUrl[] = "https://www.example.org/push";
47 const char kPostBody[] = "\0hello!\xff";
48 const size_t kPostBodyLength = arraysize(kPostBody);
49 const SpdyStringPiece kPostBodyStringPiece(kPostBody, kPostBodyLength);
50
51 static base::TimeTicks g_time_now;
52
53 base::TimeTicks InstantaneousReads() {
54 return g_time_now;
55 }
56
57 } // namespace
58
59 class SpdyStreamTest : public ::testing::Test {
60 protected:
61 // A function that takes a SpdyStream and the number of bytes which
62 // will unstall the next frame completely.
63 typedef base::Callback<void(const base::WeakPtr<SpdyStream>&, int32_t)>
64 UnstallFunction;
65
66 SpdyStreamTest()
67 : url_(kDefaultUrl),
68 session_(SpdySessionDependencies::SpdyCreateSession(&session_deps_)),
69 offset_(0),
70 ssl_(SYNCHRONOUS, OK) {}
71
72 ~SpdyStreamTest() override {}
73
74 base::WeakPtr<SpdySession> CreateDefaultSpdySession() {
75 SpdySessionKey key(HostPortPair::FromURL(url_), ProxyServer::Direct(),
76 PRIVACY_MODE_DISABLED);
77 return CreateSecureSpdySession(session_.get(), key, NetLogWithSource());
78 }
79
80 void TearDown() override { base::RunLoop().RunUntilIdle(); }
81
82 void RunResumeAfterUnstallRequestResponseTest(
83 const UnstallFunction& unstall_function);
84
85 void RunResumeAfterUnstallBidirectionalTest(
86 const UnstallFunction& unstall_function);
87
88 // Add{Read,Write}() populates lists that are eventually passed to a
89 // SocketData class. |frame| must live for the whole test.
90
91 void AddRead(const SpdySerializedFrame& frame) {
92 reads_.push_back(CreateMockRead(frame, offset_++));
93 }
94
95 void AddWrite(const SpdySerializedFrame& frame) {
96 writes_.push_back(CreateMockWrite(frame, offset_++));
97 }
98
99 void AddReadEOF() {
100 reads_.push_back(MockRead(ASYNC, 0, offset_++));
101 }
102
103 void AddWritePause() {
104 writes_.push_back(MockWrite(ASYNC, ERR_IO_PENDING, offset_++));
105 }
106
107 void AddReadPause() {
108 reads_.push_back(MockRead(ASYNC, ERR_IO_PENDING, offset_++));
109 }
110
111 MockRead* GetReads() { return reads_.data(); }
112
113 size_t GetNumReads() const {
114 return reads_.size();
115 }
116
117 MockWrite* GetWrites() { return writes_.data(); }
118
119 int GetNumWrites() const {
120 return writes_.size();
121 }
122
123 void ActivatePushStream(SpdySession* session, SpdyStream* stream) {
124 std::unique_ptr<SpdyStream> activated =
125 session->ActivateCreatedStream(stream);
126 activated->set_stream_id(2);
127 session->InsertActivatedStream(std::move(activated));
128 }
129
130 void AddSSLSocketData() {
131 // Load a cert that is valid for
132 // www.example.org, mail.example.org, and mail.example.com.
133 ssl_.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
134 ASSERT_TRUE(ssl_.cert);
135 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_);
136 }
137
138 const GURL url_;
139 SpdyTestUtil spdy_util_;
140 SpdySessionDependencies session_deps_;
141 std::unique_ptr<HttpNetworkSession> session_;
142
143 private:
144 // Used by Add{Read,Write}() above.
145 std::vector<MockWrite> writes_;
146 std::vector<MockRead> reads_;
147 int offset_;
148 SSLSocketDataProvider ssl_;
149 };
150
151 TEST_F(SpdyStreamTest, SendDataAfterOpen) {
152 SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
153 kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0));
154 AddWrite(req);
155
156 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
157 AddRead(resp);
158
159 SpdySerializedFrame msg(
160 spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, false));
161 AddWrite(msg);
162
163 SpdySerializedFrame echo(
164 spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, false));
165 AddRead(echo);
166
167 AddReadEOF();
168
169 SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(),
170 GetNumWrites());
171 MockConnect connect_data(SYNCHRONOUS, OK);
172 data.set_connect_data(connect_data);
173 session_deps_.socket_factory->AddSocketDataProvider(&data);
174
175 AddSSLSocketData();
176
177 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
178
179 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
180 SPDY_BIDIRECTIONAL_STREAM, session, url_, LOWEST, NetLogWithSource());
181 ASSERT_TRUE(stream);
182
183 StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece);
184 stream->SetDelegate(&delegate);
185
186 EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
187
188 SpdyHeaderBlock headers(
189 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength));
190 EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND),
191 IsError(ERR_IO_PENDING));
192 EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
193
194 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
195
196 EXPECT_TRUE(delegate.send_headers_completed());
197 EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
198 EXPECT_EQ(SpdyString(kPostBody, kPostBodyLength),
199 delegate.TakeReceivedData());
200 EXPECT_TRUE(data.AllWriteDataConsumed());
201 }
202
203 // Delegate that receives trailers.
204 class StreamDelegateWithTrailers : public test::StreamDelegateWithBody {
205 public:
206 StreamDelegateWithTrailers(const base::WeakPtr<SpdyStream>& stream,
207 SpdyStringPiece data)
208 : StreamDelegateWithBody(stream, data) {}
209
210 ~StreamDelegateWithTrailers() override {}
211
212 void OnTrailers(const SpdyHeaderBlock& trailers) override {
213 trailers_ = trailers.Clone();
214 }
215
216 const SpdyHeaderBlock& trailers() const { return trailers_; }
217
218 private:
219 SpdyHeaderBlock trailers_;
220 };
221
222 // Regression test for https://crbug.com/481033.
223 TEST_F(SpdyStreamTest, Trailers) {
224 SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
225 kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0));
226 AddWrite(req);
227
228 SpdySerializedFrame msg(
229 spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, true));
230 AddWrite(msg);
231
232 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
233 AddRead(resp);
234
235 SpdySerializedFrame echo(
236 spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, false));
237 AddRead(echo);
238
239 SpdyHeaderBlock late_headers;
240 late_headers["foo"] = "bar";
241 SpdySerializedFrame trailers(spdy_util_.ConstructSpdyResponseHeaders(
242 1, std::move(late_headers), false));
243 AddRead(trailers);
244
245 AddReadEOF();
246
247 SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(),
248 GetNumWrites());
249 MockConnect connect_data(SYNCHRONOUS, OK);
250 data.set_connect_data(connect_data);
251 session_deps_.socket_factory->AddSocketDataProvider(&data);
252
253 AddSSLSocketData();
254
255 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
256
257 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
258 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
259 ASSERT_TRUE(stream);
260
261 StreamDelegateWithTrailers delegate(stream, kPostBodyStringPiece);
262 stream->SetDelegate(&delegate);
263
264 EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
265
266 SpdyHeaderBlock headers(
267 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength));
268 EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND),
269 IsError(ERR_IO_PENDING));
270 EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
271
272 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
273
274 EXPECT_TRUE(delegate.send_headers_completed());
275 EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
276 const SpdyHeaderBlock& received_trailers = delegate.trailers();
277 SpdyHeaderBlock::const_iterator it = received_trailers.find("foo");
278 EXPECT_EQ("bar", it->second);
279 EXPECT_EQ(SpdyString(kPostBody, kPostBodyLength),
280 delegate.TakeReceivedData());
281 EXPECT_TRUE(data.AllWriteDataConsumed());
282 }
283
284 TEST_F(SpdyStreamTest, PushedStream) {
285 SpdySerializedFrame req(
286 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
287 AddWrite(req);
288
289 SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
290 AddRead(reply);
291
292 SpdySerializedFrame push(
293 spdy_util_.ConstructSpdyPush(nullptr, 0, 2, 1, kPushUrl));
294 AddRead(push);
295
296 SpdySerializedFrame priority(
297 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
298 AddWrite(priority);
299
300 AddReadPause();
301
302 SpdyStringPiece pushed_msg("foo");
303 SpdySerializedFrame pushed_body(spdy_util_.ConstructSpdyDataFrame(
304 2, pushed_msg.data(), pushed_msg.size(), true));
305 AddRead(pushed_body);
306
307 SpdyStringPiece msg("bar");
308 SpdySerializedFrame body(
309 spdy_util_.ConstructSpdyDataFrame(1, msg.data(), msg.size(), true));
310 AddRead(body);
311
312 AddReadEOF();
313
314 SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(),
315 GetNumWrites());
316 MockConnect connect_data(SYNCHRONOUS, OK);
317 data.set_connect_data(connect_data);
318 session_deps_.socket_factory->AddSocketDataProvider(&data);
319
320 AddSSLSocketData();
321
322 g_time_now = base::TimeTicks::Now();
323 session_deps_.time_func = InstantaneousReads;
324 session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
325
326 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
327
328 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
329 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
330 ASSERT_TRUE(stream);
331
332 StreamDelegateDoNothing delegate(stream);
333 stream->SetDelegate(&delegate);
334
335 EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
336
337 SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
338 EXPECT_THAT(
339 stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND),
340 IsError(ERR_IO_PENDING));
341 EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
342
343 data.RunUntilPaused();
344
345 SpdyStream* push_stream;
346 EXPECT_THAT(session->GetPushStream(GURL(kPushUrl), IDLE, &push_stream,
347 NetLogWithSource()),
348 IsOk());
349 ASSERT_TRUE(push_stream);
350 EXPECT_EQ(kPushUrl, push_stream->GetUrlFromHeaders().spec());
351
352 LoadTimingInfo load_timing_info;
353 EXPECT_TRUE(push_stream->GetLoadTimingInfo(&load_timing_info));
354 EXPECT_EQ(g_time_now, load_timing_info.push_start);
355 EXPECT_TRUE(load_timing_info.push_end.is_null());
356
357 StreamDelegateDoNothing push_delegate(push_stream->GetWeakPtr());
358 push_stream->SetDelegate(&push_delegate);
359
360 data.Resume();
361
362 EXPECT_TRUE(push_stream->GetLoadTimingInfo(&load_timing_info));
363 EXPECT_EQ(g_time_now, load_timing_info.push_start);
364 EXPECT_FALSE(load_timing_info.push_end.is_null());
365
366 EXPECT_THAT(delegate.WaitForClose(), IsOk());
367 EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
368 EXPECT_EQ(msg, delegate.TakeReceivedData());
369
370 EXPECT_THAT(push_delegate.WaitForClose(), IsOk());
371 EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
372 EXPECT_EQ(pushed_msg, push_delegate.TakeReceivedData());
373 }
374
375 TEST_F(SpdyStreamTest, StreamError) {
376 SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
377 kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0));
378 AddWrite(req);
379
380 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
381 AddRead(resp);
382
383 SpdySerializedFrame msg(
384 spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, false));
385 AddWrite(msg);
386
387 SpdySerializedFrame echo(
388 spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, false));
389 AddRead(echo);
390
391 AddReadEOF();
392
393 BoundTestNetLog log;
394
395 SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(),
396 GetNumWrites());
397 MockConnect connect_data(SYNCHRONOUS, OK);
398 data.set_connect_data(connect_data);
399 session_deps_.socket_factory->AddSocketDataProvider(&data);
400
401 AddSSLSocketData();
402
403 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
404
405 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
406 SPDY_BIDIRECTIONAL_STREAM, session, url_, LOWEST, log.bound());
407 ASSERT_TRUE(stream);
408
409 StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece);
410 stream->SetDelegate(&delegate);
411
412 EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
413
414 SpdyHeaderBlock headers(
415 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength));
416 EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND),
417 IsError(ERR_IO_PENDING));
418 EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
419
420 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
421
422 const SpdyStreamId stream_id = delegate.stream_id();
423
424 EXPECT_TRUE(delegate.send_headers_completed());
425 EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
426 EXPECT_EQ(SpdyString(kPostBody, kPostBodyLength),
427 delegate.TakeReceivedData());
428 EXPECT_TRUE(data.AllWriteDataConsumed());
429
430 // Check that the NetLog was filled reasonably.
431 TestNetLogEntry::List entries;
432 log.GetEntries(&entries);
433 EXPECT_LT(0u, entries.size());
434
435 // Check that we logged SPDY_STREAM_ERROR correctly.
436 int pos = ExpectLogContainsSomewhere(
437 entries, 0, NetLogEventType::HTTP2_STREAM_ERROR, NetLogEventPhase::NONE);
438
439 int stream_id2;
440 ASSERT_TRUE(entries[pos].GetIntegerValue("stream_id", &stream_id2));
441 EXPECT_EQ(static_cast<int>(stream_id), stream_id2);
442 }
443
444 // Make sure that large blocks of data are properly split up into frame-sized
445 // chunks for a request/response (i.e., an HTTP-like) stream.
446 TEST_F(SpdyStreamTest, SendLargeDataAfterOpenRequestResponse) {
447 SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
448 kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0));
449 AddWrite(req);
450
451 SpdyString chunk_data(kMaxSpdyFrameChunkSize, 'x');
452 SpdySerializedFrame chunk(spdy_util_.ConstructSpdyDataFrame(
453 1, chunk_data.data(), chunk_data.length(), false));
454 AddWrite(chunk);
455 AddWrite(chunk);
456
457 SpdySerializedFrame last_chunk(spdy_util_.ConstructSpdyDataFrame(
458 1, chunk_data.data(), chunk_data.length(), true));
459 AddWrite(last_chunk);
460
461 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
462 AddRead(resp);
463
464 AddReadEOF();
465
466 SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(),
467 GetNumWrites());
468 MockConnect connect_data(SYNCHRONOUS, OK);
469 data.set_connect_data(connect_data);
470 session_deps_.socket_factory->AddSocketDataProvider(&data);
471
472 AddSSLSocketData();
473
474 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
475
476 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
477 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
478 ASSERT_TRUE(stream);
479
480 SpdyString body_data(3 * kMaxSpdyFrameChunkSize, 'x');
481 StreamDelegateWithBody delegate(stream, body_data);
482 stream->SetDelegate(&delegate);
483
484 EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
485
486 SpdyHeaderBlock headers(
487 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength));
488 EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND),
489 IsError(ERR_IO_PENDING));
490 EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
491
492 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
493
494 EXPECT_TRUE(delegate.send_headers_completed());
495 EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
496 EXPECT_EQ(SpdyString(), delegate.TakeReceivedData());
497 EXPECT_TRUE(data.AllWriteDataConsumed());
498 }
499
500 // Make sure that large blocks of data are properly split up into frame-sized
501 // chunks for a bidirectional (i.e., non-HTTP-like) stream.
502 TEST_F(SpdyStreamTest, SendLargeDataAfterOpenBidirectional) {
503 SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
504 kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0));
505 AddWrite(req);
506
507 SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0));
508 AddRead(resp);
509
510 SpdyString chunk_data(kMaxSpdyFrameChunkSize, 'x');
511 SpdySerializedFrame chunk(spdy_util_.ConstructSpdyDataFrame(
512 1, chunk_data.data(), chunk_data.length(), false));
513 AddWrite(chunk);
514 AddWrite(chunk);
515 AddWrite(chunk);
516
517 AddReadEOF();
518
519 SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(),
520 GetNumWrites());
521 MockConnect connect_data(SYNCHRONOUS, OK);
522 data.set_connect_data(connect_data);
523 session_deps_.socket_factory->AddSocketDataProvider(&data);
524
525 AddSSLSocketData();
526
527 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
528
529 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
530 SPDY_BIDIRECTIONAL_STREAM, session, url_, LOWEST, NetLogWithSource());
531 ASSERT_TRUE(stream);
532
533 SpdyString body_data(3 * kMaxSpdyFrameChunkSize, 'x');
534 StreamDelegateSendImmediate delegate(stream, body_data);
535 stream->SetDelegate(&delegate);
536
537 EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
538
539 SpdyHeaderBlock headers(
540 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength));
541 EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND),
542 IsError(ERR_IO_PENDING));
543 EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
544
545 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
546
547 EXPECT_TRUE(delegate.send_headers_completed());
548 EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
549 EXPECT_EQ(SpdyString(), delegate.TakeReceivedData());
550 EXPECT_TRUE(data.AllWriteDataConsumed());
551 }
552
553 // Receiving a header with uppercase ASCII should result in a protocol error.
554 TEST_F(SpdyStreamTest, UpperCaseHeaders) {
555 SpdySerializedFrame req(
556 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
557 AddWrite(req);
558
559 const char* const kExtraHeaders[] = {"X-UpperCase", "yes"};
560 SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(
561 kExtraHeaders, arraysize(kExtraHeaders) / 2, 1));
562 AddRead(reply);
563
564 SpdySerializedFrame rst(
565 spdy_util_.ConstructSpdyRstStream(1, ERROR_CODE_PROTOCOL_ERROR));
566 AddWrite(rst);
567
568 AddReadEOF();
569
570 SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(),
571 GetNumWrites());
572 MockConnect connect_data(SYNCHRONOUS, OK);
573 data.set_connect_data(connect_data);
574 session_deps_.socket_factory->AddSocketDataProvider(&data);
575
576 AddSSLSocketData();
577
578 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
579
580 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
581 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
582 ASSERT_TRUE(stream);
583
584 StreamDelegateDoNothing delegate(stream);
585 stream->SetDelegate(&delegate);
586
587 EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
588
589 SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
590 EXPECT_THAT(
591 stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND),
592 IsError(ERR_IO_PENDING));
593 EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
594
595 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_SPDY_PROTOCOL_ERROR));
596
597 // Finish async network reads and writes.
598 base::RunLoop().RunUntilIdle();
599
600 EXPECT_TRUE(data.AllWriteDataConsumed());
601 EXPECT_TRUE(data.AllReadDataConsumed());
602 }
603
604 // Receiving a header with uppercase ASCII should result in a protocol error
605 // even for a push stream.
606 TEST_F(SpdyStreamTest, UpperCaseHeadersOnPush) {
607 SpdySerializedFrame req(
608 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
609 AddWrite(req);
610
611 SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
612 AddRead(reply);
613
614 const char* const kExtraHeaders[] = {"X-UpperCase", "yes"};
615 SpdySerializedFrame push(spdy_util_.ConstructSpdyPush(
616 kExtraHeaders, arraysize(kExtraHeaders) / 2, 2, 1, kPushUrl));
617 AddRead(push);
618
619 SpdySerializedFrame priority(
620 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
621 AddWrite(priority);
622
623 SpdySerializedFrame rst(
624 spdy_util_.ConstructSpdyRstStream(2, ERROR_CODE_PROTOCOL_ERROR));
625 AddWrite(rst);
626
627 AddReadPause();
628
629 AddReadEOF();
630
631 SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(),
632 GetNumWrites());
633 MockConnect connect_data(SYNCHRONOUS, OK);
634 data.set_connect_data(connect_data);
635 session_deps_.socket_factory->AddSocketDataProvider(&data);
636
637 AddSSLSocketData();
638
639 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
640
641 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
642 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
643 ASSERT_TRUE(stream);
644
645 StreamDelegateDoNothing delegate(stream);
646 stream->SetDelegate(&delegate);
647
648 EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
649
650 SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
651 EXPECT_THAT(
652 stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND),
653 IsError(ERR_IO_PENDING));
654 EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
655
656 data.RunUntilPaused();
657
658 SpdyStream* push_stream;
659 EXPECT_THAT(session->GetPushStream(GURL(kPushUrl), IDLE, &push_stream,
660 NetLogWithSource()),
661 IsOk());
662 EXPECT_FALSE(push_stream);
663
664 data.Resume();
665
666 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
667
668 EXPECT_TRUE(data.AllWriteDataConsumed());
669 EXPECT_TRUE(data.AllReadDataConsumed());
670 }
671
672 TEST_F(SpdyStreamTest, HeadersMustHaveStatus) {
673 SpdySerializedFrame req(
674 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
675 AddWrite(req);
676
677 // Response headers without ":status" header field: protocol error.
678 SpdyHeaderBlock header_block_without_status;
679 header_block_without_status[spdy_util_.GetMethodKey()] = "GET";
680 header_block_without_status[spdy_util_.GetHostKey()] = "www.example.org";
681 header_block_without_status[spdy_util_.GetSchemeKey()] = "https";
682 header_block_without_status[spdy_util_.GetPathKey()] = "/";
683 SpdySerializedFrame reply(
684 spdy_util_.ConstructSpdyReply(1, std::move(header_block_without_status)));
685 AddRead(reply);
686
687 SpdySerializedFrame rst(
688 spdy_util_.ConstructSpdyRstStream(1, ERROR_CODE_PROTOCOL_ERROR));
689 AddWrite(rst);
690
691 AddReadEOF();
692
693 SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(),
694 GetNumWrites());
695 MockConnect connect_data(SYNCHRONOUS, OK);
696 data.set_connect_data(connect_data);
697 session_deps_.socket_factory->AddSocketDataProvider(&data);
698
699 AddSSLSocketData();
700
701 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
702
703 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
704 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
705 ASSERT_TRUE(stream);
706
707 StreamDelegateDoNothing delegate(stream);
708 stream->SetDelegate(&delegate);
709
710 EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
711
712 SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
713 EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers),
714 NO_MORE_DATA_TO_SEND));
715 EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
716
717 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_SPDY_PROTOCOL_ERROR));
718
719 // Finish async network reads and writes.
720 base::RunLoop().RunUntilIdle();
721
722 EXPECT_TRUE(data.AllWriteDataConsumed());
723 EXPECT_TRUE(data.AllReadDataConsumed());
724 }
725
726 TEST_F(SpdyStreamTest, HeadersMustHaveStatusOnPushedStream) {
727 SpdySerializedFrame req(
728 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
729 AddWrite(req);
730
731 SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
732 AddRead(reply);
733
734 SpdySerializedFrame push_promise(spdy_util_.ConstructInitialSpdyPushFrame(
735 spdy_util_.ConstructGetHeaderBlock(kPushUrl), 2, 1));
736 AddRead(push_promise);
737
738 SpdySerializedFrame priority(
739 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
740 AddWrite(priority);
741
742 // Response headers without ":status" header field: protocol error.
743 SpdyHeaderBlock header_block_without_status;
744 header_block_without_status[spdy_util_.GetMethodKey()] = "GET";
745 header_block_without_status[spdy_util_.GetHostKey()] = "www.example.org";
746 header_block_without_status[spdy_util_.GetSchemeKey()] = "https";
747 header_block_without_status[spdy_util_.GetPathKey()] = "/";
748 SpdySerializedFrame pushed_reply(
749 spdy_util_.ConstructSpdyReply(2, std::move(header_block_without_status)));
750 AddRead(pushed_reply);
751
752 SpdySerializedFrame rst(
753 spdy_util_.ConstructSpdyRstStream(2, ERROR_CODE_PROTOCOL_ERROR));
754 AddWrite(rst);
755
756 SpdySerializedFrame body(
757 spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, true));
758 AddRead(body);
759
760 AddReadEOF();
761
762 SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(),
763 GetNumWrites());
764 MockConnect connect_data(SYNCHRONOUS, OK);
765 data.set_connect_data(connect_data);
766 session_deps_.socket_factory->AddSocketDataProvider(&data);
767
768 AddSSLSocketData();
769
770 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
771
772 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
773 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
774 ASSERT_TRUE(stream);
775
776 StreamDelegateDoNothing delegate(stream);
777 stream->SetDelegate(&delegate);
778
779 EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
780
781 SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
782 EXPECT_THAT(
783 stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND),
784 IsError(ERR_IO_PENDING));
785 EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
786
787 EXPECT_THAT(delegate.WaitForClose(), IsOk());
788 EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
789 EXPECT_EQ(SpdyString(kPostBody, kPostBodyLength),
790 delegate.TakeReceivedData());
791
792 // Finish async network reads and writes.
793 base::RunLoop().RunUntilIdle();
794
795 EXPECT_TRUE(data.AllWriteDataConsumed());
796 EXPECT_TRUE(data.AllReadDataConsumed());
797 }
798
799 TEST_F(SpdyStreamTest, HeadersMustPreceedData) {
800 SpdySerializedFrame req(
801 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
802 AddWrite(req);
803
804 // Response body not preceeded by headers: protocol error.
805 SpdySerializedFrame body(
806 spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, true));
807 AddRead(body);
808
809 SpdySerializedFrame rst(
810 spdy_util_.ConstructSpdyRstStream(1, ERROR_CODE_PROTOCOL_ERROR));
811 AddWrite(rst);
812
813 AddReadEOF();
814
815 SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(),
816 GetNumWrites());
817 MockConnect connect_data(SYNCHRONOUS, OK);
818 data.set_connect_data(connect_data);
819 session_deps_.socket_factory->AddSocketDataProvider(&data);
820
821 AddSSLSocketData();
822
823 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
824
825 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
826 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
827 ASSERT_TRUE(stream);
828
829 StreamDelegateDoNothing delegate(stream);
830 stream->SetDelegate(&delegate);
831
832 EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
833
834 SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
835 EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers),
836 NO_MORE_DATA_TO_SEND));
837 EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
838
839 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_SPDY_PROTOCOL_ERROR));
840 }
841
842 TEST_F(SpdyStreamTest, HeadersMustPreceedDataOnPushedStream) {
843 SpdySerializedFrame req(
844 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
845 AddWrite(req);
846
847 SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
848 AddRead(reply);
849
850 SpdySerializedFrame push_promise(spdy_util_.ConstructInitialSpdyPushFrame(
851 spdy_util_.ConstructGetHeaderBlock(kPushUrl), 2, 1));
852 AddRead(push_promise);
853
854 SpdySerializedFrame priority(
855 spdy_util_.ConstructSpdyPriority(2, 1, IDLE, true));
856 AddWrite(priority);
857
858 SpdySerializedFrame pushed_body(
859 spdy_util_.ConstructSpdyDataFrame(2, kPostBody, kPostBodyLength, true));
860 AddRead(pushed_body);
861
862 SpdySerializedFrame rst(
863 spdy_util_.ConstructSpdyRstStream(2, ERROR_CODE_PROTOCOL_ERROR));
864 AddWrite(rst);
865
866 SpdySerializedFrame body(
867 spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, true));
868 AddRead(body);
869
870 AddReadEOF();
871
872 SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(),
873 GetNumWrites());
874 MockConnect connect_data(SYNCHRONOUS, OK);
875 data.set_connect_data(connect_data);
876 session_deps_.socket_factory->AddSocketDataProvider(&data);
877
878 AddSSLSocketData();
879
880 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
881
882 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
883 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
884 ASSERT_TRUE(stream);
885
886 StreamDelegateDoNothing delegate(stream);
887 stream->SetDelegate(&delegate);
888
889 EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
890
891 SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
892 EXPECT_THAT(
893 stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND),
894 IsError(ERR_IO_PENDING));
895 EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
896
897 EXPECT_THAT(delegate.WaitForClose(), IsOk());
898 EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
899 EXPECT_EQ(SpdyString(kPostBody, kPostBodyLength),
900 delegate.TakeReceivedData());
901
902 // Finish async network reads and writes.
903 base::RunLoop().RunUntilIdle();
904
905 EXPECT_TRUE(data.AllWriteDataConsumed());
906 EXPECT_TRUE(data.AllReadDataConsumed());
907 }
908
909 TEST_F(SpdyStreamTest, TrailersMustNotFollowTrailers) {
910 SpdySerializedFrame req(
911 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
912 AddWrite(req);
913
914 SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
915 AddRead(reply);
916
917 SpdySerializedFrame body(
918 spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, false));
919 AddRead(body);
920
921 SpdyHeaderBlock trailers_block;
922 trailers_block["foo"] = "bar";
923 SpdySerializedFrame first_trailers(spdy_util_.ConstructSpdyResponseHeaders(
924 1, std::move(trailers_block), false));
925 AddRead(first_trailers);
926
927 // Trailers following trailers: procotol error.
928 SpdySerializedFrame second_trailers(spdy_util_.ConstructSpdyResponseHeaders(
929 1, std::move(trailers_block), true));
930 AddRead(second_trailers);
931
932 SpdySerializedFrame rst(
933 spdy_util_.ConstructSpdyRstStream(1, ERROR_CODE_PROTOCOL_ERROR));
934 AddWrite(rst);
935
936 AddReadEOF();
937
938 SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(),
939 GetNumWrites());
940 MockConnect connect_data(SYNCHRONOUS, OK);
941 data.set_connect_data(connect_data);
942 session_deps_.socket_factory->AddSocketDataProvider(&data);
943
944 AddSSLSocketData();
945
946 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
947
948 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
949 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
950 ASSERT_TRUE(stream);
951
952 StreamDelegateDoNothing delegate(stream);
953 stream->SetDelegate(&delegate);
954
955 EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
956
957 SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
958 EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers),
959 NO_MORE_DATA_TO_SEND));
960 EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
961
962 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_SPDY_PROTOCOL_ERROR));
963
964 // Finish async network reads and writes.
965 base::RunLoop().RunUntilIdle();
966
967 EXPECT_TRUE(data.AllWriteDataConsumed());
968 EXPECT_TRUE(data.AllReadDataConsumed());
969 }
970
971 TEST_F(SpdyStreamTest, DataMustNotFollowTrailers) {
972 SpdySerializedFrame req(
973 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
974 AddWrite(req);
975
976 SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
977 AddRead(reply);
978
979 SpdySerializedFrame body(
980 spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, false));
981 AddRead(body);
982
983 SpdyHeaderBlock trailers_block;
984 trailers_block["foo"] = "bar";
985 SpdySerializedFrame trailers(spdy_util_.ConstructSpdyResponseHeaders(
986 1, std::move(trailers_block), false));
987 AddRead(trailers);
988
989 // DATA frame following trailers: protocol error.
990 AddRead(body);
991
992 SpdySerializedFrame rst(
993 spdy_util_.ConstructSpdyRstStream(1, ERROR_CODE_PROTOCOL_ERROR));
994 AddWrite(rst);
995
996 AddReadEOF();
997
998 SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(),
999 GetNumWrites());
1000 MockConnect connect_data(SYNCHRONOUS, OK);
1001 data.set_connect_data(connect_data);
1002 session_deps_.socket_factory->AddSocketDataProvider(&data);
1003
1004 AddSSLSocketData();
1005
1006 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
1007
1008 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
1009 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
1010 ASSERT_TRUE(stream);
1011
1012 StreamDelegateDoNothing delegate(stream);
1013 stream->SetDelegate(&delegate);
1014
1015 EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
1016
1017 SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
1018 EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers),
1019 NO_MORE_DATA_TO_SEND));
1020 EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
1021
1022 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_SPDY_PROTOCOL_ERROR));
1023
1024 // Finish async network reads and writes.
1025 base::RunLoop().RunUntilIdle();
1026
1027 EXPECT_TRUE(data.AllWriteDataConsumed());
1028 EXPECT_TRUE(data.AllReadDataConsumed());
1029 }
1030
1031 TEST_F(SpdyStreamTest, InformationalHeaders) {
1032 SpdySerializedFrame req(
1033 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
1034 AddWrite(req);
1035
1036 SpdyHeaderBlock informational_headers;
1037 informational_headers[":status"] = "100";
1038 SpdySerializedFrame informational_response(
1039 spdy_util_.ConstructSpdyResponseHeaders(
1040 1, std::move(informational_headers), false));
1041 AddRead(informational_response);
1042
1043 SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1044 AddRead(reply);
1045
1046 SpdySerializedFrame body(
1047 spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, true));
1048 AddRead(body);
1049
1050 AddReadEOF();
1051
1052 SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(),
1053 GetNumWrites());
1054 MockConnect connect_data(SYNCHRONOUS, OK);
1055 data.set_connect_data(connect_data);
1056 session_deps_.socket_factory->AddSocketDataProvider(&data);
1057
1058 AddSSLSocketData();
1059
1060 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
1061
1062 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
1063 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
1064 ASSERT_TRUE(stream);
1065
1066 StreamDelegateDoNothing delegate(stream);
1067 stream->SetDelegate(&delegate);
1068
1069 EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
1070
1071 SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
1072 EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers),
1073 NO_MORE_DATA_TO_SEND));
1074 EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
1075
1076 EXPECT_THAT(delegate.WaitForClose(), IsOk());
1077 EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
1078 EXPECT_EQ(SpdyString(kPostBody, kPostBodyLength),
1079 delegate.TakeReceivedData());
1080
1081 // Finish async network reads and writes.
1082 base::RunLoop().RunUntilIdle();
1083
1084 EXPECT_TRUE(data.AllWriteDataConsumed());
1085 EXPECT_TRUE(data.AllReadDataConsumed());
1086 }
1087
1088 TEST_F(SpdyStreamTest, StatusMustBeNumber) {
1089 SpdySerializedFrame req(
1090 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
1091 AddWrite(req);
1092
1093 SpdyHeaderBlock incorrect_headers;
1094 incorrect_headers[":status"] = "nan";
1095 SpdySerializedFrame reply(spdy_util_.ConstructSpdyResponseHeaders(
1096 1, std::move(incorrect_headers), false));
1097 AddRead(reply);
1098
1099 SpdySerializedFrame rst(
1100 spdy_util_.ConstructSpdyRstStream(1, ERROR_CODE_PROTOCOL_ERROR));
1101 AddWrite(rst);
1102
1103 AddReadEOF();
1104
1105 SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(),
1106 GetNumWrites());
1107 MockConnect connect_data(SYNCHRONOUS, OK);
1108 data.set_connect_data(connect_data);
1109 session_deps_.socket_factory->AddSocketDataProvider(&data);
1110
1111 AddSSLSocketData();
1112
1113 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
1114
1115 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
1116 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
1117 ASSERT_TRUE(stream);
1118
1119 StreamDelegateDoNothing delegate(stream);
1120 stream->SetDelegate(&delegate);
1121
1122 EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
1123
1124 SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
1125 EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers),
1126 NO_MORE_DATA_TO_SEND));
1127 EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
1128
1129 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_SPDY_PROTOCOL_ERROR));
1130
1131 // Finish async network reads and writes.
1132 base::RunLoop().RunUntilIdle();
1133
1134 EXPECT_TRUE(data.AllWriteDataConsumed());
1135 EXPECT_TRUE(data.AllReadDataConsumed());
1136 }
1137
1138 TEST_F(SpdyStreamTest, StatusCannotHaveExtraText) {
1139 SpdySerializedFrame req(
1140 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
1141 AddWrite(req);
1142
1143 SpdyHeaderBlock headers_with_status_text;
1144 headers_with_status_text[":status"] =
1145 "200 Some random extra text describing status";
1146 SpdySerializedFrame reply(spdy_util_.ConstructSpdyResponseHeaders(
1147 1, std::move(headers_with_status_text), false));
1148 AddRead(reply);
1149
1150 SpdySerializedFrame body(
1151 spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, true));
1152 AddRead(body);
1153
1154 SpdySerializedFrame rst(
1155 spdy_util_.ConstructSpdyRstStream(1, ERROR_CODE_PROTOCOL_ERROR));
1156 AddWrite(rst);
1157
1158 AddReadEOF();
1159
1160 SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(),
1161 GetNumWrites());
1162 MockConnect connect_data(SYNCHRONOUS, OK);
1163 data.set_connect_data(connect_data);
1164 session_deps_.socket_factory->AddSocketDataProvider(&data);
1165
1166 AddSSLSocketData();
1167
1168 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
1169
1170 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
1171 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
1172 ASSERT_TRUE(stream);
1173
1174 StreamDelegateDoNothing delegate(stream);
1175 stream->SetDelegate(&delegate);
1176
1177 EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
1178
1179 SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
1180 EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers),
1181 NO_MORE_DATA_TO_SEND));
1182 EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
1183
1184 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_SPDY_PROTOCOL_ERROR));
1185
1186 // Finish async network reads and writes.
1187 base::RunLoop().RunUntilIdle();
1188
1189 EXPECT_TRUE(data.AllWriteDataConsumed());
1190 EXPECT_TRUE(data.AllReadDataConsumed());
1191 }
1192
1193 TEST_F(SpdyStreamTest, StatusMustBePresent) {
1194 SpdySerializedFrame req(
1195 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
1196 AddWrite(req);
1197
1198 SpdyHeaderBlock headers_without_status;
1199 SpdySerializedFrame reply(spdy_util_.ConstructSpdyResponseHeaders(
1200 1, std::move(headers_without_status), false));
1201 AddRead(reply);
1202
1203 SpdySerializedFrame body(
1204 spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, true));
1205 AddRead(body);
1206
1207 SpdySerializedFrame rst(
1208 spdy_util_.ConstructSpdyRstStream(1, ERROR_CODE_PROTOCOL_ERROR));
1209 AddWrite(rst);
1210
1211 AddReadEOF();
1212
1213 SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(),
1214 GetNumWrites());
1215 MockConnect connect_data(SYNCHRONOUS, OK);
1216 data.set_connect_data(connect_data);
1217 session_deps_.socket_factory->AddSocketDataProvider(&data);
1218
1219 AddSSLSocketData();
1220
1221 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
1222
1223 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
1224 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
1225 ASSERT_TRUE(stream);
1226
1227 StreamDelegateDoNothing delegate(stream);
1228 stream->SetDelegate(&delegate);
1229
1230 EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
1231
1232 SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
1233 EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers),
1234 NO_MORE_DATA_TO_SEND));
1235 EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
1236
1237 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_SPDY_PROTOCOL_ERROR));
1238
1239 // Finish async network reads and writes.
1240 base::RunLoop().RunUntilIdle();
1241
1242 EXPECT_TRUE(data.AllWriteDataConsumed());
1243 EXPECT_TRUE(data.AllReadDataConsumed());
1244 }
1245
1246 // Call IncreaseSendWindowSize on a stream with a large enough delta to overflow
1247 // an int32_t. The SpdyStream should handle that case gracefully.
1248 TEST_F(SpdyStreamTest, IncreaseSendWindowSizeOverflow) {
1249 SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
1250 kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0));
1251 AddWrite(req);
1252
1253 AddReadPause();
1254
1255 // Triggered by the overflowing call to IncreaseSendWindowSize
1256 // below.
1257 SpdySerializedFrame rst(
1258 spdy_util_.ConstructSpdyRstStream(1, ERROR_CODE_FLOW_CONTROL_ERROR));
1259 AddWrite(rst);
1260
1261 AddReadEOF();
1262
1263 BoundTestNetLog log;
1264
1265 SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(),
1266 GetNumWrites());
1267 MockConnect connect_data(SYNCHRONOUS, OK);
1268 data.set_connect_data(connect_data);
1269 session_deps_.socket_factory->AddSocketDataProvider(&data);
1270
1271 AddSSLSocketData();
1272
1273 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
1274
1275 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
1276 SPDY_BIDIRECTIONAL_STREAM, session, url_, LOWEST, log.bound());
1277 ASSERT_TRUE(stream);
1278 StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece);
1279 stream->SetDelegate(&delegate);
1280
1281 SpdyHeaderBlock headers(
1282 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength));
1283 EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND),
1284 IsError(ERR_IO_PENDING));
1285 EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
1286
1287 data.RunUntilPaused();
1288
1289 int32_t old_send_window_size = stream->send_window_size();
1290 ASSERT_GT(old_send_window_size, 0);
1291 int32_t delta_window_size =
1292 std::numeric_limits<int32_t>::max() - old_send_window_size + 1;
1293 stream->IncreaseSendWindowSize(delta_window_size);
1294 EXPECT_FALSE(stream);
1295
1296 data.Resume();
1297 base::RunLoop().RunUntilIdle();
1298
1299 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_SPDY_PROTOCOL_ERROR));
1300 }
1301
1302 // Functions used with
1303 // RunResumeAfterUnstall{RequestResponse,Bidirectional}Test().
1304
1305 void StallStream(const base::WeakPtr<SpdyStream>& stream) {
1306 // Reduce the send window size to 0 to stall.
1307 while (stream->send_window_size() > 0) {
1308 stream->DecreaseSendWindowSize(
1309 std::min(kMaxSpdyFrameChunkSize, stream->send_window_size()));
1310 }
1311 }
1312
1313 void IncreaseStreamSendWindowSize(const base::WeakPtr<SpdyStream>& stream,
1314 int32_t delta_window_size) {
1315 EXPECT_TRUE(stream->send_stalled_by_flow_control());
1316 stream->IncreaseSendWindowSize(delta_window_size);
1317 EXPECT_FALSE(stream->send_stalled_by_flow_control());
1318 }
1319
1320 void AdjustStreamSendWindowSize(const base::WeakPtr<SpdyStream>& stream,
1321 int32_t delta_window_size) {
1322 // Make sure that negative adjustments are handled properly.
1323 EXPECT_TRUE(stream->send_stalled_by_flow_control());
1324 stream->AdjustSendWindowSize(-delta_window_size);
1325 EXPECT_TRUE(stream->send_stalled_by_flow_control());
1326 stream->AdjustSendWindowSize(+delta_window_size);
1327 EXPECT_TRUE(stream->send_stalled_by_flow_control());
1328 stream->AdjustSendWindowSize(+delta_window_size);
1329 EXPECT_FALSE(stream->send_stalled_by_flow_control());
1330 }
1331
1332 // Given an unstall function, runs a test to make sure that a
1333 // request/response (i.e., an HTTP-like) stream resumes after a stall
1334 // and unstall.
1335 void SpdyStreamTest::RunResumeAfterUnstallRequestResponseTest(
1336 const UnstallFunction& unstall_function) {
1337 SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
1338 kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0));
1339 AddWrite(req);
1340
1341 SpdySerializedFrame body(
1342 spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, true));
1343 AddWrite(body);
1344
1345 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1346 AddRead(resp);
1347
1348 AddReadEOF();
1349
1350 SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(),
1351 GetNumWrites());
1352 MockConnect connect_data(SYNCHRONOUS, OK);
1353 data.set_connect_data(connect_data);
1354 session_deps_.socket_factory->AddSocketDataProvider(&data);
1355
1356 AddSSLSocketData();
1357
1358 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
1359
1360 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
1361 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
1362 ASSERT_TRUE(stream);
1363
1364 StreamDelegateWithBody delegate(stream, kPostBodyStringPiece);
1365 stream->SetDelegate(&delegate);
1366
1367 EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
1368 EXPECT_FALSE(stream->send_stalled_by_flow_control());
1369
1370 SpdyHeaderBlock headers(
1371 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength));
1372 EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND),
1373 IsError(ERR_IO_PENDING));
1374 EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
1375
1376 StallStream(stream);
1377
1378 base::RunLoop().RunUntilIdle();
1379
1380 EXPECT_TRUE(stream->send_stalled_by_flow_control());
1381
1382 unstall_function.Run(stream, kPostBodyLength);
1383
1384 EXPECT_FALSE(stream->send_stalled_by_flow_control());
1385
1386 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
1387
1388 EXPECT_TRUE(delegate.send_headers_completed());
1389 EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
1390 EXPECT_EQ(SpdyString(), delegate.TakeReceivedData());
1391 EXPECT_TRUE(data.AllWriteDataConsumed());
1392 }
1393
1394 TEST_F(SpdyStreamTest, ResumeAfterSendWindowSizeIncreaseRequestResponse) {
1395 RunResumeAfterUnstallRequestResponseTest(
1396 base::Bind(&IncreaseStreamSendWindowSize));
1397 }
1398
1399 TEST_F(SpdyStreamTest, ResumeAfterSendWindowSizeAdjustRequestResponse) {
1400 RunResumeAfterUnstallRequestResponseTest(
1401 base::Bind(&AdjustStreamSendWindowSize));
1402 }
1403
1404 // Given an unstall function, runs a test to make sure that a bidirectional
1405 // (i.e., non-HTTP-like) stream resumes after a stall and unstall.
1406 void SpdyStreamTest::RunResumeAfterUnstallBidirectionalTest(
1407 const UnstallFunction& unstall_function) {
1408 SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
1409 kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0));
1410 AddWrite(req);
1411
1412 AddReadPause();
1413
1414 SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1415 AddRead(resp);
1416
1417 SpdySerializedFrame msg(
1418 spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, false));
1419 AddWrite(msg);
1420
1421 SpdySerializedFrame echo(
1422 spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, false));
1423 AddRead(echo);
1424
1425 AddReadEOF();
1426
1427 SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(),
1428 GetNumWrites());
1429 MockConnect connect_data(SYNCHRONOUS, OK);
1430 data.set_connect_data(connect_data);
1431 session_deps_.socket_factory->AddSocketDataProvider(&data);
1432
1433 AddSSLSocketData();
1434
1435 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
1436
1437 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
1438 SPDY_BIDIRECTIONAL_STREAM, session, url_, LOWEST, NetLogWithSource());
1439 ASSERT_TRUE(stream);
1440
1441 StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece);
1442 stream->SetDelegate(&delegate);
1443
1444 EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
1445
1446 SpdyHeaderBlock headers(
1447 spdy_util_.ConstructPostHeaderBlock(kDefaultUrl, kPostBodyLength));
1448 EXPECT_THAT(stream->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND),
1449 IsError(ERR_IO_PENDING));
1450 EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
1451
1452 data.RunUntilPaused();
1453
1454 EXPECT_FALSE(stream->send_stalled_by_flow_control());
1455
1456 StallStream(stream);
1457
1458 data.Resume();
1459 base::RunLoop().RunUntilIdle();
1460
1461 EXPECT_TRUE(stream->send_stalled_by_flow_control());
1462
1463 unstall_function.Run(stream, kPostBodyLength);
1464
1465 EXPECT_FALSE(stream->send_stalled_by_flow_control());
1466
1467 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
1468
1469 EXPECT_TRUE(delegate.send_headers_completed());
1470 EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
1471 EXPECT_EQ(SpdyString(kPostBody, kPostBodyLength),
1472 delegate.TakeReceivedData());
1473 EXPECT_TRUE(data.AllWriteDataConsumed());
1474 }
1475
1476 TEST_F(SpdyStreamTest, ResumeAfterSendWindowSizeIncreaseBidirectional) {
1477 RunResumeAfterUnstallBidirectionalTest(
1478 base::Bind(&IncreaseStreamSendWindowSize));
1479 }
1480
1481 TEST_F(SpdyStreamTest, ResumeAfterSendWindowSizeAdjustBidirectional) {
1482 RunResumeAfterUnstallBidirectionalTest(
1483 base::Bind(&AdjustStreamSendWindowSize));
1484 }
1485
1486 // Test calculation of amount of bytes received from network.
1487 TEST_F(SpdyStreamTest, ReceivedBytes) {
1488 SpdySerializedFrame req(
1489 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
1490 AddWrite(req);
1491
1492 AddReadPause();
1493
1494 SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1495 AddRead(reply);
1496
1497 AddReadPause();
1498
1499 SpdySerializedFrame msg(
1500 spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, false));
1501 AddRead(msg);
1502
1503 AddReadPause();
1504
1505 AddReadEOF();
1506
1507 SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(),
1508 GetNumWrites());
1509 MockConnect connect_data(SYNCHRONOUS, OK);
1510 data.set_connect_data(connect_data);
1511 session_deps_.socket_factory->AddSocketDataProvider(&data);
1512
1513 AddSSLSocketData();
1514
1515 base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
1516
1517 base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
1518 SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
1519 ASSERT_TRUE(stream);
1520
1521 StreamDelegateDoNothing delegate(stream);
1522 stream->SetDelegate(&delegate);
1523
1524 EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
1525
1526 SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
1527 EXPECT_THAT(
1528 stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND),
1529 IsError(ERR_IO_PENDING));
1530 EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
1531
1532 int64_t reply_frame_len = reply.size();
1533 int64_t data_header_len = kDataFrameMinimumSize;
1534 int64_t data_frame_len = data_header_len + kPostBodyLength;
1535 int64_t response_len = reply_frame_len + data_frame_len;
1536
1537 EXPECT_EQ(0, stream->raw_received_bytes());
1538
1539 // REQUEST
1540 data.RunUntilPaused();
1541 EXPECT_EQ(0, stream->raw_received_bytes());
1542
1543 // REPLY
1544 data.Resume();
1545 data.RunUntilPaused();
1546 EXPECT_EQ(reply_frame_len, stream->raw_received_bytes());
1547
1548 // DATA
1549 data.Resume();
1550 data.RunUntilPaused();
1551 EXPECT_EQ(response_len, stream->raw_received_bytes());
1552
1553 // FIN
1554 data.Resume();
1555 EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
1556 }
1557
1558 } // namespace test
1559
1560 } // namespace net
OLDNEW
« no previous file with comments | « net/spdy/spdy_stream_test_util.cc ('k') | net/spdy/spdy_test_util_common.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698