OLD | NEW |
| (Empty) |
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/tools/flip_server/spdy_interface.h" | |
6 | |
7 #include <list> | |
8 | |
9 #include "base/memory/scoped_ptr.h" | |
10 #include "base/strings/string_piece.h" | |
11 #include "net/spdy/buffered_spdy_framer.h" | |
12 #include "net/tools/balsa/balsa_enums.h" | |
13 #include "net/tools/balsa/balsa_headers.h" | |
14 #include "net/tools/flip_server/flip_config.h" | |
15 #include "net/tools/flip_server/flip_test_utils.h" | |
16 #include "net/tools/flip_server/mem_cache.h" | |
17 #include "testing/gmock/include/gmock/gmock.h" | |
18 #include "testing/gtest/include/gtest/gtest.h" | |
19 | |
20 namespace net { | |
21 | |
22 using ::base::StringPiece; | |
23 using ::testing::_; | |
24 using ::testing::InSequence; | |
25 using ::testing::InvokeWithoutArgs; | |
26 using ::testing::Return; | |
27 using ::testing::SaveArg; | |
28 using ::testing::Values; | |
29 | |
30 namespace { | |
31 | |
32 struct StringSaver { | |
33 public: | |
34 StringSaver() : data(NULL), size(0) {} | |
35 void Save() { string = std::string(data, size); } | |
36 | |
37 const char* data; | |
38 size_t size; | |
39 std::string string; | |
40 }; | |
41 | |
42 class SpdyFramerVisitor : public BufferedSpdyFramerVisitorInterface { | |
43 public: | |
44 virtual ~SpdyFramerVisitor() {} | |
45 MOCK_METHOD1(OnError, void(SpdyFramer::SpdyError)); | |
46 MOCK_METHOD2(OnStreamError, void(SpdyStreamId, const std::string&)); | |
47 MOCK_METHOD6(OnSynStream, | |
48 void(SpdyStreamId, | |
49 SpdyStreamId, | |
50 SpdyPriority, | |
51 bool, | |
52 bool, | |
53 const SpdyHeaderBlock&)); | |
54 MOCK_METHOD3(OnSynReply, void(SpdyStreamId, bool, const SpdyHeaderBlock&)); | |
55 MOCK_METHOD5(OnHeaders, | |
56 void(SpdyStreamId, | |
57 bool, | |
58 SpdyPriority, | |
59 bool, | |
60 const SpdyHeaderBlock&)); | |
61 MOCK_METHOD3(OnDataFrameHeader, void(SpdyStreamId, size_t, bool)); | |
62 MOCK_METHOD4(OnStreamFrameData, void(SpdyStreamId, | |
63 const char*, | |
64 size_t, | |
65 bool)); | |
66 MOCK_METHOD1(OnSettings, void(bool clear_persisted)); | |
67 MOCK_METHOD3(OnSetting, void(SpdySettingsIds, uint8, uint32)); | |
68 MOCK_METHOD2(OnPing, void(SpdyPingId unique_id, bool is_ack)); | |
69 MOCK_METHOD2(OnRstStream, void(SpdyStreamId, SpdyRstStreamStatus)); | |
70 MOCK_METHOD2(OnGoAway, void(SpdyStreamId, SpdyGoAwayStatus)); | |
71 MOCK_METHOD2(OnWindowUpdate, void(SpdyStreamId, uint32)); | |
72 MOCK_METHOD3(OnPushPromise, | |
73 void(SpdyStreamId, SpdyStreamId, const SpdyHeaderBlock&)); | |
74 MOCK_METHOD2(OnUnknownFrame, bool(SpdyStreamId stream_id, int frame_type)); | |
75 }; | |
76 | |
77 class FakeSMConnection : public SMConnection { | |
78 public: | |
79 FakeSMConnection(EpollServer* epoll_server, | |
80 SSLState* ssl_state, | |
81 MemoryCache* memory_cache, | |
82 FlipAcceptor* acceptor, | |
83 std::string log_prefix) | |
84 : SMConnection(epoll_server, | |
85 ssl_state, | |
86 memory_cache, | |
87 acceptor, | |
88 log_prefix) {} | |
89 | |
90 MOCK_METHOD0(Cleanup, void()); | |
91 MOCK_METHOD8(InitSMConnection, | |
92 void(SMConnectionPoolInterface*, | |
93 SMInterface*, | |
94 EpollServer*, | |
95 int, | |
96 std::string, | |
97 std::string, | |
98 std::string, | |
99 bool)); | |
100 }; | |
101 | |
102 // This class is almost SpdySM, except one function. | |
103 // This class is the test target of tests in this file. | |
104 class TestSpdySM : public SpdySM { | |
105 public: | |
106 virtual ~TestSpdySM() {} | |
107 TestSpdySM(SMConnection* connection, | |
108 SMInterface* sm_http_interface, | |
109 EpollServer* epoll_server, | |
110 MemoryCache* memory_cache, | |
111 FlipAcceptor* acceptor, | |
112 SpdyMajorVersion version) | |
113 : SpdySM(connection, | |
114 sm_http_interface, | |
115 epoll_server, | |
116 memory_cache, | |
117 acceptor, | |
118 version) {} | |
119 | |
120 MOCK_METHOD2(FindOrMakeNewSMConnectionInterface, | |
121 SMInterface*(const std::string&, const std::string&)); | |
122 }; | |
123 | |
124 class SpdySMTestBase : public ::testing::TestWithParam<SpdyMajorVersion> { | |
125 public: | |
126 explicit SpdySMTestBase(FlipHandlerType type) { | |
127 SSLState* ssl_state = NULL; | |
128 mock_another_interface_.reset(new MockSMInterface); | |
129 memory_cache_.reset(new MemoryCache); | |
130 acceptor_.reset(new FlipAcceptor(type, | |
131 "127.0.0.1", | |
132 "8941", | |
133 "ssl_cert_filename", | |
134 "ssl_key_filename", | |
135 "127.0.0.1", | |
136 "8942", | |
137 "127.0.0.1", | |
138 "8943", | |
139 1, | |
140 0, | |
141 true, | |
142 1, | |
143 false, | |
144 true, | |
145 NULL)); | |
146 epoll_server_.reset(new EpollServer); | |
147 connection_.reset(new FakeSMConnection(epoll_server_.get(), | |
148 ssl_state, | |
149 memory_cache_.get(), | |
150 acceptor_.get(), | |
151 "log_prefix")); | |
152 | |
153 interface_.reset(new TestSpdySM(connection_.get(), | |
154 mock_another_interface_.get(), | |
155 epoll_server_.get(), | |
156 memory_cache_.get(), | |
157 acceptor_.get(), | |
158 GetParam())); | |
159 | |
160 spdy_framer_.reset(new BufferedSpdyFramer(GetParam(), true)); | |
161 spdy_framer_visitor_.reset(new SpdyFramerVisitor); | |
162 spdy_framer_->set_visitor(spdy_framer_visitor_.get()); | |
163 } | |
164 | |
165 virtual ~SpdySMTestBase() { | |
166 if (acceptor_->listen_fd_ >= 0) { | |
167 epoll_server_->UnregisterFD(acceptor_->listen_fd_); | |
168 close(acceptor_->listen_fd_); | |
169 acceptor_->listen_fd_ = -1; | |
170 } | |
171 OutputList& output_list = *connection_->output_list(); | |
172 for (OutputList::const_iterator i = output_list.begin(); | |
173 i != output_list.end(); | |
174 ++i) { | |
175 delete *i; | |
176 } | |
177 output_list.clear(); | |
178 } | |
179 | |
180 bool HasStream(uint32 stream_id) { | |
181 return interface_->output_ordering().ExistsInPriorityMaps(stream_id); | |
182 } | |
183 | |
184 protected: | |
185 scoped_ptr<MockSMInterface> mock_another_interface_; | |
186 scoped_ptr<MemoryCache> memory_cache_; | |
187 scoped_ptr<FlipAcceptor> acceptor_; | |
188 scoped_ptr<EpollServer> epoll_server_; | |
189 scoped_ptr<FakeSMConnection> connection_; | |
190 scoped_ptr<TestSpdySM> interface_; | |
191 scoped_ptr<BufferedSpdyFramer> spdy_framer_; | |
192 scoped_ptr<SpdyFramerVisitor> spdy_framer_visitor_; | |
193 }; | |
194 | |
195 class SpdySMProxyTest : public SpdySMTestBase { | |
196 public: | |
197 SpdySMProxyTest() : SpdySMTestBase(FLIP_HANDLER_PROXY) {} | |
198 virtual ~SpdySMProxyTest() {} | |
199 }; | |
200 | |
201 class SpdySMServerTest : public SpdySMTestBase { | |
202 public: | |
203 SpdySMServerTest() : SpdySMTestBase(FLIP_HANDLER_SPDY_SERVER) {} | |
204 virtual ~SpdySMServerTest() {} | |
205 }; | |
206 | |
207 INSTANTIATE_TEST_CASE_P(SpdySMProxyTest, | |
208 SpdySMProxyTest, | |
209 Values(SPDY3, SPDY4)); | |
210 INSTANTIATE_TEST_CASE_P(SpdySMServerTest, SpdySMServerTest, Values(SPDY4)); | |
211 | |
212 TEST_P(SpdySMProxyTest, InitSMConnection) { | |
213 { | |
214 InSequence s; | |
215 EXPECT_CALL(*connection_, InitSMConnection(_, _, _, _, _, _, _, _)); | |
216 } | |
217 interface_->InitSMConnection( | |
218 NULL, NULL, epoll_server_.get(), -1, "", "", "", false); | |
219 } | |
220 | |
221 TEST_P(SpdySMProxyTest, OnStreamFrameData) { | |
222 BufferedSpdyFramerVisitorInterface* visitor = interface_.get(); | |
223 scoped_ptr<MockSMInterface> mock_interface(new MockSMInterface); | |
224 uint32 stream_id = 92; | |
225 uint32 associated_id = 43; | |
226 SpdyHeaderBlock block; | |
227 testing::MockFunction<void(int)> checkpoint; // NOLINT | |
228 | |
229 scoped_ptr<SpdyFrame> frame(spdy_framer_->CreatePingFrame(12, false)); | |
230 block[":method"] = "GET"; | |
231 block[":host"] = "www.example.com"; | |
232 block[":path"] = "/path"; | |
233 block[":scheme"] = "http"; | |
234 block["foo"] = "bar"; | |
235 { | |
236 InSequence s; | |
237 EXPECT_CALL(*interface_, | |
238 FindOrMakeNewSMConnectionInterface(_, _)) | |
239 .WillOnce(Return(mock_interface.get())); | |
240 EXPECT_CALL(*mock_interface, SetStreamID(stream_id)); | |
241 EXPECT_CALL(*mock_interface, ProcessWriteInput(_, _)).Times(1); | |
242 EXPECT_CALL(checkpoint, Call(0)); | |
243 EXPECT_CALL(*mock_interface, | |
244 ProcessWriteInput(frame->data(), frame->size())).Times(1); | |
245 } | |
246 | |
247 visitor->OnSynStream(stream_id, associated_id, 0, false, false, block); | |
248 checkpoint.Call(0); | |
249 visitor->OnStreamFrameData(stream_id, frame->data(), frame->size(), true); | |
250 } | |
251 | |
252 TEST_P(SpdySMProxyTest, OnRstStream) { | |
253 BufferedSpdyFramerVisitorInterface* visitor = interface_.get(); | |
254 uint32 stream_id = 82; | |
255 MemCacheIter mci; | |
256 mci.stream_id = stream_id; | |
257 | |
258 { | |
259 BalsaHeaders headers; | |
260 std::string filename = "foobar"; | |
261 memory_cache_->InsertFile(&headers, filename, ""); | |
262 mci.file_data = memory_cache_->GetFileData(filename); | |
263 } | |
264 | |
265 interface_->AddToOutputOrder(mci); | |
266 ASSERT_TRUE(HasStream(stream_id)); | |
267 visitor->OnRstStream(stream_id, RST_STREAM_INVALID); | |
268 ASSERT_FALSE(HasStream(stream_id)); | |
269 } | |
270 | |
271 TEST_P(SpdySMProxyTest, ProcessReadInput) { | |
272 ASSERT_EQ(SpdyFramer::SPDY_RESET, interface_->spdy_framer()->state()); | |
273 interface_->ProcessReadInput("", 1); | |
274 ASSERT_EQ(SpdyFramer::SPDY_READING_COMMON_HEADER, | |
275 interface_->spdy_framer()->state()); | |
276 } | |
277 | |
278 TEST_P(SpdySMProxyTest, ResetForNewConnection) { | |
279 uint32 stream_id = 13; | |
280 MemCacheIter mci; | |
281 mci.stream_id = stream_id; | |
282 // incomplete input | |
283 const char input[] = {'\0', '\0', '\0'}; | |
284 | |
285 { | |
286 BalsaHeaders headers; | |
287 std::string filename = "foobar"; | |
288 memory_cache_->InsertFile(&headers, filename, ""); | |
289 mci.file_data = memory_cache_->GetFileData(filename); | |
290 } | |
291 | |
292 interface_->AddToOutputOrder(mci); | |
293 ASSERT_TRUE(HasStream(stream_id)); | |
294 interface_->ProcessReadInput(input, sizeof(input)); | |
295 ASSERT_NE(SpdyFramer::SPDY_RESET, interface_->spdy_framer()->state()); | |
296 | |
297 interface_->ResetForNewConnection(); | |
298 ASSERT_FALSE(HasStream(stream_id)); | |
299 ASSERT_TRUE(interface_->spdy_framer() == NULL); | |
300 } | |
301 | |
302 TEST_P(SpdySMProxyTest, CreateFramer) { | |
303 interface_->ResetForNewConnection(); | |
304 interface_->CreateFramer(SPDY3); | |
305 ASSERT_TRUE(interface_->spdy_framer() != NULL); | |
306 ASSERT_EQ(interface_->spdy_version(), SPDY3); | |
307 | |
308 interface_->ResetForNewConnection(); | |
309 interface_->CreateFramer(SPDY4); | |
310 ASSERT_TRUE(interface_->spdy_framer() != NULL); | |
311 ASSERT_EQ(interface_->spdy_version(), SPDY4); | |
312 } | |
313 | |
314 TEST_P(SpdySMProxyTest, PostAcceptHook) { | |
315 interface_->PostAcceptHook(); | |
316 | |
317 ASSERT_EQ(1u, connection_->output_list()->size()); | |
318 std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin(); | |
319 DataFrame* df = *i++; | |
320 | |
321 { | |
322 InSequence s; | |
323 EXPECT_CALL(*spdy_framer_visitor_, OnSettings(false)); | |
324 EXPECT_CALL(*spdy_framer_visitor_, | |
325 OnSetting(SETTINGS_MAX_CONCURRENT_STREAMS, 0u, 100u)); | |
326 } | |
327 spdy_framer_->ProcessInput(df->data, df->size); | |
328 } | |
329 | |
330 TEST_P(SpdySMProxyTest, NewStream) { | |
331 // TODO(yhirano): SpdySM::NewStream leads to crash when | |
332 // acceptor_->flip_handler_type_ != FLIP_HANDLER_SPDY_SERVER. | |
333 // It should be fixed though I don't know the solution now. | |
334 } | |
335 | |
336 TEST_P(SpdySMProxyTest, AddToOutputOrder) { | |
337 uint32 stream_id = 13; | |
338 MemCacheIter mci; | |
339 mci.stream_id = stream_id; | |
340 | |
341 { | |
342 BalsaHeaders headers; | |
343 std::string filename = "foobar"; | |
344 memory_cache_->InsertFile(&headers, filename, ""); | |
345 mci.file_data = memory_cache_->GetFileData(filename); | |
346 } | |
347 | |
348 interface_->AddToOutputOrder(mci); | |
349 ASSERT_TRUE(HasStream(stream_id)); | |
350 } | |
351 | |
352 TEST_P(SpdySMProxyTest, SendErrorNotFound) { | |
353 uint32 stream_id = 82; | |
354 SpdyHeaderBlock actual_header_block; | |
355 const char* actual_data; | |
356 size_t actual_size; | |
357 testing::MockFunction<void(int)> checkpoint; // NOLINT | |
358 | |
359 interface_->SendErrorNotFound(stream_id); | |
360 | |
361 ASSERT_EQ(2u, connection_->output_list()->size()); | |
362 | |
363 { | |
364 InSequence s; | |
365 if (GetParam() < SPDY4) { | |
366 EXPECT_CALL(*spdy_framer_visitor_, | |
367 OnSynReply(stream_id, false, _)) | |
368 .WillOnce(SaveArg<2>(&actual_header_block)); | |
369 } else { | |
370 EXPECT_CALL(*spdy_framer_visitor_, | |
371 OnHeaders(stream_id, false, 0, false, _)) | |
372 .WillOnce(SaveArg<4>(&actual_header_block)); | |
373 } | |
374 EXPECT_CALL(checkpoint, Call(0)); | |
375 EXPECT_CALL(*spdy_framer_visitor_, | |
376 OnDataFrameHeader(stream_id, _, true)); | |
377 EXPECT_CALL(*spdy_framer_visitor_, | |
378 OnStreamFrameData(stream_id, _, _, false)).Times(1) | |
379 .WillOnce(DoAll(SaveArg<1>(&actual_data), | |
380 SaveArg<2>(&actual_size))); | |
381 EXPECT_CALL(*spdy_framer_visitor_, | |
382 OnStreamFrameData(stream_id, NULL, 0, true)).Times(1); | |
383 } | |
384 | |
385 std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin(); | |
386 DataFrame* df = *i++; | |
387 spdy_framer_->ProcessInput(df->data, df->size); | |
388 checkpoint.Call(0); | |
389 df = *i++; | |
390 spdy_framer_->ProcessInput(df->data, df->size); | |
391 | |
392 ASSERT_EQ(2, spdy_framer_->frames_received()); | |
393 ASSERT_EQ(2u, actual_header_block.size()); | |
394 ASSERT_EQ("404 Not Found", actual_header_block[":status"]); | |
395 ASSERT_EQ("HTTP/1.1", actual_header_block[":version"]); | |
396 ASSERT_EQ("wtf?", StringPiece(actual_data, actual_size)); | |
397 } | |
398 | |
399 TEST_P(SpdySMProxyTest, SendSynStream) { | |
400 uint32 stream_id = 82; | |
401 BalsaHeaders headers; | |
402 SpdyHeaderBlock actual_header_block; | |
403 headers.AppendHeader("key1", "value1"); | |
404 headers.AppendHeader("Host", "www.example.com"); | |
405 headers.SetRequestFirstlineFromStringPieces("GET", "/path", "HTTP/1.1"); | |
406 | |
407 interface_->SendSynStream(stream_id, headers); | |
408 | |
409 ASSERT_EQ(1u, connection_->output_list()->size()); | |
410 std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin(); | |
411 DataFrame* df = *i++; | |
412 | |
413 { | |
414 InSequence s; | |
415 EXPECT_CALL(*spdy_framer_visitor_, | |
416 OnSynStream(stream_id, 0, _, false, false, _)) | |
417 .WillOnce(SaveArg<5>(&actual_header_block)); | |
418 } | |
419 | |
420 spdy_framer_->ProcessInput(df->data, df->size); | |
421 ASSERT_EQ(1, spdy_framer_->frames_received()); | |
422 ASSERT_EQ(5u, actual_header_block.size()); | |
423 ASSERT_EQ("GET", actual_header_block[":method"]); | |
424 ASSERT_EQ("HTTP/1.1", actual_header_block[":version"]); | |
425 ASSERT_EQ("/path", actual_header_block[":path"]); | |
426 ASSERT_EQ("www.example.com", actual_header_block[":host"]); | |
427 ASSERT_EQ("value1", actual_header_block["key1"]); | |
428 } | |
429 | |
430 TEST_P(SpdySMProxyTest, SendSynReply) { | |
431 uint32 stream_id = 82; | |
432 BalsaHeaders headers; | |
433 SpdyHeaderBlock actual_header_block; | |
434 headers.AppendHeader("key1", "value1"); | |
435 headers.SetResponseFirstlineFromStringPieces("HTTP/1.1", "200", "OK"); | |
436 | |
437 interface_->SendSynReply(stream_id, headers); | |
438 | |
439 ASSERT_EQ(1u, connection_->output_list()->size()); | |
440 std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin(); | |
441 DataFrame* df = *i++; | |
442 | |
443 { | |
444 InSequence s; | |
445 if (GetParam() < SPDY4) { | |
446 EXPECT_CALL(*spdy_framer_visitor_, OnSynReply(stream_id, false, _)) | |
447 .WillOnce(SaveArg<2>(&actual_header_block)); | |
448 } else { | |
449 EXPECT_CALL(*spdy_framer_visitor_, | |
450 OnHeaders(stream_id, false, 0, false, _)) | |
451 .WillOnce(SaveArg<4>(&actual_header_block)); | |
452 } | |
453 } | |
454 | |
455 spdy_framer_->ProcessInput(df->data, df->size); | |
456 ASSERT_EQ(1, spdy_framer_->frames_received()); | |
457 ASSERT_EQ(3u, actual_header_block.size()); | |
458 ASSERT_EQ("200 OK", actual_header_block[":status"]); | |
459 ASSERT_EQ("HTTP/1.1", actual_header_block[":version"]); | |
460 ASSERT_EQ("value1", actual_header_block["key1"]); | |
461 } | |
462 | |
463 TEST_P(SpdySMProxyTest, SendDataFrame) { | |
464 uint32 stream_id = 133; | |
465 SpdyDataFlags flags = DATA_FLAG_NONE; | |
466 const char* actual_data; | |
467 size_t actual_size; | |
468 | |
469 interface_->SendDataFrame(stream_id, "hello", 5, flags, true); | |
470 | |
471 ASSERT_EQ(1u, connection_->output_list()->size()); | |
472 std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin(); | |
473 DataFrame* df = *i++; | |
474 | |
475 { | |
476 InSequence s; | |
477 EXPECT_CALL(*spdy_framer_visitor_, | |
478 OnDataFrameHeader(stream_id, _, false)); | |
479 EXPECT_CALL(*spdy_framer_visitor_, | |
480 OnStreamFrameData(stream_id, _, _, false)) | |
481 .WillOnce(DoAll(SaveArg<1>(&actual_data), SaveArg<2>(&actual_size))); | |
482 } | |
483 | |
484 spdy_framer_->ProcessInput(df->data, df->size); | |
485 ASSERT_EQ(1, spdy_framer_->frames_received()); | |
486 ASSERT_EQ("hello", StringPiece(actual_data, actual_size)); | |
487 } | |
488 | |
489 TEST_P(SpdySMProxyTest, SendLongDataFrame) { | |
490 uint32 stream_id = 133; | |
491 SpdyDataFlags flags = DATA_FLAG_NONE; | |
492 const char* actual_data; | |
493 size_t actual_size; | |
494 | |
495 std::string data = std::string(kSpdySegmentSize, 'a') + | |
496 std::string(kSpdySegmentSize, 'b') + "c"; | |
497 interface_->SendDataFrame(stream_id, data.data(), data.size(), flags, true); | |
498 | |
499 { | |
500 InSequence s; | |
501 for (int i = 0; i < 3; ++i) { | |
502 EXPECT_CALL(*spdy_framer_visitor_, | |
503 OnDataFrameHeader(stream_id, _, false)); | |
504 EXPECT_CALL(*spdy_framer_visitor_, | |
505 OnStreamFrameData(stream_id, _, _, false)) | |
506 .WillOnce(DoAll(SaveArg<1>(&actual_data), | |
507 SaveArg<2>(&actual_size))); | |
508 } | |
509 } | |
510 | |
511 ASSERT_EQ(3u, connection_->output_list()->size()); | |
512 std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin(); | |
513 DataFrame* df = *i++; | |
514 spdy_framer_->ProcessInput(df->data, df->size); | |
515 ASSERT_EQ(std::string(kSpdySegmentSize, 'a'), | |
516 StringPiece(actual_data, actual_size)); | |
517 | |
518 df = *i++; | |
519 spdy_framer_->ProcessInput(df->data, df->size); | |
520 ASSERT_EQ(std::string(kSpdySegmentSize, 'b'), | |
521 StringPiece(actual_data, actual_size)); | |
522 | |
523 df = *i++; | |
524 spdy_framer_->ProcessInput(df->data, df->size); | |
525 ASSERT_EQ("c", StringPiece(actual_data, actual_size)); | |
526 } | |
527 | |
528 TEST_P(SpdySMServerTest, OnSynStream) { | |
529 BufferedSpdyFramerVisitorInterface* visitor = interface_.get(); | |
530 uint32 stream_id = 82; | |
531 SpdyHeaderBlock spdy_headers; | |
532 spdy_headers["url"] = "http://www.example.com/path"; | |
533 spdy_headers["method"] = "GET"; | |
534 spdy_headers["scheme"] = "http"; | |
535 spdy_headers["version"] = "HTTP/1.1"; | |
536 | |
537 { | |
538 BalsaHeaders headers; | |
539 memory_cache_->InsertFile(&headers, "GET_/path", ""); | |
540 } | |
541 visitor->OnSynStream(stream_id, 0, 0, true, true, spdy_headers); | |
542 ASSERT_TRUE(HasStream(stream_id)); | |
543 } | |
544 | |
545 TEST_P(SpdySMServerTest, NewStream) { | |
546 uint32 stream_id = 13; | |
547 std::string filename = "foobar"; | |
548 | |
549 { | |
550 BalsaHeaders headers; | |
551 memory_cache_->InsertFile(&headers, filename, ""); | |
552 } | |
553 | |
554 interface_->NewStream(stream_id, 0, filename); | |
555 ASSERT_TRUE(HasStream(stream_id)); | |
556 } | |
557 | |
558 TEST_P(SpdySMServerTest, NewStreamError) { | |
559 uint32 stream_id = 82; | |
560 SpdyHeaderBlock actual_header_block; | |
561 const char* actual_data; | |
562 size_t actual_size; | |
563 testing::MockFunction<void(int)> checkpoint; // NOLINT | |
564 | |
565 interface_->NewStream(stream_id, 0, "nonexistingfile"); | |
566 | |
567 ASSERT_EQ(2u, connection_->output_list()->size()); | |
568 | |
569 { | |
570 InSequence s; | |
571 if (GetParam() < SPDY4) { | |
572 EXPECT_CALL(*spdy_framer_visitor_, OnSynReply(stream_id, false, _)) | |
573 .WillOnce(SaveArg<2>(&actual_header_block)); | |
574 } else { | |
575 EXPECT_CALL(*spdy_framer_visitor_, | |
576 OnHeaders(stream_id, false, 0, false, _)) | |
577 .WillOnce(SaveArg<4>(&actual_header_block)); | |
578 } | |
579 EXPECT_CALL(checkpoint, Call(0)); | |
580 EXPECT_CALL(*spdy_framer_visitor_, | |
581 OnDataFrameHeader(stream_id, _, true)); | |
582 EXPECT_CALL(*spdy_framer_visitor_, | |
583 OnStreamFrameData(stream_id, _, _, false)).Times(1) | |
584 .WillOnce(DoAll(SaveArg<1>(&actual_data), | |
585 SaveArg<2>(&actual_size))); | |
586 EXPECT_CALL(*spdy_framer_visitor_, | |
587 OnStreamFrameData(stream_id, NULL, 0, true)).Times(1); | |
588 } | |
589 | |
590 std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin(); | |
591 DataFrame* df = *i++; | |
592 spdy_framer_->ProcessInput(df->data, df->size); | |
593 checkpoint.Call(0); | |
594 df = *i++; | |
595 spdy_framer_->ProcessInput(df->data, df->size); | |
596 | |
597 ASSERT_EQ(2, spdy_framer_->frames_received()); | |
598 ASSERT_EQ(2u, actual_header_block.size()); | |
599 ASSERT_EQ("404 Not Found", actual_header_block["status"]); | |
600 ASSERT_EQ("HTTP/1.1", actual_header_block["version"]); | |
601 ASSERT_EQ("wtf?", StringPiece(actual_data, actual_size)); | |
602 } | |
603 | |
604 } // namespace | |
605 | |
606 } // namespace net | |
OLD | NEW |