[Android WebView] Fix webview perf bot switchover to use org.chromium.webview_shell...
[chromium-blink-merge.git] / net / quic / quic_headers_stream_test.cc
blob8916340f478dd960fc84eeba92a2cd677146add5
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_METHOD3(OnAltSvc,
70 void(SpdyStreamId stream_id,
71 StringPiece origin,
72 const SpdyAltSvcWireFormat::AlternativeServiceVector&
73 altsvc_vector));
74 MOCK_METHOD2(OnUnknownFrame, bool(SpdyStreamId stream_id, int frame_type));
77 // Run all tests with each version, and client or server
78 struct TestParams {
79 TestParams(QuicVersion version, Perspective perspective)
80 : version(version), perspective(perspective) {}
82 friend ostream& operator<<(ostream& os, const TestParams& p) {
83 os << "{ version: " << QuicVersionToString(p.version);
84 os << ", perspective: " << p.perspective << " }";
85 return os;
88 QuicVersion version;
89 Perspective perspective;
92 // Constructs various test permutations.
93 vector<TestParams> GetTestParams() {
94 vector<TestParams> params;
95 QuicVersionVector all_supported_versions = QuicSupportedVersions();
96 for (const QuicVersion version : all_supported_versions) {
97 params.push_back(TestParams(version, Perspective::IS_CLIENT));
98 params.push_back(TestParams(version, Perspective::IS_SERVER));
100 return params;
103 class QuicHeadersStreamTest : public ::testing::TestWithParam<TestParams> {
104 public:
105 QuicHeadersStreamTest()
106 : connection_(
107 new StrictMock<MockConnection>(perspective(), GetVersion())),
108 session_(connection_),
109 headers_stream_(QuicSessionPeer::GetHeadersStream(&session_)),
110 body_("hello world"),
111 framer_(SPDY4) {
112 headers_[":version"] = "HTTP/1.1";
113 headers_[":status"] = "200 Ok";
114 headers_["content-length"] = "11";
115 framer_.set_visitor(&visitor_);
116 EXPECT_EQ(version(), session_.connection()->version());
117 EXPECT_TRUE(headers_stream_ != nullptr);
118 VLOG(1) << GetParam();
121 QuicConsumedData SaveIov(const IOVector& data) {
122 const iovec* iov = data.iovec();
123 int count = data.Capacity();
124 for (int i = 0 ; i < count; ++i) {
125 saved_data_.append(static_cast<char*>(iov[i].iov_base), iov[i].iov_len);
127 return QuicConsumedData(saved_data_.length(), false);
130 bool SaveHeaderData(const char* data, int len) {
131 saved_header_data_.append(data, len);
132 return true;
135 void SaveHeaderDataStringPiece(StringPiece data) {
136 saved_header_data_.append(data.data(), data.length());
139 void WriteHeadersAndExpectSynStream(QuicStreamId stream_id,
140 bool fin,
141 QuicPriority priority) {
142 WriteHeadersAndCheckData(stream_id, fin, priority, SYN_STREAM);
145 void WriteHeadersAndExpectSynReply(QuicStreamId stream_id,
146 bool fin) {
147 WriteHeadersAndCheckData(stream_id, fin, 0, SYN_REPLY);
150 void WriteHeadersAndCheckData(QuicStreamId stream_id,
151 bool fin,
152 QuicPriority priority,
153 SpdyFrameType type) {
154 // Write the headers and capture the outgoing data
155 EXPECT_CALL(session_, WritevData(kHeadersStreamId, _, _, false, _, nullptr))
156 .WillOnce(WithArgs<1>(Invoke(this, &QuicHeadersStreamTest::SaveIov)));
157 headers_stream_->WriteHeaders(stream_id, headers_, fin, priority, nullptr);
159 // Parse the outgoing data and check that it matches was was written.
160 if (type == SYN_STREAM) {
161 EXPECT_CALL(visitor_, OnHeaders(stream_id, kHasPriority, priority, fin,
162 kFrameComplete));
163 } else {
164 EXPECT_CALL(visitor_, OnHeaders(stream_id, !kHasPriority,
165 /*priority=*/0, fin, kFrameComplete));
167 EXPECT_CALL(visitor_, OnControlFrameHeaderData(stream_id, _, _))
168 .WillRepeatedly(WithArgs<1, 2>(
169 Invoke(this, &QuicHeadersStreamTest::SaveHeaderData)));
170 if (fin) {
171 EXPECT_CALL(visitor_, OnStreamFrameData(stream_id, nullptr, 0, true));
173 framer_.ProcessInput(saved_data_.data(), saved_data_.length());
174 EXPECT_FALSE(framer_.HasError())
175 << SpdyFramer::ErrorCodeToString(framer_.error_code());
177 CheckHeaders();
178 saved_data_.clear();
181 void CheckHeaders() {
182 SpdyHeaderBlock headers;
183 EXPECT_EQ(saved_header_data_.length(),
184 framer_.ParseHeaderBlockInBuffer(saved_header_data_.data(),
185 saved_header_data_.length(),
186 &headers));
187 EXPECT_EQ(headers_, headers);
188 saved_header_data_.clear();
191 Perspective perspective() { return GetParam().perspective; }
193 QuicVersion version() { return GetParam().version; }
195 QuicVersionVector GetVersion() {
196 QuicVersionVector versions;
197 versions.push_back(version());
198 return versions;
201 void CloseConnection() {
202 QuicConnectionPeer::CloseConnection(connection_);
205 static const bool kFrameComplete = true;
206 static const bool kHasPriority = true;
208 StrictMock<MockConnection>* connection_;
209 StrictMock<MockSession> session_;
210 QuicHeadersStream* headers_stream_;
211 SpdyHeaderBlock headers_;
212 string body_;
213 string saved_data_;
214 string saved_header_data_;
215 SpdyFramer framer_;
216 StrictMock<MockVisitor> visitor_;
219 INSTANTIATE_TEST_CASE_P(Tests,
220 QuicHeadersStreamTest,
221 ::testing::ValuesIn(GetTestParams()));
223 TEST_P(QuicHeadersStreamTest, StreamId) {
224 EXPECT_EQ(3u, headers_stream_->id());
227 TEST_P(QuicHeadersStreamTest, EffectivePriority) {
228 EXPECT_EQ(0u, headers_stream_->EffectivePriority());
231 TEST_P(QuicHeadersStreamTest, WriteHeaders) {
232 for (QuicStreamId stream_id = kClientDataStreamId1;
233 stream_id < kClientDataStreamId3; stream_id += 2) {
234 for (int count = 0; count < 2; ++count) {
235 bool fin = (count == 0);
236 if (perspective() == Perspective::IS_SERVER) {
237 WriteHeadersAndExpectSynReply(stream_id, fin);
238 } else {
239 for (QuicPriority priority = 0; priority < 7; ++priority) {
240 // TODO(rch): implement priorities correctly.
241 WriteHeadersAndExpectSynStream(stream_id, fin, 0);
248 TEST_P(QuicHeadersStreamTest, ProcessRawData) {
249 for (QuicStreamId stream_id = kClientDataStreamId1;
250 stream_id < kClientDataStreamId3; stream_id += 2) {
251 for (int count = 0; count < 2; ++count) {
252 bool fin = (count == 0);
253 for (QuicPriority priority = 0; priority < 7; ++priority) {
254 // Replace with "WriteHeadersAndSaveData"
255 scoped_ptr<SpdySerializedFrame> frame;
256 if (perspective() == Perspective::IS_SERVER) {
257 SpdyHeadersIR headers_frame(stream_id);
258 headers_frame.set_name_value_block(headers_);
259 headers_frame.set_fin(fin);
260 headers_frame.set_has_priority(true);
261 frame.reset(framer_.SerializeFrame(headers_frame));
262 EXPECT_CALL(session_, OnStreamHeadersPriority(stream_id, 0));
263 } else {
264 SpdyHeadersIR headers_frame(stream_id);
265 headers_frame.set_name_value_block(headers_);
266 headers_frame.set_fin(fin);
267 frame.reset(framer_.SerializeFrame(headers_frame));
269 EXPECT_CALL(session_, OnStreamHeaders(stream_id, _))
270 .WillRepeatedly(WithArgs<1>(
271 Invoke(this,
272 &QuicHeadersStreamTest::SaveHeaderDataStringPiece)));
273 EXPECT_CALL(session_,
274 OnStreamHeadersComplete(stream_id, fin, frame->size()));
275 headers_stream_->ProcessRawData(frame->data(), frame->size());
276 CheckHeaders();
282 TEST_P(QuicHeadersStreamTest, ProcessLargeRawData) {
283 // We want to create a frame that is more than the SPDY Framer's max control
284 // frame size, which is 16K, but less than the HPACK decoders max decode
285 // buffer size, which is 32K.
286 headers_["key0"] = string(1 << 13, '.');
287 headers_["key1"] = string(1 << 13, '.');
288 headers_["key2"] = string(1 << 13, '.');
289 for (QuicStreamId stream_id = kClientDataStreamId1;
290 stream_id < kClientDataStreamId3; stream_id += 2) {
291 for (int count = 0; count < 2; ++count) {
292 bool fin = (count == 0);
293 for (QuicPriority priority = 0; priority < 7; ++priority) {
294 // Replace with "WriteHeadersAndSaveData"
295 scoped_ptr<SpdySerializedFrame> frame;
296 if (perspective() == Perspective::IS_SERVER) {
297 SpdyHeadersIR headers_frame(stream_id);
298 headers_frame.set_name_value_block(headers_);
299 headers_frame.set_fin(fin);
300 headers_frame.set_has_priority(true);
301 frame.reset(framer_.SerializeFrame(headers_frame));
302 EXPECT_CALL(session_, OnStreamHeadersPriority(stream_id, 0));
303 } else {
304 SpdyHeadersIR headers_frame(stream_id);
305 headers_frame.set_name_value_block(headers_);
306 headers_frame.set_fin(fin);
307 frame.reset(framer_.SerializeFrame(headers_frame));
309 EXPECT_CALL(session_, OnStreamHeaders(stream_id, _))
310 .WillRepeatedly(WithArgs<1>(Invoke(
311 this, &QuicHeadersStreamTest::SaveHeaderDataStringPiece)));
312 EXPECT_CALL(session_,
313 OnStreamHeadersComplete(stream_id, fin, frame->size()));
314 headers_stream_->ProcessRawData(frame->data(), frame->size());
315 CheckHeaders();
321 TEST_P(QuicHeadersStreamTest, ProcessBadData) {
322 const char kBadData[] = "blah blah blah";
323 EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(
324 QUIC_INVALID_HEADERS_STREAM_DATA, _))
325 .Times(::testing::AnyNumber());
326 headers_stream_->ProcessRawData(kBadData, strlen(kBadData));
329 TEST_P(QuicHeadersStreamTest, ProcessSpdyDataFrame) {
330 SpdyDataIR data(2, "");
331 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
332 EXPECT_CALL(*connection_,
333 SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
334 "SPDY DATA frame received."))
335 .WillOnce(InvokeWithoutArgs(this,
336 &QuicHeadersStreamTest::CloseConnection));
337 headers_stream_->ProcessRawData(frame->data(), frame->size());
340 TEST_P(QuicHeadersStreamTest, ProcessSpdyRstStreamFrame) {
341 SpdyRstStreamIR data(2, RST_STREAM_PROTOCOL_ERROR, "");
342 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
343 EXPECT_CALL(*connection_,
344 SendConnectionCloseWithDetails(
345 QUIC_INVALID_HEADERS_STREAM_DATA,
346 "SPDY RST_STREAM frame received."))
347 .WillOnce(InvokeWithoutArgs(this,
348 &QuicHeadersStreamTest::CloseConnection));
349 headers_stream_->ProcessRawData(frame->data(), frame->size());
352 TEST_P(QuicHeadersStreamTest, ProcessSpdySettingsFrame) {
353 SpdySettingsIR data;
354 data.AddSetting(SETTINGS_HEADER_TABLE_SIZE, true, true, 0);
355 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
356 EXPECT_CALL(*connection_,
357 SendConnectionCloseWithDetails(
358 QUIC_INVALID_HEADERS_STREAM_DATA,
359 "SPDY SETTINGS frame received."))
360 .WillOnce(InvokeWithoutArgs(this,
361 &QuicHeadersStreamTest::CloseConnection));
362 headers_stream_->ProcessRawData(frame->data(), frame->size());
365 TEST_P(QuicHeadersStreamTest, ProcessSpdyPingFrame) {
366 SpdyPingIR data(1);
367 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
368 EXPECT_CALL(*connection_,
369 SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
370 "SPDY PING frame received."))
371 .WillOnce(InvokeWithoutArgs(this,
372 &QuicHeadersStreamTest::CloseConnection));
373 headers_stream_->ProcessRawData(frame->data(), frame->size());
376 TEST_P(QuicHeadersStreamTest, ProcessSpdyGoAwayFrame) {
377 SpdyGoAwayIR data(1, GOAWAY_PROTOCOL_ERROR, "go away");
378 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
379 EXPECT_CALL(*connection_,
380 SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
381 "SPDY GOAWAY frame received."))
382 .WillOnce(InvokeWithoutArgs(this,
383 &QuicHeadersStreamTest::CloseConnection));
384 headers_stream_->ProcessRawData(frame->data(), frame->size());
387 TEST_P(QuicHeadersStreamTest, ProcessSpdyWindowUpdateFrame) {
388 SpdyWindowUpdateIR data(1, 1);
389 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
390 EXPECT_CALL(*connection_,
391 SendConnectionCloseWithDetails(
392 QUIC_INVALID_HEADERS_STREAM_DATA,
393 "SPDY WINDOW_UPDATE frame received."))
394 .WillOnce(InvokeWithoutArgs(this,
395 &QuicHeadersStreamTest::CloseConnection));
396 headers_stream_->ProcessRawData(frame->data(), frame->size());
399 TEST_P(QuicHeadersStreamTest, NoConnectionLevelFlowControl) {
400 EXPECT_FALSE(ReliableQuicStreamPeer::StreamContributesToConnectionFlowControl(
401 headers_stream_));
404 } // namespace
405 } // namespace test
406 } // namespace net