Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / net / quic / quic_headers_stream_test.cc
blob097df993c1b2a1e0f33333ba137a78973bc401c8
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::string;
18 using testing::Invoke;
19 using testing::StrictMock;
20 using testing::WithArgs;
21 using testing::_;
23 namespace net {
24 namespace test {
25 namespace {
27 class MockVisitor : public SpdyFramerVisitorInterface {
28 public:
29 MOCK_METHOD1(OnError, void(SpdyFramer* framer));
30 MOCK_METHOD3(OnDataFrameHeader, void(SpdyStreamId stream_id,
31 size_t length,
32 bool fin));
33 MOCK_METHOD4(OnStreamFrameData, void(SpdyStreamId stream_id,
34 const char* data,
35 size_t len,
36 bool fin));
37 MOCK_METHOD3(OnControlFrameHeaderData, bool(SpdyStreamId stream_id,
38 const char* header_data,
39 size_t len));
40 MOCK_METHOD5(OnSynStream, void(SpdyStreamId stream_id,
41 SpdyStreamId associated_stream_id,
42 SpdyPriority priority,
43 bool fin,
44 bool unidirectional));
45 MOCK_METHOD2(OnSynReply, void(SpdyStreamId stream_id, bool fin));
46 MOCK_METHOD2(OnRstStream, void(SpdyStreamId stream_id,
47 SpdyRstStreamStatus status));
48 MOCK_METHOD1(OnSettings, void(bool clear_persisted));
49 MOCK_METHOD3(OnSetting, void(SpdySettingsIds id, uint8 flags, uint32 value));
50 MOCK_METHOD0(OnSettingsAck, void());
51 MOCK_METHOD0(OnSettingsEnd, void());
52 MOCK_METHOD2(OnPing, void(SpdyPingId unique_id, bool is_ack));
53 MOCK_METHOD2(OnGoAway, void(SpdyStreamId last_accepted_stream_id,
54 SpdyGoAwayStatus status));
55 MOCK_METHOD3(OnHeaders, void(SpdyStreamId stream_id, bool fin, bool end));
56 MOCK_METHOD2(OnWindowUpdate, void(SpdyStreamId stream_id,
57 uint32 delta_window_size));
58 MOCK_METHOD2(OnCredentialFrameData, bool(const char* credential_data,
59 size_t len));
60 MOCK_METHOD1(OnBlocked, void(SpdyStreamId stream_id));
61 MOCK_METHOD3(OnPushPromise, void(SpdyStreamId stream_id,
62 SpdyStreamId promised_stream_id,
63 bool end));
64 MOCK_METHOD2(OnContinuation, void(SpdyStreamId stream_id, bool end));
65 MOCK_METHOD6(OnAltSvc, void(SpdyStreamId stream_id,
66 uint32 max_age,
67 uint16 port,
68 StringPiece protocol_id,
69 StringPiece host,
70 StringPiece origin));
71 MOCK_METHOD2(OnUnknownFrame, bool(SpdyStreamId stream_id, int frame_type));
74 class QuicHeadersStreamTest : public ::testing::TestWithParam<bool> {
75 public:
76 static QuicVersionVector GetVersions() {
77 QuicVersionVector versions;
78 versions.push_back(QuicVersionMax());
79 return versions;
82 QuicHeadersStreamTest()
83 : connection_(new StrictMock<MockConnection>(is_server(), GetVersions())),
84 session_(connection_),
85 headers_stream_(QuicSessionPeer::GetHeadersStream(&session_)),
86 body_("hello world"),
87 framer_(SPDY3) {
88 headers_[":version"] = "HTTP/1.1";
89 headers_[":status"] = "200 Ok";
90 headers_["content-length"] = "11";
91 framer_.set_visitor(&visitor_);
92 EXPECT_EQ(QuicVersionMax(), session_.connection()->version());
93 EXPECT_TRUE(headers_stream_ != NULL);
96 QuicConsumedData SaveIov(const IOVector& data) {
97 const iovec* iov = data.iovec();
98 int count = data.Capacity();
99 for (int i = 0 ; i < count; ++i) {
100 saved_data_.append(static_cast<char*>(iov[i].iov_base), iov[i].iov_len);
102 return QuicConsumedData(saved_data_.length(), false);
105 bool SaveHeaderData(const char* data, int len) {
106 saved_header_data_.append(data, len);
107 return true;
110 void SaveHeaderDataStringPiece(StringPiece data) {
111 saved_header_data_.append(data.data(), data.length());
114 void WriteHeadersAndExpectSynStream(QuicStreamId stream_id,
115 bool fin,
116 QuicPriority priority) {
117 WriteHeadersAndCheckData(stream_id, fin, priority, SYN_STREAM);
120 void WriteHeadersAndExpectSynReply(QuicStreamId stream_id,
121 bool fin) {
122 WriteHeadersAndCheckData(stream_id, fin, 0, SYN_REPLY);
125 void WriteHeadersAndCheckData(QuicStreamId stream_id,
126 bool fin,
127 QuicPriority priority,
128 SpdyFrameType type) {
129 // Write the headers and capture the outgoing data
130 EXPECT_CALL(session_, WritevData(kHeadersStreamId, _, _, false, _, NULL))
131 .WillOnce(WithArgs<1>(Invoke(this, &QuicHeadersStreamTest::SaveIov)));
132 headers_stream_->WriteHeaders(stream_id, headers_, fin, NULL);
134 // Parse the outgoing data and check that it matches was was written.
135 if (type == SYN_STREAM) {
136 EXPECT_CALL(visitor_, OnSynStream(stream_id, kNoAssociatedStream, 0,
137 // priority,
138 fin, kNotUnidirectional));
139 } else {
140 EXPECT_CALL(visitor_, OnSynReply(stream_id, fin));
142 EXPECT_CALL(visitor_, OnControlFrameHeaderData(stream_id, _, _))
143 .WillRepeatedly(WithArgs<1, 2>(
144 Invoke(this, &QuicHeadersStreamTest::SaveHeaderData)));
145 if (fin) {
146 EXPECT_CALL(visitor_, OnStreamFrameData(stream_id, NULL, 0, true));
148 framer_.ProcessInput(saved_data_.data(), saved_data_.length());
149 EXPECT_FALSE(framer_.HasError()) << framer_.error_code();
151 CheckHeaders();
152 saved_data_.clear();
155 void CheckHeaders() {
156 SpdyHeaderBlock headers;
157 EXPECT_EQ(saved_header_data_.length(),
158 framer_.ParseHeaderBlockInBuffer(saved_header_data_.data(),
159 saved_header_data_.length(),
160 &headers));
161 EXPECT_EQ(headers_, headers);
162 saved_header_data_.clear();
165 bool is_server() {
166 return GetParam();
169 void CloseConnection() {
170 QuicConnectionPeer::CloseConnection(connection_);
173 static const bool kNotUnidirectional = false;
174 static const bool kNoAssociatedStream = false;
176 StrictMock<MockConnection>* connection_;
177 StrictMock<MockSession> session_;
178 QuicHeadersStream* headers_stream_;
179 SpdyHeaderBlock headers_;
180 string body_;
181 string saved_data_;
182 string saved_header_data_;
183 SpdyFramer framer_;
184 StrictMock<MockVisitor> visitor_;
187 INSTANTIATE_TEST_CASE_P(Tests, QuicHeadersStreamTest, testing::Bool());
189 TEST_P(QuicHeadersStreamTest, StreamId) {
190 EXPECT_EQ(3u, headers_stream_->id());
193 TEST_P(QuicHeadersStreamTest, EffectivePriority) {
194 EXPECT_EQ(0u, headers_stream_->EffectivePriority());
197 TEST_P(QuicHeadersStreamTest, WriteHeaders) {
198 for (QuicStreamId stream_id = kClientDataStreamId1;
199 stream_id < kClientDataStreamId3; stream_id += 2) {
200 for (int count = 0; count < 2; ++count) {
201 bool fin = (count == 0);
202 if (is_server()) {
203 WriteHeadersAndExpectSynReply(stream_id, fin);
204 } else {
205 for (QuicPriority priority = 0; priority < 7; ++priority) {
206 WriteHeadersAndExpectSynStream(stream_id, fin, priority);
213 TEST_P(QuicHeadersStreamTest, ProcessRawData) {
214 for (QuicStreamId stream_id = kClientDataStreamId1;
215 stream_id < kClientDataStreamId3; stream_id += 2) {
216 for (int count = 0; count < 2; ++count) {
217 bool fin = (count == 0);
218 for (QuicPriority priority = 0; priority < 7; ++priority) {
219 // Replace with "WriteHeadersAndSaveData"
220 scoped_ptr<SpdySerializedFrame> frame;
221 if (is_server()) {
222 SpdySynStreamIR syn_stream(stream_id);
223 syn_stream.set_name_value_block(headers_);
224 syn_stream.set_fin(fin);
225 frame.reset(framer_.SerializeSynStream(syn_stream));
226 EXPECT_CALL(session_, OnStreamHeadersPriority(stream_id, 0));
227 } else {
228 SpdySynReplyIR syn_reply(stream_id);
229 syn_reply.set_name_value_block(headers_);
230 syn_reply.set_fin(fin);
231 frame.reset(framer_.SerializeSynReply(syn_reply));
233 EXPECT_CALL(session_, OnStreamHeaders(stream_id, _))
234 .WillRepeatedly(WithArgs<1>(
235 Invoke(this,
236 &QuicHeadersStreamTest::SaveHeaderDataStringPiece)));
237 EXPECT_CALL(session_,
238 OnStreamHeadersComplete(stream_id, fin, frame->size()));
239 headers_stream_->ProcessRawData(frame->data(), frame->size());
241 CheckHeaders();
247 TEST_P(QuicHeadersStreamTest, ProcessSpdyDataFrame) {
248 SpdyDataIR data(2, "");
249 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
250 EXPECT_CALL(*connection_,
251 SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
252 "SPDY DATA frame received."))
253 .WillOnce(InvokeWithoutArgs(this,
254 &QuicHeadersStreamTest::CloseConnection));
255 headers_stream_->ProcessRawData(frame->data(), frame->size());
258 TEST_P(QuicHeadersStreamTest, ProcessSpdyRstStreamFrame) {
259 SpdyRstStreamIR data(2, RST_STREAM_PROTOCOL_ERROR, "");
260 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
261 EXPECT_CALL(*connection_,
262 SendConnectionCloseWithDetails(
263 QUIC_INVALID_HEADERS_STREAM_DATA,
264 "SPDY RST_STREAM frame received."))
265 .WillOnce(InvokeWithoutArgs(this,
266 &QuicHeadersStreamTest::CloseConnection));
267 headers_stream_->ProcessRawData(frame->data(), frame->size());
270 TEST_P(QuicHeadersStreamTest, ProcessSpdySettingsFrame) {
271 SpdySettingsIR data;
272 data.AddSetting(SETTINGS_UPLOAD_BANDWIDTH, true, true, 0);
273 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
274 EXPECT_CALL(*connection_,
275 SendConnectionCloseWithDetails(
276 QUIC_INVALID_HEADERS_STREAM_DATA,
277 "SPDY SETTINGS frame received."))
278 .WillOnce(InvokeWithoutArgs(this,
279 &QuicHeadersStreamTest::CloseConnection));
280 headers_stream_->ProcessRawData(frame->data(), frame->size());
283 TEST_P(QuicHeadersStreamTest, ProcessSpdyPingFrame) {
284 SpdyPingIR data(1);
285 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
286 EXPECT_CALL(*connection_,
287 SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
288 "SPDY PING frame received."))
289 .WillOnce(InvokeWithoutArgs(this,
290 &QuicHeadersStreamTest::CloseConnection));
291 headers_stream_->ProcessRawData(frame->data(), frame->size());
294 TEST_P(QuicHeadersStreamTest, ProcessSpdyGoAwayFrame) {
295 SpdyGoAwayIR data(1, GOAWAY_PROTOCOL_ERROR, "go away");
296 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
297 EXPECT_CALL(*connection_,
298 SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
299 "SPDY GOAWAY frame received."))
300 .WillOnce(InvokeWithoutArgs(this,
301 &QuicHeadersStreamTest::CloseConnection));
302 headers_stream_->ProcessRawData(frame->data(), frame->size());
305 TEST_P(QuicHeadersStreamTest, ProcessSpdyHeadersFrame) {
306 SpdyHeadersIR data(1);
307 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
308 EXPECT_CALL(*connection_,
309 SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
310 "SPDY HEADERS frame received."))
311 .WillOnce(InvokeWithoutArgs(this,
312 &QuicHeadersStreamTest::CloseConnection));
313 headers_stream_->ProcessRawData(frame->data(), frame->size());
316 TEST_P(QuicHeadersStreamTest, ProcessSpdyWindowUpdateFrame) {
317 SpdyWindowUpdateIR data(1, 1);
318 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
319 EXPECT_CALL(*connection_,
320 SendConnectionCloseWithDetails(
321 QUIC_INVALID_HEADERS_STREAM_DATA,
322 "SPDY WINDOW_UPDATE frame received."))
323 .WillOnce(InvokeWithoutArgs(this,
324 &QuicHeadersStreamTest::CloseConnection));
325 headers_stream_->ProcessRawData(frame->data(), frame->size());
328 TEST_P(QuicHeadersStreamTest, NoConnectionLevelFlowControl) {
329 if (connection_->version() <= QUIC_VERSION_20) {
330 EXPECT_FALSE(headers_stream_->flow_controller()->IsEnabled());
331 } else {
332 EXPECT_TRUE(headers_stream_->flow_controller()->IsEnabled());
334 EXPECT_FALSE(ReliableQuicStreamPeer::StreamContributesToConnectionFlowControl(
335 headers_stream_));
338 } // namespace
339 } // namespace test
340 } // namespace net