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