Don't add an aura tooltip to bubble close buttons on Windows.
[chromium-blink-merge.git] / net / quic / quic_headers_stream_test.cc
blob3a2c7c480aa8b2558088781d9612f1bcd72ee616
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_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_METHOD5(OnHeaders, void(SpdyStreamId stream_id, bool has_priority,
59 SpdyPriority priority, bool fin, bool end));
60 MOCK_METHOD2(OnWindowUpdate, void(SpdyStreamId stream_id,
61 uint32 delta_window_size));
62 MOCK_METHOD2(OnCredentialFrameData, bool(const char* credential_data,
63 size_t len));
64 MOCK_METHOD1(OnBlocked, void(SpdyStreamId stream_id));
65 MOCK_METHOD3(OnPushPromise, void(SpdyStreamId stream_id,
66 SpdyStreamId promised_stream_id,
67 bool end));
68 MOCK_METHOD2(OnContinuation, void(SpdyStreamId stream_id, bool end));
69 MOCK_METHOD6(OnAltSvc, void(SpdyStreamId stream_id,
70 uint32 max_age,
71 uint16 port,
72 StringPiece protocol_id,
73 StringPiece host,
74 StringPiece origin));
75 MOCK_METHOD2(OnUnknownFrame, bool(SpdyStreamId stream_id, int frame_type));
78 // Run all tests with each version, and client or server
79 struct TestParams {
80 TestParams(QuicVersion version, Perspective perspective)
81 : version(version), perspective(perspective) {}
83 friend ostream& operator<<(ostream& os, const TestParams& p) {
84 os << "{ version: " << QuicVersionToString(p.version);
85 os << ", perspective: " << p.perspective << " }";
86 return os;
89 QuicVersion version;
90 Perspective perspective;
93 // Constructs various test permutations.
94 vector<TestParams> GetTestParams() {
95 vector<TestParams> params;
96 QuicVersionVector all_supported_versions = QuicSupportedVersions();
97 for (const QuicVersion version : all_supported_versions) {
98 params.push_back(TestParams(version, Perspective::IS_CLIENT));
99 params.push_back(TestParams(version, Perspective::IS_SERVER));
101 return params;
104 class QuicHeadersStreamTest : public ::testing::TestWithParam<TestParams> {
105 public:
106 QuicHeadersStreamTest()
107 : connection_(
108 new StrictMock<MockConnection>(perspective(), GetVersion())),
109 session_(connection_),
110 headers_stream_(QuicSessionPeer::GetHeadersStream(&session_)),
111 body_("hello world"),
112 framer_(version() > QUIC_VERSION_23 ? SPDY4 : SPDY3) {
113 headers_[":version"] = "HTTP/1.1";
114 headers_[":status"] = "200 Ok";
115 headers_["content-length"] = "11";
116 framer_.set_visitor(&visitor_);
117 EXPECT_EQ(version(), session_.connection()->version());
118 EXPECT_TRUE(headers_stream_ != nullptr);
119 VLOG(1) << GetParam();
122 QuicConsumedData SaveIov(const IOVector& data) {
123 const iovec* iov = data.iovec();
124 int count = data.Capacity();
125 for (int i = 0 ; i < count; ++i) {
126 saved_data_.append(static_cast<char*>(iov[i].iov_base), iov[i].iov_len);
128 return QuicConsumedData(saved_data_.length(), false);
131 bool SaveHeaderData(const char* data, int len) {
132 saved_header_data_.append(data, len);
133 return true;
136 void SaveHeaderDataStringPiece(StringPiece data) {
137 saved_header_data_.append(data.data(), data.length());
140 void WriteHeadersAndExpectSynStream(QuicStreamId stream_id,
141 bool fin,
142 QuicPriority priority) {
143 WriteHeadersAndCheckData(stream_id, fin, priority, SYN_STREAM);
146 void WriteHeadersAndExpectSynReply(QuicStreamId stream_id,
147 bool fin) {
148 WriteHeadersAndCheckData(stream_id, fin, 0, SYN_REPLY);
151 void WriteHeadersAndCheckData(QuicStreamId stream_id,
152 bool fin,
153 QuicPriority priority,
154 SpdyFrameType type) {
155 // Write the headers and capture the outgoing data
156 EXPECT_CALL(session_, WritevData(kHeadersStreamId, _, _, false, _, nullptr))
157 .WillOnce(WithArgs<1>(Invoke(this, &QuicHeadersStreamTest::SaveIov)));
158 headers_stream_->WriteHeaders(stream_id, headers_, fin, priority, nullptr);
160 // Parse the outgoing data and check that it matches was was written.
161 if (type == SYN_STREAM) {
162 if (version() > QUIC_VERSION_23) {
163 EXPECT_CALL(visitor_, OnHeaders(stream_id, kHasPriority, priority, fin,
164 kFrameComplete));
165 } else {
166 EXPECT_CALL(visitor_,
167 OnSynStream(stream_id, kNoAssociatedStream,
168 /*priority=*/0, fin, kNotUnidirectional));
170 } else {
171 if (version() > QUIC_VERSION_23) {
172 EXPECT_CALL(visitor_, OnHeaders(stream_id, !kHasPriority,
173 /*priority=*/0, fin, kFrameComplete));
174 } else {
175 EXPECT_CALL(visitor_, OnSynReply(stream_id, fin));
178 EXPECT_CALL(visitor_, OnControlFrameHeaderData(stream_id, _, _))
179 .WillRepeatedly(WithArgs<1, 2>(
180 Invoke(this, &QuicHeadersStreamTest::SaveHeaderData)));
181 if (fin) {
182 EXPECT_CALL(visitor_, OnStreamFrameData(stream_id, nullptr, 0, true));
184 framer_.ProcessInput(saved_data_.data(), saved_data_.length());
185 EXPECT_FALSE(framer_.HasError())
186 << SpdyFramer::ErrorCodeToString(framer_.error_code());
188 CheckHeaders();
189 saved_data_.clear();
192 void CheckHeaders() {
193 SpdyHeaderBlock headers;
194 EXPECT_EQ(saved_header_data_.length(),
195 framer_.ParseHeaderBlockInBuffer(saved_header_data_.data(),
196 saved_header_data_.length(),
197 &headers));
198 EXPECT_EQ(headers_, headers);
199 saved_header_data_.clear();
202 Perspective perspective() { return GetParam().perspective; }
204 QuicVersion version() { return GetParam().version; }
206 QuicVersionVector GetVersion() {
207 QuicVersionVector versions;
208 versions.push_back(version());
209 return versions;
212 void CloseConnection() {
213 QuicConnectionPeer::CloseConnection(connection_);
216 static const bool kFrameComplete = true;
217 static const bool kHasPriority = true;
218 static const bool kNotUnidirectional = false;
219 static const bool kNoAssociatedStream = false;
221 StrictMock<MockConnection>* connection_;
222 StrictMock<MockSession> session_;
223 QuicHeadersStream* headers_stream_;
224 SpdyHeaderBlock headers_;
225 string body_;
226 string saved_data_;
227 string saved_header_data_;
228 SpdyFramer framer_;
229 StrictMock<MockVisitor> visitor_;
232 INSTANTIATE_TEST_CASE_P(Tests,
233 QuicHeadersStreamTest,
234 ::testing::ValuesIn(GetTestParams()));
236 TEST_P(QuicHeadersStreamTest, StreamId) {
237 EXPECT_EQ(3u, headers_stream_->id());
240 TEST_P(QuicHeadersStreamTest, EffectivePriority) {
241 EXPECT_EQ(0u, headers_stream_->EffectivePriority());
244 TEST_P(QuicHeadersStreamTest, WriteHeaders) {
245 for (QuicStreamId stream_id = kClientDataStreamId1;
246 stream_id < kClientDataStreamId3; stream_id += 2) {
247 for (int count = 0; count < 2; ++count) {
248 bool fin = (count == 0);
249 if (perspective() == Perspective::IS_SERVER) {
250 WriteHeadersAndExpectSynReply(stream_id, fin);
251 } else {
252 for (QuicPriority priority = 0; priority < 7; ++priority) {
253 // TODO(rch): implement priorities correctly.
254 WriteHeadersAndExpectSynStream(stream_id, fin, 0);
261 TEST_P(QuicHeadersStreamTest, ProcessRawData) {
262 for (QuicStreamId stream_id = kClientDataStreamId1;
263 stream_id < kClientDataStreamId3; stream_id += 2) {
264 for (int count = 0; count < 2; ++count) {
265 bool fin = (count == 0);
266 for (QuicPriority priority = 0; priority < 7; ++priority) {
267 // Replace with "WriteHeadersAndSaveData"
268 scoped_ptr<SpdySerializedFrame> frame;
269 if (perspective() == Perspective::IS_SERVER) {
270 if (version() > QUIC_VERSION_23) {
271 SpdyHeadersIR headers_frame(stream_id);
272 headers_frame.set_name_value_block(headers_);
273 headers_frame.set_fin(fin);
274 headers_frame.set_has_priority(true);
275 frame.reset(framer_.SerializeFrame(headers_frame));
276 } else {
277 SpdySynStreamIR syn_stream(stream_id);
278 syn_stream.set_name_value_block(headers_);
279 syn_stream.set_fin(fin);
280 frame.reset(framer_.SerializeSynStream(syn_stream));
282 EXPECT_CALL(session_, OnStreamHeadersPriority(stream_id, 0));
283 } else {
284 if (version() > QUIC_VERSION_23) {
285 SpdyHeadersIR headers_frame(stream_id);
286 headers_frame.set_name_value_block(headers_);
287 headers_frame.set_fin(fin);
288 frame.reset(framer_.SerializeFrame(headers_frame));
289 } else {
290 SpdySynReplyIR syn_reply(stream_id);
291 syn_reply.set_name_value_block(headers_);
292 syn_reply.set_fin(fin);
293 frame.reset(framer_.SerializeSynReply(syn_reply));
296 EXPECT_CALL(session_, OnStreamHeaders(stream_id, _))
297 .WillRepeatedly(WithArgs<1>(
298 Invoke(this,
299 &QuicHeadersStreamTest::SaveHeaderDataStringPiece)));
300 EXPECT_CALL(session_,
301 OnStreamHeadersComplete(stream_id, fin, frame->size()));
302 headers_stream_->ProcessRawData(frame->data(), frame->size());
303 CheckHeaders();
309 TEST_P(QuicHeadersStreamTest, ProcessLargeRawData) {
310 // We want to create a frame that is more than the SPDY Framer's max control
311 // frame size, which is 16K, but less than the HPACK decoders max decode
312 // buffer size, which is 32K.
313 headers_["key0"] = string(1 << 13, '.');
314 headers_["key1"] = string(1 << 13, '.');
315 headers_["key2"] = string(1 << 13, '.');
316 for (QuicStreamId stream_id = kClientDataStreamId1;
317 stream_id < kClientDataStreamId3; stream_id += 2) {
318 for (int count = 0; count < 2; ++count) {
319 bool fin = (count == 0);
320 for (QuicPriority priority = 0; priority < 7; ++priority) {
321 // Replace with "WriteHeadersAndSaveData"
322 scoped_ptr<SpdySerializedFrame> frame;
323 if (perspective() == Perspective::IS_SERVER) {
324 if (version() > QUIC_VERSION_23) {
325 SpdyHeadersIR headers_frame(stream_id);
326 headers_frame.set_name_value_block(headers_);
327 headers_frame.set_fin(fin);
328 headers_frame.set_has_priority(true);
329 frame.reset(framer_.SerializeFrame(headers_frame));
330 } else {
331 SpdySynStreamIR syn_stream(stream_id);
332 syn_stream.set_name_value_block(headers_);
333 syn_stream.set_fin(fin);
334 frame.reset(framer_.SerializeSynStream(syn_stream));
336 EXPECT_CALL(session_, OnStreamHeadersPriority(stream_id, 0));
337 } else {
338 if (version() > QUIC_VERSION_23) {
339 SpdyHeadersIR headers_frame(stream_id);
340 headers_frame.set_name_value_block(headers_);
341 headers_frame.set_fin(fin);
342 frame.reset(framer_.SerializeFrame(headers_frame));
343 } else {
344 SpdySynReplyIR syn_reply(stream_id);
345 syn_reply.set_name_value_block(headers_);
346 syn_reply.set_fin(fin);
347 frame.reset(framer_.SerializeSynReply(syn_reply));
350 EXPECT_CALL(session_, OnStreamHeaders(stream_id, _))
351 .WillRepeatedly(WithArgs<1>(Invoke(
352 this, &QuicHeadersStreamTest::SaveHeaderDataStringPiece)));
353 EXPECT_CALL(session_,
354 OnStreamHeadersComplete(stream_id, fin, frame->size()));
355 headers_stream_->ProcessRawData(frame->data(), frame->size());
356 CheckHeaders();
362 TEST_P(QuicHeadersStreamTest, ProcessBadData) {
363 const char kBadData[] = "blah blah blah";
364 EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(
365 QUIC_INVALID_HEADERS_STREAM_DATA, _))
366 .Times(::testing::AnyNumber());
367 headers_stream_->ProcessRawData(kBadData, strlen(kBadData));
370 TEST_P(QuicHeadersStreamTest, ProcessSpdyDataFrame) {
371 SpdyDataIR data(2, "");
372 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
373 EXPECT_CALL(*connection_,
374 SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
375 "SPDY DATA frame received."))
376 .WillOnce(InvokeWithoutArgs(this,
377 &QuicHeadersStreamTest::CloseConnection));
378 headers_stream_->ProcessRawData(frame->data(), frame->size());
381 TEST_P(QuicHeadersStreamTest, ProcessSpdyRstStreamFrame) {
382 SpdyRstStreamIR data(2, RST_STREAM_PROTOCOL_ERROR, "");
383 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
384 EXPECT_CALL(*connection_,
385 SendConnectionCloseWithDetails(
386 QUIC_INVALID_HEADERS_STREAM_DATA,
387 "SPDY RST_STREAM frame received."))
388 .WillOnce(InvokeWithoutArgs(this,
389 &QuicHeadersStreamTest::CloseConnection));
390 headers_stream_->ProcessRawData(frame->data(), frame->size());
393 TEST_P(QuicHeadersStreamTest, ProcessSpdySettingsFrame) {
394 SpdySettingsIR data;
395 if (version() > QUIC_VERSION_23) {
396 data.AddSetting(SETTINGS_HEADER_TABLE_SIZE, true, true, 0);
397 } else {
398 data.AddSetting(SETTINGS_UPLOAD_BANDWIDTH, true, true, 0);
400 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
401 EXPECT_CALL(*connection_,
402 SendConnectionCloseWithDetails(
403 QUIC_INVALID_HEADERS_STREAM_DATA,
404 "SPDY SETTINGS frame received."))
405 .WillOnce(InvokeWithoutArgs(this,
406 &QuicHeadersStreamTest::CloseConnection));
407 headers_stream_->ProcessRawData(frame->data(), frame->size());
410 TEST_P(QuicHeadersStreamTest, ProcessSpdyPingFrame) {
411 SpdyPingIR data(1);
412 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
413 EXPECT_CALL(*connection_,
414 SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
415 "SPDY PING frame received."))
416 .WillOnce(InvokeWithoutArgs(this,
417 &QuicHeadersStreamTest::CloseConnection));
418 headers_stream_->ProcessRawData(frame->data(), frame->size());
421 TEST_P(QuicHeadersStreamTest, ProcessSpdyGoAwayFrame) {
422 SpdyGoAwayIR data(1, GOAWAY_PROTOCOL_ERROR, "go away");
423 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
424 EXPECT_CALL(*connection_,
425 SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
426 "SPDY GOAWAY frame received."))
427 .WillOnce(InvokeWithoutArgs(this,
428 &QuicHeadersStreamTest::CloseConnection));
429 headers_stream_->ProcessRawData(frame->data(), frame->size());
432 TEST_P(QuicHeadersStreamTest, ProcessSpdyHeadersFrame) {
433 if (version() > QUIC_VERSION_23) {
434 // HEADERS frames are an error when using SPDY/3, but
435 // when using SPDY/4 they're the "normal" way of sending headers
436 // so we test their handling in the ProcessRawData test.
437 return;
439 SpdyHeadersIR data(1);
440 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
441 EXPECT_CALL(*connection_,
442 SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
443 "SPDY HEADERS frame received."))
444 .WillOnce(InvokeWithoutArgs(this,
445 &QuicHeadersStreamTest::CloseConnection));
446 headers_stream_->ProcessRawData(frame->data(), frame->size());
449 TEST_P(QuicHeadersStreamTest, ProcessSpdyWindowUpdateFrame) {
450 SpdyWindowUpdateIR data(1, 1);
451 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
452 EXPECT_CALL(*connection_,
453 SendConnectionCloseWithDetails(
454 QUIC_INVALID_HEADERS_STREAM_DATA,
455 "SPDY WINDOW_UPDATE frame received."))
456 .WillOnce(InvokeWithoutArgs(this,
457 &QuicHeadersStreamTest::CloseConnection));
458 headers_stream_->ProcessRawData(frame->data(), frame->size());
461 TEST_P(QuicHeadersStreamTest, NoConnectionLevelFlowControl) {
462 EXPECT_FALSE(ReliableQuicStreamPeer::StreamContributesToConnectionFlowControl(
463 headers_stream_));
466 } // namespace
467 } // namespace test
468 } // namespace net