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.
5 #include "net/tools/flip_server/spdy_interface.h"
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"
22 using ::base::StringPiece;
24 using ::testing::InSequence;
25 using ::testing::InvokeWithoutArgs;
26 using ::testing::Return;
27 using ::testing::SaveArg;
28 using ::testing::Values;
34 StringSaver() : data(NULL), size(0) {}
35 void Save() { string = std::string(data, size); }
42 class SpdyFramerVisitor : public BufferedSpdyFramerVisitorInterface {
44 virtual ~SpdyFramerVisitor() {}
45 MOCK_METHOD1(OnError, void(SpdyFramer::SpdyError));
46 MOCK_METHOD2(OnStreamError, void(SpdyStreamId, const std::string&));
47 MOCK_METHOD7(OnSynStream,
54 const SpdyHeaderBlock&));
55 MOCK_METHOD3(OnSynStream, void(SpdyStreamId, bool, const SpdyHeaderBlock&));
56 MOCK_METHOD3(OnSynReply, void(SpdyStreamId, bool, const SpdyHeaderBlock&));
57 MOCK_METHOD3(OnHeaders, void(SpdyStreamId, bool, const SpdyHeaderBlock&));
58 MOCK_METHOD3(OnDataFrameHeader, void(SpdyStreamId, size_t, bool));
59 MOCK_METHOD4(OnStreamFrameData, void(SpdyStreamId,
63 MOCK_METHOD1(OnSettings, void(bool clear_persisted));
64 MOCK_METHOD3(OnSetting, void(SpdySettingsIds, uint8, uint32));
65 MOCK_METHOD1(OnPing, void(uint32 unique_id));
66 MOCK_METHOD2(OnRstStream, void(SpdyStreamId, SpdyRstStreamStatus));
67 MOCK_METHOD2(OnGoAway, void(SpdyStreamId, SpdyGoAwayStatus));
68 MOCK_METHOD2(OnWindowUpdate, void(SpdyStreamId, uint32));
69 MOCK_METHOD2(OnPushPromise, void(SpdyStreamId, SpdyStreamId));
72 class FakeSMConnection : public SMConnection {
74 FakeSMConnection(EpollServer* epoll_server,
76 MemoryCache* memory_cache,
77 FlipAcceptor* acceptor,
78 std::string log_prefix)
79 : SMConnection(epoll_server,
85 MOCK_METHOD0(Cleanup, void());
86 MOCK_METHOD8(InitSMConnection,
87 void(SMConnectionPoolInterface*,
97 // This class is almost SpdySM, except one function.
98 // This class is the test target of tests in this file.
99 class TestSpdySM : public SpdySM {
101 virtual ~TestSpdySM() {}
102 TestSpdySM(SMConnection* connection,
103 SMInterface* sm_http_interface,
104 EpollServer* epoll_server,
105 MemoryCache* memory_cache,
106 FlipAcceptor* acceptor,
107 SpdyMajorVersion version)
115 MOCK_METHOD2(FindOrMakeNewSMConnectionInterface,
116 SMInterface*(const std::string&, const std::string&));
119 class SpdySMTestBase : public ::testing::TestWithParam<SpdyMajorVersion> {
121 explicit SpdySMTestBase(FlipHandlerType type) {
122 SSLState* ssl_state = NULL;
123 mock_another_interface_.reset(new MockSMInterface);
124 memory_cache_.reset(new MemoryCache);
125 acceptor_.reset(new FlipAcceptor(type,
141 epoll_server_.reset(new EpollServer);
142 connection_.reset(new FakeSMConnection(epoll_server_.get(),
148 interface_.reset(new TestSpdySM(connection_.get(),
149 mock_another_interface_.get(),
155 spdy_framer_.reset(new BufferedSpdyFramer(GetParam(), true));
156 spdy_framer_visitor_.reset(new SpdyFramerVisitor);
157 spdy_framer_->set_visitor(spdy_framer_visitor_.get());
160 virtual ~SpdySMTestBase() {
161 if (acceptor_->listen_fd_ >= 0) {
162 epoll_server_->UnregisterFD(acceptor_->listen_fd_);
163 close(acceptor_->listen_fd_);
164 acceptor_->listen_fd_ = -1;
166 OutputList& output_list = *connection_->output_list();
167 for (OutputList::const_iterator i = output_list.begin();
168 i != output_list.end();
175 bool HasStream(uint32 stream_id) {
176 return interface_->output_ordering().ExistsInPriorityMaps(stream_id);
180 scoped_ptr<MockSMInterface> mock_another_interface_;
181 scoped_ptr<MemoryCache> memory_cache_;
182 scoped_ptr<FlipAcceptor> acceptor_;
183 scoped_ptr<EpollServer> epoll_server_;
184 scoped_ptr<FakeSMConnection> connection_;
185 scoped_ptr<TestSpdySM> interface_;
186 scoped_ptr<BufferedSpdyFramer> spdy_framer_;
187 scoped_ptr<SpdyFramerVisitor> spdy_framer_visitor_;
190 class SpdySMProxyTest : public SpdySMTestBase {
192 SpdySMProxyTest() : SpdySMTestBase(FLIP_HANDLER_PROXY) {}
193 virtual ~SpdySMProxyTest() {}
196 class SpdySMServerTest : public SpdySMTestBase {
198 SpdySMServerTest() : SpdySMTestBase(FLIP_HANDLER_SPDY_SERVER) {}
199 virtual ~SpdySMServerTest() {}
202 INSTANTIATE_TEST_CASE_P(SpdySMProxyTest,
204 Values(SPDY2, SPDY3, SPDY4));
205 INSTANTIATE_TEST_CASE_P(SpdySMServerTest, SpdySMServerTest, Values(SPDY2));
207 TEST_P(SpdySMProxyTest, InitSMConnection) {
210 EXPECT_CALL(*connection_, InitSMConnection(_, _, _, _, _, _, _, _));
212 interface_->InitSMConnection(
213 NULL, NULL, epoll_server_.get(), -1, "", "", "", false);
216 TEST_P(SpdySMProxyTest, OnSynStream_SPDY2) {
217 if (GetParam() != SPDY2) {
218 // This test case is for SPDY2.
221 BufferedSpdyFramerVisitorInterface* visitor = interface_.get();
222 scoped_ptr<MockSMInterface> mock_interface(new MockSMInterface);
223 uint32 stream_id = 92;
224 uint32 associated_id = 43;
225 std::string expected = "GET /path HTTP/1.0\r\n"
226 "Host: 127.0.0.1\r\n"
227 "hoge: fuga\r\n\r\n";
228 SpdyHeaderBlock block;
229 block["method"] = "GET";
230 block["url"] = "/path";
231 block["scheme"] = "http";
232 block["version"] = "HTTP/1.0";
233 block["hoge"] = "fuga";
237 EXPECT_CALL(*interface_, FindOrMakeNewSMConnectionInterface(_, _))
238 .WillOnce(Return(mock_interface.get()));
239 EXPECT_CALL(*mock_interface, SetStreamID(stream_id));
240 EXPECT_CALL(*mock_interface, ProcessWriteInput(_, _))
241 .WillOnce(DoAll(SaveArg<0>(&saver.data),
242 SaveArg<1>(&saver.size),
243 InvokeWithoutArgs(&saver, &StringSaver::Save),
246 visitor->OnSynStream(stream_id, associated_id, 0, 0, false, false, block);
247 ASSERT_EQ(expected, saver.string);
250 TEST_P(SpdySMProxyTest, OnSynStream) {
251 if (GetParam() == SPDY2) {
252 // This test case is not for SPDY2.
255 BufferedSpdyFramerVisitorInterface* visitor = interface_.get();
256 scoped_ptr<MockSMInterface> mock_interface(new MockSMInterface);
257 uint32 stream_id = 92;
258 uint32 associated_id = 43;
259 std::string expected = "GET /path HTTP/1.1\r\n"
260 "Host: 127.0.0.1\r\n"
262 SpdyHeaderBlock block;
263 block[":method"] = "GET";
264 block[":host"] = "www.example.com";
265 block[":path"] = "/path";
266 block[":scheme"] = "http";
267 block["foo"] = "bar";
271 EXPECT_CALL(*interface_,
272 FindOrMakeNewSMConnectionInterface(_, _))
273 .WillOnce(Return(mock_interface.get()));
274 EXPECT_CALL(*mock_interface, SetStreamID(stream_id));
275 EXPECT_CALL(*mock_interface, ProcessWriteInput(_, _))
276 .WillOnce(DoAll(SaveArg<0>(&saver.data),
277 SaveArg<1>(&saver.size),
278 InvokeWithoutArgs(&saver, &StringSaver::Save),
281 visitor->OnSynStream(stream_id, associated_id, 0, 0, false, false, block);
282 ASSERT_EQ(expected, saver.string);
285 TEST_P(SpdySMProxyTest, OnStreamFrameData_SPDY2) {
286 if (GetParam() != SPDY2) {
287 // This test case is for SPDY2.
290 BufferedSpdyFramerVisitorInterface* visitor = interface_.get();
291 scoped_ptr<MockSMInterface> mock_interface(new MockSMInterface);
292 uint32 stream_id = 92;
293 uint32 associated_id = 43;
294 SpdyHeaderBlock block;
295 testing::MockFunction<void(int)> checkpoint; // NOLINT
297 scoped_ptr<SpdyFrame> frame(spdy_framer_->CreatePingFrame(12));
298 block["method"] = "GET";
299 block["url"] = "http://www.example.com/path";
300 block["scheme"] = "http";
301 block["version"] = "HTTP/1.0";
304 EXPECT_CALL(*interface_, FindOrMakeNewSMConnectionInterface(_, _))
305 .WillOnce(Return(mock_interface.get()));
306 EXPECT_CALL(*mock_interface, SetStreamID(stream_id));
307 EXPECT_CALL(*mock_interface, ProcessWriteInput(_, _)).Times(1);
308 EXPECT_CALL(checkpoint, Call(0));
309 EXPECT_CALL(*mock_interface,
310 ProcessWriteInput(frame->data(), frame->size())).Times(1);
313 visitor->OnSynStream(stream_id, associated_id, 0, 0, false, false, block);
315 visitor->OnStreamFrameData(stream_id, frame->data(), frame->size(), true);
318 TEST_P(SpdySMProxyTest, OnStreamFrameData) {
319 if (GetParam() == SPDY2) {
320 // This test case is not for SPDY2.
323 BufferedSpdyFramerVisitorInterface* visitor = interface_.get();
324 scoped_ptr<MockSMInterface> mock_interface(new MockSMInterface);
325 uint32 stream_id = 92;
326 uint32 associated_id = 43;
327 SpdyHeaderBlock block;
328 testing::MockFunction<void(int)> checkpoint; // NOLINT
330 scoped_ptr<SpdyFrame> frame(spdy_framer_->CreatePingFrame(12));
331 block[":method"] = "GET";
332 block[":host"] = "www.example.com";
333 block[":path"] = "/path";
334 block[":scheme"] = "http";
335 block["foo"] = "bar";
338 EXPECT_CALL(*interface_,
339 FindOrMakeNewSMConnectionInterface(_, _))
340 .WillOnce(Return(mock_interface.get()));
341 EXPECT_CALL(*mock_interface, SetStreamID(stream_id));
342 EXPECT_CALL(*mock_interface, ProcessWriteInput(_, _)).Times(1);
343 EXPECT_CALL(checkpoint, Call(0));
344 EXPECT_CALL(*mock_interface,
345 ProcessWriteInput(frame->data(), frame->size())).Times(1);
348 visitor->OnSynStream(stream_id, associated_id, 0, 0, false, false, block);
350 visitor->OnStreamFrameData(stream_id, frame->data(), frame->size(), true);
353 TEST_P(SpdySMProxyTest, OnRstStream) {
354 BufferedSpdyFramerVisitorInterface* visitor = interface_.get();
355 uint32 stream_id = 82;
357 mci.stream_id = stream_id;
360 BalsaHeaders headers;
361 std::string filename = "foobar";
362 memory_cache_->InsertFile(&headers, filename, "");
363 mci.file_data = memory_cache_->GetFileData(filename);
366 interface_->AddToOutputOrder(mci);
367 ASSERT_TRUE(HasStream(stream_id));
368 visitor->OnRstStream(stream_id, RST_STREAM_INVALID);
369 ASSERT_FALSE(HasStream(stream_id));
372 TEST_P(SpdySMProxyTest, ProcessReadInput) {
373 ASSERT_EQ(SpdyFramer::SPDY_RESET, interface_->spdy_framer()->state());
374 interface_->ProcessReadInput("", 1);
375 ASSERT_EQ(SpdyFramer::SPDY_READING_COMMON_HEADER,
376 interface_->spdy_framer()->state());
379 TEST_P(SpdySMProxyTest, ResetForNewConnection) {
380 uint32 stream_id = 13;
382 mci.stream_id = stream_id;
384 const char input[] = {'\0', '\0', '\0'};
387 BalsaHeaders headers;
388 std::string filename = "foobar";
389 memory_cache_->InsertFile(&headers, filename, "");
390 mci.file_data = memory_cache_->GetFileData(filename);
393 interface_->AddToOutputOrder(mci);
394 ASSERT_TRUE(HasStream(stream_id));
395 interface_->ProcessReadInput(input, sizeof(input));
396 ASSERT_NE(SpdyFramer::SPDY_RESET, interface_->spdy_framer()->state());
398 interface_->ResetForNewConnection();
399 ASSERT_FALSE(HasStream(stream_id));
400 ASSERT_EQ(SpdyFramer::SPDY_RESET, interface_->spdy_framer()->state());
403 TEST_P(SpdySMProxyTest, PostAcceptHook) {
404 interface_->PostAcceptHook();
406 ASSERT_EQ(1u, connection_->output_list()->size());
407 std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin();
408 DataFrame* df = *i++;
412 EXPECT_CALL(*spdy_framer_visitor_, OnSettings(false));
413 EXPECT_CALL(*spdy_framer_visitor_,
414 OnSetting(SETTINGS_MAX_CONCURRENT_STREAMS, 0u, 100u));
416 spdy_framer_->ProcessInput(df->data, df->size);
419 TEST_P(SpdySMProxyTest, NewStream) {
420 // TODO(yhirano): SpdySM::NewStream leads to crash when
421 // acceptor_->flip_handler_type_ != FLIP_HANDLER_SPDY_SERVER.
422 // It should be fixed though I don't know the solution now.
425 TEST_P(SpdySMProxyTest, AddToOutputOrder) {
426 uint32 stream_id = 13;
428 mci.stream_id = stream_id;
431 BalsaHeaders headers;
432 std::string filename = "foobar";
433 memory_cache_->InsertFile(&headers, filename, "");
434 mci.file_data = memory_cache_->GetFileData(filename);
437 interface_->AddToOutputOrder(mci);
438 ASSERT_TRUE(HasStream(stream_id));
441 TEST_P(SpdySMProxyTest, SendErrorNotFound_SPDY2) {
442 if (GetParam() != SPDY2) {
443 // This test is for SPDY2.
446 uint32 stream_id = 82;
447 SpdyHeaderBlock actual_header_block;
448 const char* actual_data;
450 testing::MockFunction<void(int)> checkpoint; // NOLINT
452 interface_->SendErrorNotFound(stream_id);
454 ASSERT_EQ(2u, connection_->output_list()->size());
458 EXPECT_CALL(*spdy_framer_visitor_, OnSynReply(stream_id, false, _))
459 .WillOnce(SaveArg<2>(&actual_header_block));
460 EXPECT_CALL(checkpoint, Call(0));
461 EXPECT_CALL(*spdy_framer_visitor_,
462 OnDataFrameHeader(stream_id, _, true));
463 EXPECT_CALL(*spdy_framer_visitor_,
464 OnStreamFrameData(stream_id, _, _, false)).Times(1)
465 .WillOnce(DoAll(SaveArg<1>(&actual_data),
466 SaveArg<2>(&actual_size)));
467 EXPECT_CALL(*spdy_framer_visitor_,
468 OnStreamFrameData(stream_id, NULL, 0, true)).Times(1);
471 std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin();
472 DataFrame* df = *i++;
473 spdy_framer_->ProcessInput(df->data, df->size);
476 spdy_framer_->ProcessInput(df->data, df->size);
478 ASSERT_EQ(2, spdy_framer_->frames_received());
479 ASSERT_EQ(2u, actual_header_block.size());
480 ASSERT_EQ("404 Not Found", actual_header_block["status"]);
481 ASSERT_EQ("HTTP/1.1", actual_header_block["version"]);
482 ASSERT_EQ("wtf?", StringPiece(actual_data, actual_size));
485 TEST_P(SpdySMProxyTest, SendErrorNotFound) {
486 if (GetParam() == SPDY2) {
487 // This test is not for SPDY2.
490 uint32 stream_id = 82;
491 SpdyHeaderBlock actual_header_block;
492 const char* actual_data;
494 testing::MockFunction<void(int)> checkpoint; // NOLINT
496 interface_->SendErrorNotFound(stream_id);
498 ASSERT_EQ(2u, connection_->output_list()->size());
502 EXPECT_CALL(*spdy_framer_visitor_,
503 OnSynReply(stream_id, false, _))
504 .WillOnce(SaveArg<2>(&actual_header_block));
505 EXPECT_CALL(checkpoint, Call(0));
506 EXPECT_CALL(*spdy_framer_visitor_,
507 OnDataFrameHeader(stream_id, _, true));
508 EXPECT_CALL(*spdy_framer_visitor_,
509 OnStreamFrameData(stream_id, _, _, false)).Times(1)
510 .WillOnce(DoAll(SaveArg<1>(&actual_data),
511 SaveArg<2>(&actual_size)));
512 EXPECT_CALL(*spdy_framer_visitor_,
513 OnStreamFrameData(stream_id, NULL, 0, true)).Times(1);
516 std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin();
517 DataFrame* df = *i++;
518 spdy_framer_->ProcessInput(df->data, df->size);
521 spdy_framer_->ProcessInput(df->data, df->size);
523 ASSERT_EQ(2, spdy_framer_->frames_received());
524 ASSERT_EQ(2u, actual_header_block.size());
525 ASSERT_EQ("404 Not Found", actual_header_block[":status"]);
526 ASSERT_EQ("HTTP/1.1", actual_header_block[":version"]);
527 ASSERT_EQ("wtf?", StringPiece(actual_data, actual_size));
530 TEST_P(SpdySMProxyTest, SendSynStream_SPDY2) {
531 if (GetParam() != SPDY2) {
532 // This test is for SPDY2.
535 uint32 stream_id = 82;
536 BalsaHeaders headers;
537 SpdyHeaderBlock actual_header_block;
538 headers.AppendHeader("key1", "value1");
539 headers.SetRequestFirstlineFromStringPieces("GET", "/path", "HTTP/1.0");
541 interface_->SendSynStream(stream_id, headers);
543 ASSERT_EQ(1u, connection_->output_list()->size());
544 std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin();
545 DataFrame* df = *i++;
549 EXPECT_CALL(*spdy_framer_visitor_,
550 OnSynStream(stream_id, 0, _, _, false, false, _))
551 .WillOnce(SaveArg<6>(&actual_header_block));
554 spdy_framer_->ProcessInput(df->data, df->size);
555 ASSERT_EQ(1, spdy_framer_->frames_received());
556 ASSERT_EQ(4u, actual_header_block.size());
557 ASSERT_EQ("GET", actual_header_block["method"]);
558 ASSERT_EQ("HTTP/1.0", actual_header_block["version"]);
559 ASSERT_EQ("/path", actual_header_block["url"]);
560 ASSERT_EQ("value1", actual_header_block["key1"]);
563 TEST_P(SpdySMProxyTest, SendSynStream) {
564 if (GetParam() == SPDY2) {
565 // This test is not for SPDY2.
568 uint32 stream_id = 82;
569 BalsaHeaders headers;
570 SpdyHeaderBlock actual_header_block;
571 headers.AppendHeader("key1", "value1");
572 headers.AppendHeader("Host", "www.example.com");
573 headers.SetRequestFirstlineFromStringPieces("GET", "/path", "HTTP/1.1");
575 interface_->SendSynStream(stream_id, headers);
577 ASSERT_EQ(1u, connection_->output_list()->size());
578 std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin();
579 DataFrame* df = *i++;
583 EXPECT_CALL(*spdy_framer_visitor_,
584 OnSynStream(stream_id, 0, _, _, false, false, _))
585 .WillOnce(SaveArg<6>(&actual_header_block));
588 spdy_framer_->ProcessInput(df->data, df->size);
589 ASSERT_EQ(1, spdy_framer_->frames_received());
590 ASSERT_EQ(5u, actual_header_block.size());
591 ASSERT_EQ("GET", actual_header_block[":method"]);
592 ASSERT_EQ("HTTP/1.1", actual_header_block[":version"]);
593 ASSERT_EQ("/path", actual_header_block[":path"]);
594 ASSERT_EQ("www.example.com", actual_header_block[":host"]);
595 ASSERT_EQ("value1", actual_header_block["key1"]);
598 TEST_P(SpdySMProxyTest, SendSynReply_SPDY2) {
599 if (GetParam() != SPDY2) {
600 // This test is for SPDY2.
603 uint32 stream_id = 82;
604 BalsaHeaders headers;
605 SpdyHeaderBlock actual_header_block;
606 headers.AppendHeader("key1", "value1");
607 headers.SetResponseFirstlineFromStringPieces("HTTP/1.1", "200", "OK");
609 interface_->SendSynReply(stream_id, headers);
611 ASSERT_EQ(1u, connection_->output_list()->size());
612 std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin();
613 DataFrame* df = *i++;
617 EXPECT_CALL(*spdy_framer_visitor_, OnSynReply(stream_id, false, _))
618 .WillOnce(SaveArg<2>(&actual_header_block));
621 spdy_framer_->ProcessInput(df->data, df->size);
622 ASSERT_EQ(1, spdy_framer_->frames_received());
623 ASSERT_EQ(3u, actual_header_block.size());
624 ASSERT_EQ("200 OK", actual_header_block["status"]);
625 ASSERT_EQ("HTTP/1.1", actual_header_block["version"]);
626 ASSERT_EQ("value1", actual_header_block["key1"]);
629 TEST_P(SpdySMProxyTest, SendSynReply) {
630 if (GetParam() == SPDY2) {
631 // This test is not for SPDY2.
634 uint32 stream_id = 82;
635 BalsaHeaders headers;
636 SpdyHeaderBlock actual_header_block;
637 headers.AppendHeader("key1", "value1");
638 headers.SetResponseFirstlineFromStringPieces("HTTP/1.1", "200", "OK");
640 interface_->SendSynReply(stream_id, headers);
642 ASSERT_EQ(1u, connection_->output_list()->size());
643 std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin();
644 DataFrame* df = *i++;
648 EXPECT_CALL(*spdy_framer_visitor_, OnSynReply(stream_id, false, _))
649 .WillOnce(SaveArg<2>(&actual_header_block));
652 spdy_framer_->ProcessInput(df->data, df->size);
653 ASSERT_EQ(1, spdy_framer_->frames_received());
654 ASSERT_EQ(3u, actual_header_block.size());
655 ASSERT_EQ("200 OK", actual_header_block[":status"]);
656 ASSERT_EQ("HTTP/1.1", actual_header_block[":version"]);
657 ASSERT_EQ("value1", actual_header_block["key1"]);
660 TEST_P(SpdySMProxyTest, SendDataFrame) {
661 uint32 stream_id = 133;
662 SpdyDataFlags flags = DATA_FLAG_NONE;
663 const char* actual_data;
666 interface_->SendDataFrame(stream_id, "hello", 5, flags, true);
668 ASSERT_EQ(1u, connection_->output_list()->size());
669 std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin();
670 DataFrame* df = *i++;
674 EXPECT_CALL(*spdy_framer_visitor_,
675 OnDataFrameHeader(stream_id, _, false));
676 EXPECT_CALL(*spdy_framer_visitor_,
677 OnStreamFrameData(stream_id, _, _, false))
678 .WillOnce(DoAll(SaveArg<1>(&actual_data), SaveArg<2>(&actual_size)));
681 spdy_framer_->ProcessInput(df->data, df->size);
682 ASSERT_EQ(1, spdy_framer_->frames_received());
683 ASSERT_EQ("hello", StringPiece(actual_data, actual_size));
686 TEST_P(SpdySMProxyTest, SendLongDataFrame) {
687 uint32 stream_id = 133;
688 SpdyDataFlags flags = DATA_FLAG_NONE;
689 const char* actual_data;
692 std::string data = std::string(kSpdySegmentSize, 'a') +
693 std::string(kSpdySegmentSize, 'b') + "c";
694 interface_->SendDataFrame(stream_id, data.data(), data.size(), flags, true);
698 for (int i = 0; i < 3; ++i) {
699 EXPECT_CALL(*spdy_framer_visitor_,
700 OnDataFrameHeader(stream_id, _, false));
701 EXPECT_CALL(*spdy_framer_visitor_,
702 OnStreamFrameData(stream_id, _, _, false))
703 .WillOnce(DoAll(SaveArg<1>(&actual_data),
704 SaveArg<2>(&actual_size)));
708 ASSERT_EQ(3u, connection_->output_list()->size());
709 std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin();
710 DataFrame* df = *i++;
711 spdy_framer_->ProcessInput(df->data, df->size);
712 ASSERT_EQ(std::string(kSpdySegmentSize, 'a'),
713 StringPiece(actual_data, actual_size));
716 spdy_framer_->ProcessInput(df->data, df->size);
717 ASSERT_EQ(std::string(kSpdySegmentSize, 'b'),
718 StringPiece(actual_data, actual_size));
721 spdy_framer_->ProcessInput(df->data, df->size);
722 ASSERT_EQ("c", StringPiece(actual_data, actual_size));
725 TEST_P(SpdySMProxyTest, SendEOF_SPDY2) {
726 // This test is for SPDY2.
727 if (GetParam() != SPDY2) {
731 uint32 stream_id = 82;
733 char empty_data_frame[] = {'\0', '\0', '\0', '\x52', '\x1', '\0', '\0', '\0'};
735 mci.stream_id = stream_id;
738 BalsaHeaders headers;
739 std::string filename = "foobar";
740 memory_cache_->InsertFile(&headers, filename, "");
741 mci.file_data = memory_cache_->GetFileData(filename);
744 interface_->AddToOutputOrder(mci);
745 ASSERT_TRUE(HasStream(stream_id));
746 interface_->SendEOF(stream_id);
747 ASSERT_FALSE(HasStream(stream_id));
749 ASSERT_EQ(1u, connection_->output_list()->size());
750 std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin();
751 DataFrame* df = *i++;
752 ASSERT_EQ(StringPiece(empty_data_frame, sizeof(empty_data_frame)),
753 StringPiece(df->data, df->size));
756 TEST_P(SpdySMProxyTest, SendEmptyDataFrame_SPDY2) {
757 // This test is for SPDY2.
758 if (GetParam() != SPDY2) {
762 uint32 stream_id = 133;
763 SpdyDataFlags flags = DATA_FLAG_NONE;
765 char expected[] = {'\0', '\0', '\0', '\x85', '\0', '\0', '\0', '\0'};
767 interface_->SendDataFrame(stream_id, "hello", 0, flags, true);
769 ASSERT_EQ(1u, connection_->output_list()->size());
770 std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin();
771 DataFrame* df = *i++;
773 ASSERT_EQ(StringPiece(expected, sizeof(expected)),
774 StringPiece(df->data, df->size));
777 TEST_P(SpdySMServerTest, OnSynStream) {
778 BufferedSpdyFramerVisitorInterface* visitor = interface_.get();
779 uint32 stream_id = 82;
780 SpdyHeaderBlock spdy_headers;
781 spdy_headers["url"] = "http://www.example.com/path";
782 spdy_headers["method"] = "GET";
783 spdy_headers["scheme"] = "http";
784 spdy_headers["version"] = "HTTP/1.1";
787 BalsaHeaders headers;
788 memory_cache_->InsertFile(&headers, "GET_/path", "");
790 visitor->OnSynStream(stream_id, 0, 0, 0, true, true, spdy_headers);
791 ASSERT_TRUE(HasStream(stream_id));
794 TEST_P(SpdySMServerTest, NewStream) {
795 uint32 stream_id = 13;
796 std::string filename = "foobar";
799 BalsaHeaders headers;
800 memory_cache_->InsertFile(&headers, filename, "");
803 interface_->NewStream(stream_id, 0, filename);
804 ASSERT_TRUE(HasStream(stream_id));
807 TEST_P(SpdySMServerTest, NewStreamError) {
808 uint32 stream_id = 82;
809 SpdyHeaderBlock actual_header_block;
810 const char* actual_data;
812 testing::MockFunction<void(int)> checkpoint; // NOLINT
814 interface_->NewStream(stream_id, 0, "nonexistingfile");
816 ASSERT_EQ(2u, connection_->output_list()->size());
820 EXPECT_CALL(*spdy_framer_visitor_, OnSynReply(stream_id, false, _))
821 .WillOnce(SaveArg<2>(&actual_header_block));
822 EXPECT_CALL(checkpoint, Call(0));
823 EXPECT_CALL(*spdy_framer_visitor_,
824 OnDataFrameHeader(stream_id, _, true));
825 EXPECT_CALL(*spdy_framer_visitor_,
826 OnStreamFrameData(stream_id, _, _, false)).Times(1)
827 .WillOnce(DoAll(SaveArg<1>(&actual_data),
828 SaveArg<2>(&actual_size)));
829 EXPECT_CALL(*spdy_framer_visitor_,
830 OnStreamFrameData(stream_id, NULL, 0, true)).Times(1);
833 std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin();
834 DataFrame* df = *i++;
835 spdy_framer_->ProcessInput(df->data, df->size);
838 spdy_framer_->ProcessInput(df->data, df->size);
840 ASSERT_EQ(2, spdy_framer_->frames_received());
841 ASSERT_EQ(2u, actual_header_block.size());
842 ASSERT_EQ("404 Not Found", actual_header_block["status"]);
843 ASSERT_EQ("HTTP/1.1", actual_header_block["version"]);
844 ASSERT_EQ("wtf?", StringPiece(actual_data, actual_size));