Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / net / spdy / buffered_spdy_framer_unittest.cc
1 // Copyright (c) 2012 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/spdy/buffered_spdy_framer.h"
6
7 #include "net/spdy/spdy_test_util_common.h"
8 #include "testing/platform_test.h"
9
10 namespace net {
11
12 namespace {
13
14 class TestBufferedSpdyVisitor : public BufferedSpdyFramerVisitorInterface {
15  public:
16   explicit TestBufferedSpdyVisitor(SpdyMajorVersion spdy_version)
17       : buffered_spdy_framer_(spdy_version, true),
18         error_count_(0),
19         setting_count_(0),
20         syn_frame_count_(0),
21         syn_reply_frame_count_(0),
22         headers_frame_count_(0),
23         header_stream_id_(-1) {
24   }
25
26   virtual void OnError(SpdyFramer::SpdyError error_code) OVERRIDE {
27     LOG(INFO) << "SpdyFramer Error: " << error_code;
28     error_count_++;
29   }
30
31   virtual void OnStreamError(
32       SpdyStreamId stream_id,
33       const std::string& description) OVERRIDE {
34     LOG(INFO) << "SpdyFramer Error on stream: " << stream_id  << " "
35               << description;
36     error_count_++;
37   }
38
39   virtual void OnSynStream(SpdyStreamId stream_id,
40                            SpdyStreamId associated_stream_id,
41                            SpdyPriority priority,
42                            bool fin,
43                            bool unidirectional,
44                            const SpdyHeaderBlock& headers) OVERRIDE {
45     header_stream_id_ = stream_id;
46     EXPECT_NE(header_stream_id_, SpdyFramer::kInvalidStream);
47     syn_frame_count_++;
48     headers_ = headers;
49   }
50
51   virtual void OnSynReply(SpdyStreamId stream_id,
52                           bool fin,
53                           const SpdyHeaderBlock& headers) OVERRIDE {
54     header_stream_id_ = stream_id;
55     EXPECT_NE(header_stream_id_, SpdyFramer::kInvalidStream);
56     syn_reply_frame_count_++;
57     headers_ = headers;
58   }
59
60   virtual void OnHeaders(SpdyStreamId stream_id,
61                          bool fin,
62                          const SpdyHeaderBlock& headers) OVERRIDE {
63     header_stream_id_ = stream_id;
64     EXPECT_NE(header_stream_id_, SpdyFramer::kInvalidStream);
65     headers_frame_count_++;
66     headers_ = headers;
67   }
68
69   virtual void OnDataFrameHeader(SpdyStreamId stream_id,
70                                  size_t length,
71                                  bool fin) OVERRIDE {
72     ADD_FAILURE() << "Unexpected OnDataFrameHeader call.";
73   }
74
75   virtual void OnStreamFrameData(SpdyStreamId stream_id,
76                                  const char* data,
77                                  size_t len,
78                                  bool fin) OVERRIDE {
79     LOG(FATAL) << "Unexpected OnStreamFrameData call.";
80   }
81
82   virtual void OnSettings(bool clear_persisted) OVERRIDE {}
83
84   virtual void OnSetting(SpdySettingsIds id,
85                          uint8 flags,
86                          uint32 value) OVERRIDE {
87     setting_count_++;
88   }
89
90   virtual void OnPing(SpdyPingId unique_id) OVERRIDE {}
91
92   virtual void OnRstStream(SpdyStreamId stream_id,
93                            SpdyRstStreamStatus status) OVERRIDE {
94   }
95
96   virtual void OnGoAway(SpdyStreamId last_accepted_stream_id,
97                         SpdyGoAwayStatus status) OVERRIDE {
98   }
99
100   bool OnCredentialFrameData(const char*, size_t) {
101     LOG(FATAL) << "Unexpected OnCredentialFrameData call.";
102     return false;
103   }
104
105   void OnDataFrameHeader(const SpdyFrame* frame) {
106     LOG(FATAL) << "Unexpected OnDataFrameHeader call.";
107   }
108
109   void OnRstStream(const SpdyFrame& frame) {}
110   void OnGoAway(const SpdyFrame& frame) {}
111   void OnPing(const SpdyFrame& frame) {}
112   virtual void OnWindowUpdate(SpdyStreamId stream_id,
113                               uint32 delta_window_size) OVERRIDE {}
114   virtual void OnPushPromise(SpdyStreamId stream_id,
115                              SpdyStreamId promised_stream_id) OVERRIDE {}
116   void OnCredential(const SpdyFrame& frame) {}
117
118   // Convenience function which runs a framer simulation with particular input.
119   void SimulateInFramer(const unsigned char* input, size_t size) {
120     buffered_spdy_framer_.set_visitor(this);
121     size_t input_remaining = size;
122     const char* input_ptr = reinterpret_cast<const char*>(input);
123     while (input_remaining > 0 &&
124            buffered_spdy_framer_.error_code() == SpdyFramer::SPDY_NO_ERROR) {
125       // To make the tests more interesting, we feed random (amd small) chunks
126       // into the framer.  This simulates getting strange-sized reads from
127       // the socket.
128       const size_t kMaxReadSize = 32;
129       size_t bytes_read =
130           (rand() % std::min(input_remaining, kMaxReadSize)) + 1;
131       size_t bytes_processed =
132           buffered_spdy_framer_.ProcessInput(input_ptr, bytes_read);
133       input_remaining -= bytes_processed;
134       input_ptr += bytes_processed;
135     }
136   }
137
138   BufferedSpdyFramer buffered_spdy_framer_;
139
140   // Counters from the visitor callbacks.
141   int error_count_;
142   int setting_count_;
143   int syn_frame_count_;
144   int syn_reply_frame_count_;
145   int headers_frame_count_;
146
147   // Header block streaming state:
148   SpdyStreamId header_stream_id_;
149
150   // Headers from OnSyn, OnSynReply and OnHeaders for verification.
151   SpdyHeaderBlock headers_;
152 };
153
154 }  // namespace
155
156 class BufferedSpdyFramerTest
157     : public PlatformTest,
158       public ::testing::WithParamInterface<NextProto> {
159  protected:
160   // Returns true if the two header blocks have equivalent content.
161   bool CompareHeaderBlocks(const SpdyHeaderBlock* expected,
162                            const SpdyHeaderBlock* actual) {
163     if (expected->size() != actual->size()) {
164       LOG(ERROR) << "Expected " << expected->size() << " headers; actually got "
165                  << actual->size() << ".";
166       return false;
167     }
168     for (SpdyHeaderBlock::const_iterator it = expected->begin();
169          it != expected->end();
170          ++it) {
171       SpdyHeaderBlock::const_iterator it2 = actual->find(it->first);
172       if (it2 == actual->end()) {
173         LOG(ERROR) << "Expected header name '" << it->first << "'.";
174         return false;
175       }
176       if (it->second.compare(it2->second) != 0) {
177         LOG(ERROR) << "Expected header named '" << it->first
178                    << "' to have a value of '" << it->second
179                    << "'. The actual value received was '" << it2->second
180                    << "'.";
181         return false;
182       }
183     }
184     return true;
185   }
186
187   SpdyMajorVersion spdy_version() {
188     return NextProtoToSpdyMajorVersion(GetParam());
189   }
190 };
191
192 INSTANTIATE_TEST_CASE_P(
193     NextProto,
194     BufferedSpdyFramerTest,
195     testing::Values(kProtoDeprecatedSPDY2,
196                     kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
197                     kProtoHTTP2Draft04));
198
199 TEST_P(BufferedSpdyFramerTest, OnSetting) {
200   SpdyFramer framer(spdy_version());
201   SpdySettingsIR settings_ir;
202   settings_ir.AddSetting(SETTINGS_UPLOAD_BANDWIDTH, false, false, 0x00000002);
203   settings_ir.AddSetting(SETTINGS_DOWNLOAD_BANDWIDTH, false, false, 0x00000003);
204   scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir));
205   TestBufferedSpdyVisitor visitor(spdy_version());
206
207   visitor.SimulateInFramer(
208       reinterpret_cast<unsigned char*>(control_frame->data()),
209       control_frame->size());
210   EXPECT_EQ(0, visitor.error_count_);
211   EXPECT_EQ(2, visitor.setting_count_);
212 }
213
214 TEST_P(BufferedSpdyFramerTest, ReadSynStreamHeaderBlock) {
215   SpdyHeaderBlock headers;
216   headers["aa"] = "vv";
217   headers["bb"] = "ww";
218   BufferedSpdyFramer framer(spdy_version(), true);
219   scoped_ptr<SpdyFrame> control_frame(
220       framer.CreateSynStream(1,                        // stream_id
221                              0,                        // associated_stream_id
222                              1,                        // priority
223                              CONTROL_FLAG_NONE,
224                              &headers));
225   EXPECT_TRUE(control_frame.get() != NULL);
226
227   TestBufferedSpdyVisitor visitor(spdy_version());
228   visitor.SimulateInFramer(
229       reinterpret_cast<unsigned char*>(control_frame.get()->data()),
230       control_frame.get()->size());
231   EXPECT_EQ(0, visitor.error_count_);
232   EXPECT_EQ(1, visitor.syn_frame_count_);
233   EXPECT_EQ(0, visitor.syn_reply_frame_count_);
234   EXPECT_EQ(0, visitor.headers_frame_count_);
235   EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
236 }
237
238 TEST_P(BufferedSpdyFramerTest, ReadSynReplyHeaderBlock) {
239   SpdyHeaderBlock headers;
240   headers["alpha"] = "beta";
241   headers["gamma"] = "delta";
242   BufferedSpdyFramer framer(spdy_version(), true);
243   scoped_ptr<SpdyFrame> control_frame(
244       framer.CreateSynReply(1,                        // stream_id
245                             CONTROL_FLAG_NONE,
246                             &headers));
247   EXPECT_TRUE(control_frame.get() != NULL);
248
249   TestBufferedSpdyVisitor visitor(spdy_version());
250   visitor.SimulateInFramer(
251       reinterpret_cast<unsigned char*>(control_frame.get()->data()),
252       control_frame.get()->size());
253   EXPECT_EQ(0, visitor.error_count_);
254   EXPECT_EQ(0, visitor.syn_frame_count_);
255   if(spdy_version() < SPDY4) {
256     EXPECT_EQ(1, visitor.syn_reply_frame_count_);
257     EXPECT_EQ(0, visitor.headers_frame_count_);
258   } else {
259     EXPECT_EQ(0, visitor.syn_reply_frame_count_);
260     EXPECT_EQ(1, visitor.headers_frame_count_);
261   }
262   EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
263 }
264
265 TEST_P(BufferedSpdyFramerTest, ReadHeadersHeaderBlock) {
266   SpdyHeaderBlock headers;
267   headers["alpha"] = "beta";
268   headers["gamma"] = "delta";
269   BufferedSpdyFramer framer(spdy_version(), true);
270   scoped_ptr<SpdyFrame> control_frame(
271       framer.CreateHeaders(1,                        // stream_id
272                            CONTROL_FLAG_NONE,
273                            &headers));
274   EXPECT_TRUE(control_frame.get() != NULL);
275
276   TestBufferedSpdyVisitor visitor(spdy_version());
277   visitor.SimulateInFramer(
278       reinterpret_cast<unsigned char*>(control_frame.get()->data()),
279       control_frame.get()->size());
280   EXPECT_EQ(0, visitor.error_count_);
281   EXPECT_EQ(0, visitor.syn_frame_count_);
282   EXPECT_EQ(0, visitor.syn_reply_frame_count_);
283   EXPECT_EQ(1, visitor.headers_frame_count_);
284   EXPECT_TRUE(CompareHeaderBlocks(&headers, &visitor.headers_));
285 }
286
287 }  // namespace net