Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / net / quic / quic_headers_stream_test.cc
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.
4
5 #include "net/quic/quic_headers_stream.h"
6
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"
14
15 using base::StringPiece;
16 using std::string;
17 using testing::Invoke;
18 using testing::Return;
19 using testing::StrictMock;
20 using testing::WithArgs;
21 using testing::_;
22
23 namespace net {
24 namespace test {
25 namespace {
26
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_METHOD1(OnPing, void(SpdyPingId unique_id));
51   MOCK_METHOD2(OnGoAway, void(SpdyStreamId last_accepted_stream_id,
52                               SpdyGoAwayStatus status));
53   MOCK_METHOD2(OnHeaders, void(SpdyStreamId stream_id, bool fin));
54   MOCK_METHOD2(OnWindowUpdate, void(SpdyStreamId stream_id,
55                                     uint32 delta_window_size));
56   MOCK_METHOD2(OnCredentialFrameData, bool(const char* credential_data,
57                                            size_t len));
58   MOCK_METHOD1(OnBlocked, void(SpdyStreamId stream_id));
59   MOCK_METHOD2(OnPushPromise, void(SpdyStreamId stream_id,
60                                    SpdyStreamId promised_stream_id));
61 };
62
63 class QuicHeadersStreamTest : public ::testing::TestWithParam<bool> {
64  public:
65   static QuicVersionVector GetVersions() {
66     QuicVersionVector versions;
67     versions.push_back(QUIC_VERSION_13);
68     return versions;
69   }
70
71   QuicHeadersStreamTest()
72       : connection_(new StrictMock<MockConnection>(is_server(), GetVersions())),
73         session_(connection_),
74         headers_stream_(QuicSessionPeer::GetHeadersStream(&session_)),
75         body_("hello world"),
76         framer_(SPDY3) {
77     headers_[":version"]  = "HTTP/1.1";
78     headers_[":status"] = "200 Ok";
79     headers_["content-length"] = "11";
80     framer_.set_visitor(&visitor_);
81     EXPECT_EQ(QUIC_VERSION_13, session_.connection()->version());
82     EXPECT_TRUE(headers_stream_ != NULL);
83   }
84
85   QuicConsumedData SaveIov(const struct iovec* iov, int count) {
86     for (int i = 0 ; i < count; ++i) {
87       saved_data_.append(static_cast<char*>(iov[i].iov_base), iov[i].iov_len);
88     }
89     return QuicConsumedData(saved_data_.length(), false);
90   }
91
92   bool SaveHeaderData(const char* data, int len) {
93     saved_header_data_.append(data, len);
94     return true;
95   }
96
97   void SaveHeaderDataStringPiece(StringPiece data) {
98     saved_header_data_.append(data.data(), data.length());
99   }
100
101   void WriteHeadersAndExpectSynStream(QuicStreamId stream_id,
102                                       bool fin,
103                                       QuicPriority priority) {
104     WriteHeadersAndCheckData(stream_id, fin, priority, SYN_STREAM);
105   }
106
107   void WriteHeadersAndExpectSynReply(QuicStreamId stream_id,
108                                      bool fin) {
109     WriteHeadersAndCheckData(stream_id, fin, 0, SYN_REPLY);
110   }
111
112   void WriteHeadersAndCheckData(QuicStreamId stream_id,
113                                 bool fin,
114                                 QuicPriority priority,
115                                 SpdyFrameType type) {
116     // Write the headers and capture the outgoing data
117     EXPECT_CALL(session_, WritevData(kHeadersStreamId, _, _, _, false, NULL))
118         .WillOnce(WithArgs<1, 2>(
119             Invoke(this, &QuicHeadersStreamTest::SaveIov)));
120     headers_stream_->WriteHeaders(stream_id, headers_, fin);
121
122     // Parse the outgoing data and check that it matches was was written.
123     if (type == SYN_STREAM) {
124       EXPECT_CALL(visitor_, OnSynStream(stream_id, kNoAssociatedStream, 0,
125                                         // priority,
126                                         fin, kNotUnidirectional));
127     } else {
128       EXPECT_CALL(visitor_, OnSynReply(stream_id, fin));
129     }
130     EXPECT_CALL(visitor_, OnControlFrameHeaderData(stream_id, _, _))
131         .WillRepeatedly(WithArgs<1, 2>(
132             Invoke(this, &QuicHeadersStreamTest::SaveHeaderData)));
133     if (fin) {
134       EXPECT_CALL(visitor_, OnStreamFrameData(stream_id, NULL, 0, true));
135     }
136     framer_.ProcessInput(saved_data_.data(), saved_data_.length());
137     EXPECT_FALSE(framer_.HasError()) << framer_.error_code();
138
139     CheckHeaders();
140     saved_data_.clear();
141   }
142
143   void CheckHeaders() {
144     SpdyHeaderBlock headers;
145     EXPECT_EQ(saved_header_data_.length(),
146               framer_.ParseHeaderBlockInBuffer(saved_header_data_.data(),
147                                                saved_header_data_.length(),
148                                                &headers));
149     EXPECT_EQ(headers_, headers);
150     saved_header_data_.clear();
151   }
152
153   bool is_server() {
154     return GetParam();
155   }
156
157   void CloseConnection() {
158     QuicConnectionPeer::CloseConnection(connection_);
159   }
160
161   static const bool kNotUnidirectional = false;
162   static const bool kNoAssociatedStream = false;
163
164   StrictMock<MockConnection>* connection_;
165   StrictMock<MockSession> session_;
166   QuicHeadersStream* headers_stream_;
167   SpdyHeaderBlock headers_;
168   string body_;
169   string saved_data_;
170   string saved_header_data_;
171   SpdyFramer framer_;
172   StrictMock<MockVisitor> visitor_;
173 };
174
175 INSTANTIATE_TEST_CASE_P(Tests, QuicHeadersStreamTest, testing::Bool());
176
177 TEST_P(QuicHeadersStreamTest, StreamId) {
178   EXPECT_EQ(3u, headers_stream_->id());
179 }
180
181 TEST_P(QuicHeadersStreamTest, EffectivePriority) {
182   EXPECT_EQ(0u, headers_stream_->EffectivePriority());
183 }
184
185 TEST_P(QuicHeadersStreamTest, WriteHeaders) {
186   for (QuicStreamId stream_id = 5; stream_id < 9; stream_id +=2) {
187     for (int count = 0; count < 2; ++count) {
188       bool fin = (count == 0);
189       if (is_server()) {
190         WriteHeadersAndExpectSynReply(stream_id, fin);
191       } else {
192         for (QuicPriority priority = 0; priority < 7; ++priority) {
193           WriteHeadersAndExpectSynStream(stream_id, fin, priority);
194         }
195       }
196     }
197   }
198 }
199
200 TEST_P(QuicHeadersStreamTest, ProcessRawData) {
201   for (QuicStreamId stream_id = 5; stream_id < 9; stream_id +=2) {
202     for (int count = 0; count < 2; ++count) {
203       bool fin = (count == 0);
204       for (QuicPriority priority = 0; priority < 7; ++priority) {
205         // Replace with "WriteHeadersAndSaveData"
206         scoped_ptr<SpdySerializedFrame> frame;
207         if (is_server()) {
208           SpdySynStreamIR syn_stream(stream_id);
209           syn_stream.set_name_value_block(headers_);
210           syn_stream.set_fin(fin);
211           frame.reset(framer_.SerializeSynStream(syn_stream));
212           EXPECT_CALL(session_, OnStreamHeadersPriority(stream_id, 0));
213         } else {
214           SpdySynReplyIR syn_reply(stream_id);
215           syn_reply.set_name_value_block(headers_);
216           syn_reply.set_fin(fin);
217           frame.reset(framer_.SerializeSynReply(syn_reply));
218         }
219         EXPECT_CALL(session_, OnStreamHeaders(stream_id, _))
220             .WillRepeatedly(WithArgs<1>(
221                 Invoke(this,
222                        &QuicHeadersStreamTest::SaveHeaderDataStringPiece)));
223         EXPECT_CALL(session_,
224                     OnStreamHeadersComplete(stream_id, fin, frame->size()));
225         headers_stream_->ProcessRawData(frame->data(), frame->size());
226
227         CheckHeaders();
228       }
229     }
230   }
231 }
232
233 TEST_P(QuicHeadersStreamTest, ProcessSpdyDataFrame) {
234   SpdyDataIR data(2, "");
235   scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
236   EXPECT_CALL(*connection_,
237               SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
238                                              "SPDY DATA frame recevied."))
239       .WillOnce(InvokeWithoutArgs(this,
240                                   &QuicHeadersStreamTest::CloseConnection));
241   headers_stream_->ProcessRawData(frame->data(), frame->size());
242 }
243
244 TEST_P(QuicHeadersStreamTest, ProcessSpdyRstStreamFrame) {
245   SpdyRstStreamIR data(2, RST_STREAM_PROTOCOL_ERROR, "");
246   scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
247   EXPECT_CALL(*connection_,
248               SendConnectionCloseWithDetails(
249                   QUIC_INVALID_HEADERS_STREAM_DATA,
250                   "SPDY RST_STREAM frame recevied."))
251       .WillOnce(InvokeWithoutArgs(this,
252                                   &QuicHeadersStreamTest::CloseConnection));
253   headers_stream_->ProcessRawData(frame->data(), frame->size());
254 }
255
256 TEST_P(QuicHeadersStreamTest, ProcessSpdySettingsFrame) {
257   SpdySettingsIR data;
258   data.AddSetting(SETTINGS_UPLOAD_BANDWIDTH, true, true, 0);
259   scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
260   EXPECT_CALL(*connection_,
261               SendConnectionCloseWithDetails(
262                   QUIC_INVALID_HEADERS_STREAM_DATA,
263                   "SPDY SETTINGS frame recevied."))
264       .WillOnce(InvokeWithoutArgs(this,
265                                   &QuicHeadersStreamTest::CloseConnection));
266   headers_stream_->ProcessRawData(frame->data(), frame->size());
267 }
268
269 TEST_P(QuicHeadersStreamTest, ProcessSpdyPingFrame) {
270   SpdyPingIR data(1);
271   scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
272   EXPECT_CALL(*connection_,
273               SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
274                                              "SPDY PING frame recevied."))
275       .WillOnce(InvokeWithoutArgs(this,
276                                   &QuicHeadersStreamTest::CloseConnection));
277   headers_stream_->ProcessRawData(frame->data(), frame->size());
278 }
279
280 TEST_P(QuicHeadersStreamTest, ProcessSpdyGoAwayFrame) {
281   SpdyGoAwayIR data(1, GOAWAY_PROTOCOL_ERROR, "go away");
282   scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
283   EXPECT_CALL(*connection_,
284               SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
285                                              "SPDY GOAWAY frame recevied."))
286       .WillOnce(InvokeWithoutArgs(this,
287                                   &QuicHeadersStreamTest::CloseConnection));
288   headers_stream_->ProcessRawData(frame->data(), frame->size());
289 }
290
291 TEST_P(QuicHeadersStreamTest, ProcessSpdyHeadersFrame) {
292   SpdyHeadersIR data(1);
293   scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
294   EXPECT_CALL(*connection_,
295               SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
296                                              "SPDY HEADERS frame recevied."))
297       .WillOnce(InvokeWithoutArgs(this,
298                                   &QuicHeadersStreamTest::CloseConnection));
299   headers_stream_->ProcessRawData(frame->data(), frame->size());
300 }
301
302 TEST_P(QuicHeadersStreamTest, ProcessSpdyWindowUpdateFrame) {
303   SpdyWindowUpdateIR data(1, 1);
304   scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data));
305   EXPECT_CALL(*connection_,
306               SendConnectionCloseWithDetails(
307                   QUIC_INVALID_HEADERS_STREAM_DATA,
308                   "SPDY WINDOW_UPDATE frame recevied."))
309       .WillOnce(InvokeWithoutArgs(this,
310                                   &QuicHeadersStreamTest::CloseConnection));
311   headers_stream_->ProcessRawData(frame->data(), frame->size());
312 }
313
314 }  // namespace
315 }  // namespace test
316 }  // namespace net