Land Recent QUIC Changes.
[chromium-blink-merge.git] / net / quic / quic_headers_stream_test.cc
blob61ea335638cdd5be441eb67fc43b2b46bbd16f91
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/spdy/spdy_protocol.h"
13 #include "testing/gtest/include/gtest/gtest.h"
15 using base::StringPiece;
16 using std::string;
17 using testing::Invoke;
18 using testing::StrictMock;
19 using testing::WithArgs;
20 using testing::_;
22 namespace net {
23 namespace test {
24 namespace {
26 class MockVisitor : public SpdyFramerVisitorInterface {
27 public:
28 MOCK_METHOD1(OnError, void(SpdyFramer* framer));
29 MOCK_METHOD3(OnDataFrameHeader, void(SpdyStreamId stream_id,
30 size_t length,
31 bool fin));
32 MOCK_METHOD4(OnStreamFrameData, void(SpdyStreamId stream_id,
33 const char* data,
34 size_t len,
35 bool fin));
36 MOCK_METHOD3(OnControlFrameHeaderData, bool(SpdyStreamId stream_id,
37 const char* header_data,
38 size_t len));
39 MOCK_METHOD5(OnSynStream, void(SpdyStreamId stream_id,
40 SpdyStreamId associated_stream_id,
41 SpdyPriority priority,
42 bool fin,
43 bool unidirectional));
44 MOCK_METHOD2(OnSynReply, void(SpdyStreamId stream_id, bool fin));
45 MOCK_METHOD2(OnRstStream, void(SpdyStreamId stream_id,
46 SpdyRstStreamStatus status));
47 MOCK_METHOD1(OnSettings, void(bool clear_persisted));
48 MOCK_METHOD3(OnSetting, void(SpdySettingsIds id, uint8 flags, uint32 value));
49 MOCK_METHOD0(OnSettingsAck, void());
50 MOCK_METHOD0(OnSettingsEnd, void());
51 MOCK_METHOD2(OnPing, void(SpdyPingId unique_id, bool is_ack));
52 MOCK_METHOD2(OnGoAway, void(SpdyStreamId last_accepted_stream_id,
53 SpdyGoAwayStatus status));
54 MOCK_METHOD3(OnHeaders, void(SpdyStreamId stream_id, bool fin, bool end));
55 MOCK_METHOD2(OnWindowUpdate, void(SpdyStreamId stream_id,
56 uint32 delta_window_size));
57 MOCK_METHOD2(OnCredentialFrameData, bool(const char* credential_data,
58 size_t len));
59 MOCK_METHOD1(OnBlocked, void(SpdyStreamId stream_id));
60 MOCK_METHOD3(OnPushPromise, void(SpdyStreamId stream_id,
61 SpdyStreamId promised_stream_id,
62 bool end));
63 MOCK_METHOD2(OnContinuation, void(SpdyStreamId stream_id, bool end));
66 class QuicHeadersStreamTest : public ::testing::TestWithParam<bool> {
67 public:
68 static QuicVersionVector GetVersions() {
69 QuicVersionVector versions;
70 versions.push_back(QUIC_VERSION_13);
71 return versions;
74 QuicHeadersStreamTest()
75 : connection_(new StrictMock<MockConnection>(is_server(), GetVersions())),
76 session_(connection_),
77 headers_stream_(QuicSessionPeer::GetHeadersStream(&session_)),
78 body_("hello world"),
79 framer_(SPDY3) {
80 headers_[":version"] = "HTTP/1.1";
81 headers_[":status"] = "200 Ok";
82 headers_["content-length"] = "11";
83 framer_.set_visitor(&visitor_);
84 EXPECT_EQ(QUIC_VERSION_13, session_.connection()->version());
85 EXPECT_TRUE(headers_stream_ != NULL);
88 QuicConsumedData SaveIov(const IOVector& data) {
89 const iovec* iov = data.iovec();
90 int count = data.Capacity();
91 for (int i = 0 ; i < count; ++i) {
92 saved_data_.append(static_cast<char*>(iov[i].iov_base), iov[i].iov_len);
94 return QuicConsumedData(saved_data_.length(), false);
97 bool SaveHeaderData(const char* data, int len) {
98 saved_header_data_.append(data, len);
99 return true;
102 void SaveHeaderDataStringPiece(StringPiece data) {
103 saved_header_data_.append(data.data(), data.length());
106 void WriteHeadersAndExpectSynStream(QuicStreamId stream_id,
107 bool fin,
108 QuicPriority priority) {
109 WriteHeadersAndCheckData(stream_id, fin, priority, SYN_STREAM);
112 void WriteHeadersAndExpectSynReply(QuicStreamId stream_id,
113 bool fin) {
114 WriteHeadersAndCheckData(stream_id, fin, 0, SYN_REPLY);
117 void WriteHeadersAndCheckData(QuicStreamId stream_id,
118 bool fin,
119 QuicPriority priority,
120 SpdyFrameType type) {
121 // Write the headers and capture the outgoing data
122 EXPECT_CALL(session_, WritevData(kHeadersStreamId, _, _, false, NULL))
123 .WillOnce(WithArgs<1>(Invoke(this, &QuicHeadersStreamTest::SaveIov)));
124 headers_stream_->WriteHeaders(stream_id, headers_, fin);
126 // Parse the outgoing data and check that it matches was was written.
127 if (type == SYN_STREAM) {
128 EXPECT_CALL(visitor_, OnSynStream(stream_id, kNoAssociatedStream, 0,
129 // priority,
130 fin, kNotUnidirectional));
131 } else {
132 EXPECT_CALL(visitor_, OnSynReply(stream_id, fin));
134 EXPECT_CALL(visitor_, OnControlFrameHeaderData(stream_id, _, _))
135 .WillRepeatedly(WithArgs<1, 2>(
136 Invoke(this, &QuicHeadersStreamTest::SaveHeaderData)));
137 if (fin) {
138 EXPECT_CALL(visitor_, OnStreamFrameData(stream_id, NULL, 0, true));
140 framer_.ProcessInput(saved_data_.data(), saved_data_.length());
141 EXPECT_FALSE(framer_.HasError()) << framer_.error_code();
143 CheckHeaders();
144 saved_data_.clear();
147 void CheckHeaders() {
148 SpdyHeaderBlock headers;
149 EXPECT_EQ(saved_header_data_.length(),
150 framer_.ParseHeaderBlockInBuffer(saved_header_data_.data(),
151 saved_header_data_.length(),
152 &headers));
153 EXPECT_EQ(headers_, headers);
154 saved_header_data_.clear();
157 bool is_server() {
158 return GetParam();
161 void CloseConnection() {
162 QuicConnectionPeer::CloseConnection(connection_);
165 static const bool kNotUnidirectional = false;
166 static const bool kNoAssociatedStream = false;
168 StrictMock<MockConnection>* connection_;
169 StrictMock<MockSession> session_;
170 QuicHeadersStream* headers_stream_;
171 SpdyHeaderBlock headers_;
172 string body_;
173 string saved_data_;
174 string saved_header_data_;
175 SpdyFramer framer_;
176 StrictMock<MockVisitor> visitor_;
179 INSTANTIATE_TEST_CASE_P(Tests, QuicHeadersStreamTest, testing::Bool());
181 TEST_P(QuicHeadersStreamTest, StreamId) {
182 EXPECT_EQ(3u, headers_stream_->id());
185 TEST_P(QuicHeadersStreamTest, EffectivePriority) {
186 EXPECT_EQ(0u, headers_stream_->EffectivePriority());
189 TEST_P(QuicHeadersStreamTest, WriteHeaders) {
190 for (QuicStreamId stream_id = 5; stream_id < 9; stream_id +=2) {
191 for (int count = 0; count < 2; ++count) {
192 bool fin = (count == 0);
193 if (is_server()) {
194 WriteHeadersAndExpectSynReply(stream_id, fin);
195 } else {
196 for (QuicPriority priority = 0; priority < 7; ++priority) {
197 WriteHeadersAndExpectSynStream(stream_id, fin, priority);
204 TEST_P(QuicHeadersStreamTest, ProcessRawData) {
205 for (QuicStreamId stream_id = 5; stream_id < 9; stream_id +=2) {
206 for (int count = 0; count < 2; ++count) {
207 bool fin = (count == 0);
208 for (QuicPriority priority = 0; priority < 7; ++priority) {
209 // Replace with "WriteHeadersAndSaveData"
210 scoped_ptr<SpdySerializedFrame> frame;
211 if (is_server()) {
212 SpdySynStreamIR syn_stream(stream_id);
213 syn_stream.set_name_value_block(headers_);
214 syn_stream.set_fin(fin);
215 frame.reset(framer_.SerializeSynStream(syn_stream));
216 EXPECT_CALL(session_, OnStreamHeadersPriority(stream_id, 0));
217 } else {
218 SpdySynReplyIR syn_reply(stream_id);
219 syn_reply.set_name_value_block(headers_);
220 syn_reply.set_fin(fin);
221 frame.reset(framer_.SerializeSynReply(syn_reply));
223 EXPECT_CALL(session_, OnStreamHeaders(stream_id, _))
224 .WillRepeatedly(WithArgs<1>(
225 Invoke(this,
226 &QuicHeadersStreamTest::SaveHeaderDataStringPiece)));
227 EXPECT_CALL(session_,
228 OnStreamHeadersComplete(stream_id, fin, frame->size()));
229 headers_stream_->ProcessRawData(frame->data(), frame->size());
231 CheckHeaders();
237 TEST_P(QuicHeadersStreamTest, ProcessSpdyDataFrame) {
238 SpdyDataIR data(2, "");
239 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
240 EXPECT_CALL(*connection_,
241 SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
242 "SPDY DATA frame received."))
243 .WillOnce(InvokeWithoutArgs(this,
244 &QuicHeadersStreamTest::CloseConnection));
245 headers_stream_->ProcessRawData(frame->data(), frame->size());
248 TEST_P(QuicHeadersStreamTest, ProcessSpdyRstStreamFrame) {
249 SpdyRstStreamIR data(2, RST_STREAM_PROTOCOL_ERROR, "");
250 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
251 EXPECT_CALL(*connection_,
252 SendConnectionCloseWithDetails(
253 QUIC_INVALID_HEADERS_STREAM_DATA,
254 "SPDY RST_STREAM frame received."))
255 .WillOnce(InvokeWithoutArgs(this,
256 &QuicHeadersStreamTest::CloseConnection));
257 headers_stream_->ProcessRawData(frame->data(), frame->size());
260 TEST_P(QuicHeadersStreamTest, ProcessSpdySettingsFrame) {
261 SpdySettingsIR data;
262 data.AddSetting(SETTINGS_UPLOAD_BANDWIDTH, true, true, 0);
263 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
264 EXPECT_CALL(*connection_,
265 SendConnectionCloseWithDetails(
266 QUIC_INVALID_HEADERS_STREAM_DATA,
267 "SPDY SETTINGS frame received."))
268 .WillOnce(InvokeWithoutArgs(this,
269 &QuicHeadersStreamTest::CloseConnection));
270 headers_stream_->ProcessRawData(frame->data(), frame->size());
273 TEST_P(QuicHeadersStreamTest, ProcessSpdyPingFrame) {
274 SpdyPingIR data(1);
275 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
276 EXPECT_CALL(*connection_,
277 SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
278 "SPDY PING frame received."))
279 .WillOnce(InvokeWithoutArgs(this,
280 &QuicHeadersStreamTest::CloseConnection));
281 headers_stream_->ProcessRawData(frame->data(), frame->size());
284 TEST_P(QuicHeadersStreamTest, ProcessSpdyGoAwayFrame) {
285 SpdyGoAwayIR data(1, GOAWAY_PROTOCOL_ERROR, "go away");
286 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
287 EXPECT_CALL(*connection_,
288 SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
289 "SPDY GOAWAY frame received."))
290 .WillOnce(InvokeWithoutArgs(this,
291 &QuicHeadersStreamTest::CloseConnection));
292 headers_stream_->ProcessRawData(frame->data(), frame->size());
295 TEST_P(QuicHeadersStreamTest, ProcessSpdyHeadersFrame) {
296 SpdyHeadersIR data(1);
297 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
298 EXPECT_CALL(*connection_,
299 SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
300 "SPDY HEADERS frame received."))
301 .WillOnce(InvokeWithoutArgs(this,
302 &QuicHeadersStreamTest::CloseConnection));
303 headers_stream_->ProcessRawData(frame->data(), frame->size());
306 TEST_P(QuicHeadersStreamTest, ProcessSpdyWindowUpdateFrame) {
307 SpdyWindowUpdateIR data(1, 1);
308 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
309 EXPECT_CALL(*connection_,
310 SendConnectionCloseWithDetails(
311 QUIC_INVALID_HEADERS_STREAM_DATA,
312 "SPDY WINDOW_UPDATE frame received."))
313 .WillOnce(InvokeWithoutArgs(this,
314 &QuicHeadersStreamTest::CloseConnection));
315 headers_stream_->ProcessRawData(frame->data(), frame->size());
318 } // namespace
319 } // namespace test
320 } // namespace net