Upstream version 10.39.225.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/quic/test_tools/reliable_quic_stream_peer.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   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));
72 };
73
74 class QuicHeadersStreamTest : public ::testing::TestWithParam<bool> {
75  public:
76   static QuicVersionVector GetVersions() {
77     QuicVersionVector versions;
78     versions.push_back(QuicVersionMax());
79     return versions;
80   }
81
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);
94   }
95
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);
101     }
102     return QuicConsumedData(saved_data_.length(), false);
103   }
104
105   bool SaveHeaderData(const char* data, int len) {
106     saved_header_data_.append(data, len);
107     return true;
108   }
109
110   void SaveHeaderDataStringPiece(StringPiece data) {
111     saved_header_data_.append(data.data(), data.length());
112   }
113
114   void WriteHeadersAndExpectSynStream(QuicStreamId stream_id,
115                                       bool fin,
116                                       QuicPriority priority) {
117     WriteHeadersAndCheckData(stream_id, fin, priority, SYN_STREAM);
118   }
119
120   void WriteHeadersAndExpectSynReply(QuicStreamId stream_id,
121                                      bool fin) {
122     WriteHeadersAndCheckData(stream_id, fin, 0, SYN_REPLY);
123   }
124
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);
133
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));
141     }
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));
147     }
148     framer_.ProcessInput(saved_data_.data(), saved_data_.length());
149     EXPECT_FALSE(framer_.HasError()) << framer_.error_code();
150
151     CheckHeaders();
152     saved_data_.clear();
153   }
154
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();
163   }
164
165   bool is_server() {
166     return GetParam();
167   }
168
169   void CloseConnection() {
170     QuicConnectionPeer::CloseConnection(connection_);
171   }
172
173   static const bool kNotUnidirectional = false;
174   static const bool kNoAssociatedStream = false;
175
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_;
185 };
186
187 INSTANTIATE_TEST_CASE_P(Tests, QuicHeadersStreamTest, testing::Bool());
188
189 TEST_P(QuicHeadersStreamTest, StreamId) {
190   EXPECT_EQ(3u, headers_stream_->id());
191 }
192
193 TEST_P(QuicHeadersStreamTest, EffectivePriority) {
194   EXPECT_EQ(0u, headers_stream_->EffectivePriority());
195 }
196
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);
207         }
208       }
209     }
210   }
211 }
212
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));
232         }
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());
240
241         CheckHeaders();
242       }
243     }
244   }
245 }
246
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());
256 }
257
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());
268 }
269
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());
281 }
282
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());
292 }
293
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());
303 }
304
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());
314 }
315
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());
326 }
327
328 TEST_P(QuicHeadersStreamTest, NoConnectionLevelFlowControl) {
329   if (connection_->version() < QUIC_VERSION_21) {
330     EXPECT_FALSE(headers_stream_->flow_controller()->IsEnabled());
331   } else {
332     EXPECT_TRUE(headers_stream_->flow_controller()->IsEnabled());
333   }
334   EXPECT_FALSE(ReliableQuicStreamPeer::StreamContributesToConnectionFlowControl(
335       headers_stream_));
336 }
337
338 }  // namespace
339 }  // namespace test
340 }  // namespace net