Compute if a layer is clipped outside CalcDrawProps
[chromium-blink-merge.git] / net / quic / quic_headers_stream_test.cc
blob4e417b2238e73564385ae4e19ba518652c8af21b
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.
5 #include "net/quic/quic_headers_stream.h"
7 #include "net/quic/quic_utils.h"
8 #include "net/quic/spdy_utils.h"
9 #include "net/quic/test_tools/quic_connection_peer.h"
10 #include "net/quic/test_tools/quic_spdy_session_peer.h"
11 #include "net/quic/test_tools/quic_test_utils.h"
12 #include "net/quic/test_tools/reliable_quic_stream_peer.h"
13 #include "net/spdy/spdy_protocol.h"
14 #include "testing/gtest/include/gtest/gtest.h"
16 using base::StringPiece;
17 using std::ostream;
18 using std::string;
19 using std::vector;
20 using testing::Invoke;
21 using testing::StrictMock;
22 using testing::WithArgs;
23 using testing::_;
25 namespace net {
26 namespace test {
27 namespace {
29 class MockVisitor : public SpdyFramerVisitorInterface {
30 public:
31 MOCK_METHOD1(OnError, void(SpdyFramer* framer));
32 MOCK_METHOD3(OnDataFrameHeader, void(SpdyStreamId stream_id,
33 size_t length,
34 bool fin));
35 MOCK_METHOD4(OnStreamFrameData, void(SpdyStreamId stream_id,
36 const char* data,
37 size_t len,
38 bool fin));
39 MOCK_METHOD2(OnStreamPadding, void(SpdyStreamId stream_id, size_t len));
40 MOCK_METHOD3(OnControlFrameHeaderData, bool(SpdyStreamId stream_id,
41 const char* header_data,
42 size_t len));
43 MOCK_METHOD5(OnSynStream, void(SpdyStreamId stream_id,
44 SpdyStreamId associated_stream_id,
45 SpdyPriority priority,
46 bool fin,
47 bool unidirectional));
48 MOCK_METHOD2(OnSynReply, void(SpdyStreamId stream_id, bool fin));
49 MOCK_METHOD2(OnRstStream, void(SpdyStreamId stream_id,
50 SpdyRstStreamStatus status));
51 MOCK_METHOD1(OnSettings, void(bool clear_persisted));
52 MOCK_METHOD3(OnSetting, void(SpdySettingsIds id, uint8 flags, uint32 value));
53 MOCK_METHOD0(OnSettingsAck, void());
54 MOCK_METHOD0(OnSettingsEnd, void());
55 MOCK_METHOD2(OnPing, void(SpdyPingId unique_id, bool is_ack));
56 MOCK_METHOD2(OnGoAway, void(SpdyStreamId last_accepted_stream_id,
57 SpdyGoAwayStatus status));
58 MOCK_METHOD7(OnHeaders,
59 void(SpdyStreamId stream_id,
60 bool has_priority,
61 SpdyPriority priority,
62 SpdyStreamId parent_stream_id,
63 bool exclusive,
64 bool fin,
65 bool end));
66 MOCK_METHOD2(OnWindowUpdate,
67 void(SpdyStreamId stream_id, int delta_window_size));
68 MOCK_METHOD2(OnCredentialFrameData, bool(const char* credential_data,
69 size_t len));
70 MOCK_METHOD1(OnBlocked, void(SpdyStreamId stream_id));
71 MOCK_METHOD3(OnPushPromise, void(SpdyStreamId stream_id,
72 SpdyStreamId promised_stream_id,
73 bool end));
74 MOCK_METHOD2(OnContinuation, void(SpdyStreamId stream_id, bool end));
75 MOCK_METHOD3(OnAltSvc,
76 void(SpdyStreamId stream_id,
77 StringPiece origin,
78 const SpdyAltSvcWireFormat::AlternativeServiceVector&
79 altsvc_vector));
80 MOCK_METHOD2(OnUnknownFrame, bool(SpdyStreamId stream_id, int frame_type));
83 // Run all tests with each version, and client or server
84 struct TestParams {
85 TestParams(QuicVersion version, Perspective perspective)
86 : version(version), perspective(perspective) {}
88 friend ostream& operator<<(ostream& os, const TestParams& p) {
89 os << "{ version: " << QuicVersionToString(p.version);
90 os << ", perspective: " << p.perspective << " }";
91 return os;
94 QuicVersion version;
95 Perspective perspective;
98 // Constructs various test permutations.
99 vector<TestParams> GetTestParams() {
100 vector<TestParams> params;
101 QuicVersionVector all_supported_versions = QuicSupportedVersions();
102 for (const QuicVersion version : all_supported_versions) {
103 params.push_back(TestParams(version, Perspective::IS_CLIENT));
104 params.push_back(TestParams(version, Perspective::IS_SERVER));
106 return params;
109 class QuicHeadersStreamTest : public ::testing::TestWithParam<TestParams> {
110 public:
111 QuicHeadersStreamTest()
112 : connection_(
113 new StrictMock<MockConnection>(perspective(), GetVersion())),
114 session_(connection_),
115 headers_stream_(QuicSpdySessionPeer::GetHeadersStream(&session_)),
116 body_("hello world"),
117 framer_(HTTP2) {
118 headers_[":version"] = "HTTP/1.1";
119 headers_[":status"] = "200 Ok";
120 headers_["content-length"] = "11";
121 framer_.set_visitor(&visitor_);
122 EXPECT_EQ(version(), session_.connection()->version());
123 EXPECT_TRUE(headers_stream_ != nullptr);
124 VLOG(1) << GetParam();
127 QuicConsumedData SaveIov(const QuicIOVector& data) {
128 const iovec* iov = data.iov;
129 int count = data.iov_count;
130 for (int i = 0 ; i < count; ++i) {
131 saved_data_.append(static_cast<char*>(iov[i].iov_base), iov[i].iov_len);
133 return QuicConsumedData(saved_data_.length(), false);
136 bool SaveHeaderData(const char* data, int len) {
137 saved_header_data_.append(data, len);
138 return true;
141 void SaveHeaderDataStringPiece(StringPiece data) {
142 saved_header_data_.append(data.data(), data.length());
145 void WriteHeadersAndExpectSynStream(QuicStreamId stream_id,
146 bool fin,
147 QuicPriority priority) {
148 WriteHeadersAndCheckData(stream_id, fin, priority, SYN_STREAM);
151 void WriteHeadersAndExpectSynReply(QuicStreamId stream_id,
152 bool fin) {
153 WriteHeadersAndCheckData(stream_id, fin, 0, SYN_REPLY);
156 void WriteHeadersAndCheckData(QuicStreamId stream_id,
157 bool fin,
158 QuicPriority priority,
159 SpdyFrameType type) {
160 // Write the headers and capture the outgoing data
161 EXPECT_CALL(session_, WritevData(kHeadersStreamId, _, _, false, _, nullptr))
162 .WillOnce(WithArgs<1>(Invoke(this, &QuicHeadersStreamTest::SaveIov)));
163 headers_stream_->WriteHeaders(stream_id, headers_, fin, priority, nullptr);
165 // Parse the outgoing data and check that it matches was was written.
166 if (type == SYN_STREAM) {
167 EXPECT_CALL(visitor_, OnHeaders(stream_id, kHasPriority, priority,
168 /*parent_stream_id=*/0,
169 /*exclusive=*/false,
171 fin, kFrameComplete));
172 } else {
173 EXPECT_CALL(visitor_,
174 OnHeaders(stream_id, !kHasPriority,
175 /*priority=*/0,
176 /*parent_stream_id=*/0,
177 /*exclusive=*/false, fin, kFrameComplete));
179 EXPECT_CALL(visitor_, OnControlFrameHeaderData(stream_id, _, _))
180 .WillRepeatedly(WithArgs<1, 2>(
181 Invoke(this, &QuicHeadersStreamTest::SaveHeaderData)));
182 if (fin) {
183 EXPECT_CALL(visitor_, OnStreamFrameData(stream_id, nullptr, 0, true));
185 framer_.ProcessInput(saved_data_.data(), saved_data_.length());
186 EXPECT_FALSE(framer_.HasError())
187 << SpdyFramer::ErrorCodeToString(framer_.error_code());
189 CheckHeaders();
190 saved_data_.clear();
193 void CheckHeaders() {
194 SpdyHeaderBlock headers;
195 EXPECT_EQ(saved_header_data_.length(),
196 framer_.ParseHeaderBlockInBuffer(saved_header_data_.data(),
197 saved_header_data_.length(),
198 &headers));
199 EXPECT_EQ(headers_, headers);
200 saved_header_data_.clear();
203 Perspective perspective() { return GetParam().perspective; }
205 QuicVersion version() { return GetParam().version; }
207 QuicVersionVector GetVersion() {
208 QuicVersionVector versions;
209 versions.push_back(version());
210 return versions;
213 void CloseConnection() {
214 QuicConnectionPeer::CloseConnection(connection_);
217 static const bool kFrameComplete = true;
218 static const bool kHasPriority = true;
220 StrictMock<MockConnection>* connection_;
221 StrictMock<MockQuicSpdySession> session_;
222 QuicHeadersStream* headers_stream_;
223 SpdyHeaderBlock headers_;
224 string body_;
225 string saved_data_;
226 string saved_header_data_;
227 SpdyFramer framer_;
228 StrictMock<MockVisitor> visitor_;
231 INSTANTIATE_TEST_CASE_P(Tests,
232 QuicHeadersStreamTest,
233 ::testing::ValuesIn(GetTestParams()));
235 TEST_P(QuicHeadersStreamTest, StreamId) {
236 EXPECT_EQ(3u, headers_stream_->id());
239 TEST_P(QuicHeadersStreamTest, EffectivePriority) {
240 EXPECT_EQ(0u, headers_stream_->EffectivePriority());
243 TEST_P(QuicHeadersStreamTest, WriteHeaders) {
244 for (QuicStreamId stream_id = kClientDataStreamId1;
245 stream_id < kClientDataStreamId3; stream_id += 2) {
246 for (int count = 0; count < 2; ++count) {
247 bool fin = (count == 0);
248 if (perspective() == Perspective::IS_SERVER) {
249 WriteHeadersAndExpectSynReply(stream_id, fin);
250 } else {
251 for (QuicPriority priority = 0; priority < 7; ++priority) {
252 // TODO(rch): implement priorities correctly.
253 WriteHeadersAndExpectSynStream(stream_id, fin, 0);
260 TEST_P(QuicHeadersStreamTest, ProcessRawData) {
261 for (QuicStreamId stream_id = kClientDataStreamId1;
262 stream_id < kClientDataStreamId3; stream_id += 2) {
263 for (int count = 0; count < 2; ++count) {
264 bool fin = (count == 0);
265 for (QuicPriority priority = 0; priority < 7; ++priority) {
266 // Replace with "WriteHeadersAndSaveData"
267 scoped_ptr<SpdySerializedFrame> frame;
268 if (perspective() == Perspective::IS_SERVER) {
269 SpdyHeadersIR headers_frame(stream_id);
270 headers_frame.set_name_value_block(headers_);
271 headers_frame.set_fin(fin);
272 headers_frame.set_has_priority(true);
273 frame.reset(framer_.SerializeFrame(headers_frame));
274 EXPECT_CALL(session_, OnStreamHeadersPriority(stream_id, 0));
275 } else {
276 SpdyHeadersIR headers_frame(stream_id);
277 headers_frame.set_name_value_block(headers_);
278 headers_frame.set_fin(fin);
279 frame.reset(framer_.SerializeFrame(headers_frame));
281 EXPECT_CALL(session_, OnStreamHeaders(stream_id, _))
282 .WillRepeatedly(WithArgs<1>(
283 Invoke(this,
284 &QuicHeadersStreamTest::SaveHeaderDataStringPiece)));
285 EXPECT_CALL(session_,
286 OnStreamHeadersComplete(stream_id, fin, frame->size()));
287 headers_stream_->ProcessRawData(frame->data(), frame->size());
288 CheckHeaders();
294 TEST_P(QuicHeadersStreamTest, ProcessLargeRawData) {
295 // We want to create a frame that is more than the SPDY Framer's max control
296 // frame size, which is 16K, but less than the HPACK decoders max decode
297 // buffer size, which is 32K.
298 headers_["key0"] = string(1 << 13, '.');
299 headers_["key1"] = string(1 << 13, '.');
300 headers_["key2"] = string(1 << 13, '.');
301 for (QuicStreamId stream_id = kClientDataStreamId1;
302 stream_id < kClientDataStreamId3; stream_id += 2) {
303 for (int count = 0; count < 2; ++count) {
304 bool fin = (count == 0);
305 for (QuicPriority priority = 0; priority < 7; ++priority) {
306 // Replace with "WriteHeadersAndSaveData"
307 scoped_ptr<SpdySerializedFrame> frame;
308 if (perspective() == Perspective::IS_SERVER) {
309 SpdyHeadersIR headers_frame(stream_id);
310 headers_frame.set_name_value_block(headers_);
311 headers_frame.set_fin(fin);
312 headers_frame.set_has_priority(true);
313 frame.reset(framer_.SerializeFrame(headers_frame));
314 EXPECT_CALL(session_, OnStreamHeadersPriority(stream_id, 0));
315 } else {
316 SpdyHeadersIR headers_frame(stream_id);
317 headers_frame.set_name_value_block(headers_);
318 headers_frame.set_fin(fin);
319 frame.reset(framer_.SerializeFrame(headers_frame));
321 EXPECT_CALL(session_, OnStreamHeaders(stream_id, _))
322 .WillRepeatedly(WithArgs<1>(Invoke(
323 this, &QuicHeadersStreamTest::SaveHeaderDataStringPiece)));
324 EXPECT_CALL(session_,
325 OnStreamHeadersComplete(stream_id, fin, frame->size()));
326 headers_stream_->ProcessRawData(frame->data(), frame->size());
327 CheckHeaders();
333 TEST_P(QuicHeadersStreamTest, ProcessBadData) {
334 const char kBadData[] = "blah blah blah";
335 EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(
336 QUIC_INVALID_HEADERS_STREAM_DATA, _))
337 .Times(::testing::AnyNumber());
338 headers_stream_->ProcessRawData(kBadData, strlen(kBadData));
341 TEST_P(QuicHeadersStreamTest, ProcessSpdyDataFrame) {
342 SpdyDataIR data(2, "");
343 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
344 EXPECT_CALL(*connection_,
345 SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
346 "SPDY DATA frame received."))
347 .WillOnce(InvokeWithoutArgs(this,
348 &QuicHeadersStreamTest::CloseConnection));
349 headers_stream_->ProcessRawData(frame->data(), frame->size());
352 TEST_P(QuicHeadersStreamTest, ProcessSpdyRstStreamFrame) {
353 SpdyRstStreamIR data(2, RST_STREAM_PROTOCOL_ERROR, "");
354 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
355 EXPECT_CALL(*connection_,
356 SendConnectionCloseWithDetails(
357 QUIC_INVALID_HEADERS_STREAM_DATA,
358 "SPDY RST_STREAM frame received."))
359 .WillOnce(InvokeWithoutArgs(this,
360 &QuicHeadersStreamTest::CloseConnection));
361 headers_stream_->ProcessRawData(frame->data(), frame->size());
364 TEST_P(QuicHeadersStreamTest, ProcessSpdySettingsFrame) {
365 SpdySettingsIR data;
366 data.AddSetting(SETTINGS_HEADER_TABLE_SIZE, true, true, 0);
367 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
368 EXPECT_CALL(*connection_,
369 SendConnectionCloseWithDetails(
370 QUIC_INVALID_HEADERS_STREAM_DATA,
371 "SPDY SETTINGS frame received."))
372 .WillOnce(InvokeWithoutArgs(this,
373 &QuicHeadersStreamTest::CloseConnection));
374 headers_stream_->ProcessRawData(frame->data(), frame->size());
377 TEST_P(QuicHeadersStreamTest, ProcessSpdyPingFrame) {
378 SpdyPingIR data(1);
379 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
380 EXPECT_CALL(*connection_,
381 SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
382 "SPDY PING frame received."))
383 .WillOnce(InvokeWithoutArgs(this,
384 &QuicHeadersStreamTest::CloseConnection));
385 headers_stream_->ProcessRawData(frame->data(), frame->size());
388 TEST_P(QuicHeadersStreamTest, ProcessSpdyGoAwayFrame) {
389 SpdyGoAwayIR data(1, GOAWAY_PROTOCOL_ERROR, "go away");
390 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
391 EXPECT_CALL(*connection_,
392 SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
393 "SPDY GOAWAY frame received."))
394 .WillOnce(InvokeWithoutArgs(this,
395 &QuicHeadersStreamTest::CloseConnection));
396 headers_stream_->ProcessRawData(frame->data(), frame->size());
399 TEST_P(QuicHeadersStreamTest, ProcessSpdyWindowUpdateFrame) {
400 SpdyWindowUpdateIR data(1, 1);
401 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
402 EXPECT_CALL(*connection_,
403 SendConnectionCloseWithDetails(
404 QUIC_INVALID_HEADERS_STREAM_DATA,
405 "SPDY WINDOW_UPDATE frame received."))
406 .WillOnce(InvokeWithoutArgs(this,
407 &QuicHeadersStreamTest::CloseConnection));
408 headers_stream_->ProcessRawData(frame->data(), frame->size());
411 TEST_P(QuicHeadersStreamTest, NoConnectionLevelFlowControl) {
412 EXPECT_FALSE(ReliableQuicStreamPeer::StreamContributesToConnectionFlowControl(
413 headers_stream_));
416 } // namespace
417 } // namespace test
418 } // namespace net