Home | History | Annotate | Download | only in flip_server
      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_METHOD3(OnHeaders, void(SpdyStreamId, bool, const SpdyHeaderBlock&));
     56   MOCK_METHOD3(OnDataFrameHeader, void(SpdyStreamId, size_t, bool));
     57   MOCK_METHOD4(OnStreamFrameData, void(SpdyStreamId,
     58                                        const char*,
     59                                        size_t,
     60                                        bool));
     61   MOCK_METHOD1(OnSettings, void(bool clear_persisted));
     62   MOCK_METHOD3(OnSetting, void(SpdySettingsIds, uint8, uint32));
     63   MOCK_METHOD2(OnPing, void(SpdyPingId unique_id, bool is_ack));
     64   MOCK_METHOD2(OnRstStream, void(SpdyStreamId, SpdyRstStreamStatus));
     65   MOCK_METHOD2(OnGoAway, void(SpdyStreamId, SpdyGoAwayStatus));
     66   MOCK_METHOD2(OnWindowUpdate, void(SpdyStreamId, uint32));
     67   MOCK_METHOD3(OnPushPromise,
     68                void(SpdyStreamId, SpdyStreamId, const SpdyHeaderBlock&));
     69 };
     70 
     71 class FakeSMConnection : public SMConnection {
     72  public:
     73   FakeSMConnection(EpollServer* epoll_server,
     74                    SSLState* ssl_state,
     75                    MemoryCache* memory_cache,
     76                    FlipAcceptor* acceptor,
     77                    std::string log_prefix)
     78       : SMConnection(epoll_server,
     79                      ssl_state,
     80                      memory_cache,
     81                      acceptor,
     82                      log_prefix) {}
     83 
     84   MOCK_METHOD0(Cleanup, void());
     85   MOCK_METHOD8(InitSMConnection,
     86                void(SMConnectionPoolInterface*,
     87                     SMInterface*,
     88                     EpollServer*,
     89                     int,
     90                     std::string,
     91                     std::string,
     92                     std::string,
     93                     bool));
     94 };
     95 
     96 // This class is almost SpdySM, except one function.
     97 // This class is the test target of tests in this file.
     98 class TestSpdySM : public SpdySM {
     99  public:
    100   virtual ~TestSpdySM() {}
    101   TestSpdySM(SMConnection* connection,
    102              SMInterface* sm_http_interface,
    103              EpollServer* epoll_server,
    104              MemoryCache* memory_cache,
    105              FlipAcceptor* acceptor,
    106              SpdyMajorVersion version)
    107       : SpdySM(connection,
    108                sm_http_interface,
    109                epoll_server,
    110                memory_cache,
    111                acceptor,
    112                version) {}
    113 
    114   MOCK_METHOD2(FindOrMakeNewSMConnectionInterface,
    115                SMInterface*(const std::string&, const std::string&));
    116 };
    117 
    118 class SpdySMTestBase : public ::testing::TestWithParam<SpdyMajorVersion> {
    119  public:
    120   explicit SpdySMTestBase(FlipHandlerType type) {
    121     SSLState* ssl_state = NULL;
    122     mock_another_interface_.reset(new MockSMInterface);
    123     memory_cache_.reset(new MemoryCache);
    124     acceptor_.reset(new FlipAcceptor(type,
    125                                      "127.0.0.1",
    126                                      "8941",
    127                                      "ssl_cert_filename",
    128                                      "ssl_key_filename",
    129                                      "127.0.0.1",
    130                                      "8942",
    131                                      "127.0.0.1",
    132                                      "8943",
    133                                      1,
    134                                      0,
    135                                      true,
    136                                      1,
    137                                      false,
    138                                      true,
    139                                      NULL));
    140     epoll_server_.reset(new EpollServer);
    141     connection_.reset(new FakeSMConnection(epoll_server_.get(),
    142                                            ssl_state,
    143                                            memory_cache_.get(),
    144                                            acceptor_.get(),
    145                                            "log_prefix"));
    146 
    147     interface_.reset(new TestSpdySM(connection_.get(),
    148                                     mock_another_interface_.get(),
    149                                     epoll_server_.get(),
    150                                     memory_cache_.get(),
    151                                     acceptor_.get(),
    152                                     GetParam()));
    153 
    154     spdy_framer_.reset(new BufferedSpdyFramer(GetParam(), true));
    155     spdy_framer_visitor_.reset(new SpdyFramerVisitor);
    156     spdy_framer_->set_visitor(spdy_framer_visitor_.get());
    157   }
    158 
    159   virtual ~SpdySMTestBase() {
    160     if (acceptor_->listen_fd_ >= 0) {
    161       epoll_server_->UnregisterFD(acceptor_->listen_fd_);
    162       close(acceptor_->listen_fd_);
    163       acceptor_->listen_fd_ = -1;
    164     }
    165     OutputList& output_list = *connection_->output_list();
    166     for (OutputList::const_iterator i = output_list.begin();
    167          i != output_list.end();
    168          ++i) {
    169       delete *i;
    170     }
    171     output_list.clear();
    172   }
    173 
    174   bool HasStream(uint32 stream_id) {
    175     return interface_->output_ordering().ExistsInPriorityMaps(stream_id);
    176   }
    177 
    178  protected:
    179   scoped_ptr<MockSMInterface> mock_another_interface_;
    180   scoped_ptr<MemoryCache> memory_cache_;
    181   scoped_ptr<FlipAcceptor> acceptor_;
    182   scoped_ptr<EpollServer> epoll_server_;
    183   scoped_ptr<FakeSMConnection> connection_;
    184   scoped_ptr<TestSpdySM> interface_;
    185   scoped_ptr<BufferedSpdyFramer> spdy_framer_;
    186   scoped_ptr<SpdyFramerVisitor> spdy_framer_visitor_;
    187 };
    188 
    189 class SpdySMProxyTest : public SpdySMTestBase {
    190  public:
    191   SpdySMProxyTest() : SpdySMTestBase(FLIP_HANDLER_PROXY) {}
    192   virtual ~SpdySMProxyTest() {}
    193 };
    194 
    195 class SpdySMServerTest : public SpdySMTestBase {
    196  public:
    197   SpdySMServerTest() : SpdySMTestBase(FLIP_HANDLER_SPDY_SERVER) {}
    198   virtual ~SpdySMServerTest() {}
    199 };
    200 
    201 INSTANTIATE_TEST_CASE_P(SpdySMProxyTest,
    202                         SpdySMProxyTest,
    203                         Values(SPDY2, SPDY3, SPDY4));
    204 INSTANTIATE_TEST_CASE_P(SpdySMServerTest, SpdySMServerTest, Values(SPDY2));
    205 
    206 TEST_P(SpdySMProxyTest, InitSMConnection) {
    207   {
    208     InSequence s;
    209     EXPECT_CALL(*connection_, InitSMConnection(_, _, _, _, _, _, _, _));
    210   }
    211   interface_->InitSMConnection(
    212       NULL, NULL, epoll_server_.get(), -1, "", "", "", false);
    213 }
    214 
    215 TEST_P(SpdySMProxyTest, OnSynStream_SPDY2) {
    216   if (GetParam() != SPDY2) {
    217     // This test case is for SPDY2.
    218     return;
    219   }
    220   BufferedSpdyFramerVisitorInterface* visitor = interface_.get();
    221   scoped_ptr<MockSMInterface> mock_interface(new MockSMInterface);
    222   uint32 stream_id = 92;
    223   uint32 associated_id = 43;
    224   std::string expected = "GET /path HTTP/1.0\r\n"
    225       "Host: 127.0.0.1\r\n"
    226       "hoge: fuga\r\n\r\n";
    227   SpdyHeaderBlock block;
    228   block["method"] = "GET";
    229   block["url"] = "/path";
    230   block["scheme"] = "http";
    231   block["version"] = "HTTP/1.0";
    232   block["hoge"] = "fuga";
    233   StringSaver saver;
    234   {
    235     InSequence s;
    236     EXPECT_CALL(*interface_, FindOrMakeNewSMConnectionInterface(_, _))
    237         .WillOnce(Return(mock_interface.get()));
    238     EXPECT_CALL(*mock_interface, SetStreamID(stream_id));
    239     EXPECT_CALL(*mock_interface, ProcessWriteInput(_, _))
    240         .WillOnce(DoAll(SaveArg<0>(&saver.data),
    241                         SaveArg<1>(&saver.size),
    242                         InvokeWithoutArgs(&saver, &StringSaver::Save),
    243                         Return(0)));
    244   }
    245   visitor->OnSynStream(stream_id, associated_id, 0, false, false, block);
    246   ASSERT_EQ(expected, saver.string);
    247 }
    248 
    249 TEST_P(SpdySMProxyTest, OnSynStream) {
    250   if (GetParam() == SPDY2) {
    251     // This test case is not for SPDY2.
    252     return;
    253   }
    254   BufferedSpdyFramerVisitorInterface* visitor = interface_.get();
    255   scoped_ptr<MockSMInterface> mock_interface(new MockSMInterface);
    256   uint32 stream_id = 92;
    257   uint32 associated_id = 43;
    258   std::string expected = "GET /path HTTP/1.1\r\n"
    259       "Host: 127.0.0.1\r\n"
    260       "foo: bar\r\n\r\n";
    261   SpdyHeaderBlock block;
    262   block[":method"] = "GET";
    263   block[":host"] = "www.example.com";
    264   block[":path"] = "/path";
    265   block[":scheme"] = "http";
    266   block["foo"] = "bar";
    267   StringSaver saver;
    268   {
    269     InSequence s;
    270     EXPECT_CALL(*interface_,
    271                 FindOrMakeNewSMConnectionInterface(_, _))
    272         .WillOnce(Return(mock_interface.get()));
    273     EXPECT_CALL(*mock_interface, SetStreamID(stream_id));
    274     EXPECT_CALL(*mock_interface, ProcessWriteInput(_, _))
    275         .WillOnce(DoAll(SaveArg<0>(&saver.data),
    276                         SaveArg<1>(&saver.size),
    277                         InvokeWithoutArgs(&saver, &StringSaver::Save),
    278                         Return(0)));
    279   }
    280   visitor->OnSynStream(stream_id, associated_id, 0, false, false, block);
    281   ASSERT_EQ(expected, saver.string);
    282 }
    283 
    284 TEST_P(SpdySMProxyTest, OnStreamFrameData_SPDY2) {
    285   if (GetParam() != SPDY2) {
    286     // This test case is for SPDY2.
    287     return;
    288   }
    289   BufferedSpdyFramerVisitorInterface* visitor = interface_.get();
    290   scoped_ptr<MockSMInterface> mock_interface(new MockSMInterface);
    291   uint32 stream_id = 92;
    292   uint32 associated_id = 43;
    293   SpdyHeaderBlock block;
    294   testing::MockFunction<void(int)> checkpoint;  // NOLINT
    295 
    296   scoped_ptr<SpdyFrame> frame(spdy_framer_->CreatePingFrame(12, false));
    297   block["method"] = "GET";
    298   block["url"] = "http://www.example.com/path";
    299   block["scheme"] = "http";
    300   block["version"] = "HTTP/1.0";
    301   {
    302     InSequence s;
    303     EXPECT_CALL(*interface_, FindOrMakeNewSMConnectionInterface(_, _))
    304         .WillOnce(Return(mock_interface.get()));
    305     EXPECT_CALL(*mock_interface, SetStreamID(stream_id));
    306     EXPECT_CALL(*mock_interface, ProcessWriteInput(_, _)).Times(1);
    307     EXPECT_CALL(checkpoint, Call(0));
    308     EXPECT_CALL(*mock_interface,
    309                 ProcessWriteInput(frame->data(), frame->size())).Times(1);
    310   }
    311 
    312   visitor->OnSynStream(stream_id, associated_id, 0, false, false, block);
    313   checkpoint.Call(0);
    314   visitor->OnStreamFrameData(stream_id, frame->data(), frame->size(), true);
    315 }
    316 
    317 TEST_P(SpdySMProxyTest, OnStreamFrameData) {
    318   if (GetParam() == SPDY2) {
    319     // This test case is not for SPDY2.
    320     return;
    321   }
    322   BufferedSpdyFramerVisitorInterface* visitor = interface_.get();
    323   scoped_ptr<MockSMInterface> mock_interface(new MockSMInterface);
    324   uint32 stream_id = 92;
    325   uint32 associated_id = 43;
    326   SpdyHeaderBlock block;
    327   testing::MockFunction<void(int)> checkpoint;  // NOLINT
    328 
    329   scoped_ptr<SpdyFrame> frame(spdy_framer_->CreatePingFrame(12, false));
    330   block[":method"] = "GET";
    331   block[":host"] = "www.example.com";
    332   block[":path"] = "/path";
    333   block[":scheme"] = "http";
    334   block["foo"] = "bar";
    335   {
    336     InSequence s;
    337     EXPECT_CALL(*interface_,
    338                 FindOrMakeNewSMConnectionInterface(_, _))
    339         .WillOnce(Return(mock_interface.get()));
    340     EXPECT_CALL(*mock_interface, SetStreamID(stream_id));
    341     EXPECT_CALL(*mock_interface, ProcessWriteInput(_, _)).Times(1);
    342     EXPECT_CALL(checkpoint, Call(0));
    343     EXPECT_CALL(*mock_interface,
    344                 ProcessWriteInput(frame->data(), frame->size())).Times(1);
    345   }
    346 
    347   visitor->OnSynStream(stream_id, associated_id, 0, false, false, block);
    348   checkpoint.Call(0);
    349   visitor->OnStreamFrameData(stream_id, frame->data(), frame->size(), true);
    350 }
    351 
    352 TEST_P(SpdySMProxyTest, OnRstStream) {
    353   BufferedSpdyFramerVisitorInterface* visitor = interface_.get();
    354   uint32 stream_id = 82;
    355   MemCacheIter mci;
    356   mci.stream_id = stream_id;
    357 
    358   {
    359     BalsaHeaders headers;
    360     std::string filename = "foobar";
    361     memory_cache_->InsertFile(&headers, filename, "");
    362     mci.file_data = memory_cache_->GetFileData(filename);
    363   }
    364 
    365   interface_->AddToOutputOrder(mci);
    366   ASSERT_TRUE(HasStream(stream_id));
    367   visitor->OnRstStream(stream_id, RST_STREAM_INVALID);
    368   ASSERT_FALSE(HasStream(stream_id));
    369 }
    370 
    371 TEST_P(SpdySMProxyTest, ProcessReadInput) {
    372   ASSERT_EQ(SpdyFramer::SPDY_RESET, interface_->spdy_framer()->state());
    373   interface_->ProcessReadInput("", 1);
    374   ASSERT_EQ(SpdyFramer::SPDY_READING_COMMON_HEADER,
    375             interface_->spdy_framer()->state());
    376 }
    377 
    378 TEST_P(SpdySMProxyTest, ResetForNewConnection) {
    379   uint32 stream_id = 13;
    380   MemCacheIter mci;
    381   mci.stream_id = stream_id;
    382   // incomplete input
    383   const char input[] = {'\0', '\0', '\0'};
    384 
    385   {
    386     BalsaHeaders headers;
    387     std::string filename = "foobar";
    388     memory_cache_->InsertFile(&headers, filename, "");
    389     mci.file_data = memory_cache_->GetFileData(filename);
    390   }
    391 
    392   interface_->AddToOutputOrder(mci);
    393   ASSERT_TRUE(HasStream(stream_id));
    394   interface_->ProcessReadInput(input, sizeof(input));
    395   ASSERT_NE(SpdyFramer::SPDY_RESET, interface_->spdy_framer()->state());
    396 
    397   interface_->ResetForNewConnection();
    398   ASSERT_FALSE(HasStream(stream_id));
    399   ASSERT_TRUE(interface_->spdy_framer() == NULL);
    400 }
    401 
    402 TEST_P(SpdySMProxyTest, CreateFramer) {
    403   interface_->ResetForNewConnection();
    404   interface_->CreateFramer(SPDY2);
    405   ASSERT_TRUE(interface_->spdy_framer() != NULL);
    406   ASSERT_EQ(interface_->spdy_version(), SPDY2);
    407 
    408   interface_->ResetForNewConnection();
    409   interface_->CreateFramer(SPDY3);
    410   ASSERT_TRUE(interface_->spdy_framer() != NULL);
    411   ASSERT_EQ(interface_->spdy_version(), SPDY3);
    412 }
    413 
    414 TEST_P(SpdySMProxyTest, PostAcceptHook) {
    415   interface_->PostAcceptHook();
    416 
    417   ASSERT_EQ(1u, connection_->output_list()->size());
    418   std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin();
    419   DataFrame* df = *i++;
    420 
    421   {
    422     InSequence s;
    423     EXPECT_CALL(*spdy_framer_visitor_, OnSettings(false));
    424     EXPECT_CALL(*spdy_framer_visitor_,
    425                 OnSetting(SETTINGS_MAX_CONCURRENT_STREAMS, 0u, 100u));
    426   }
    427   spdy_framer_->ProcessInput(df->data, df->size);
    428 }
    429 
    430 TEST_P(SpdySMProxyTest, NewStream) {
    431   // TODO(yhirano): SpdySM::NewStream leads to crash when
    432   // acceptor_->flip_handler_type_ != FLIP_HANDLER_SPDY_SERVER.
    433   // It should be fixed though I don't know the solution now.
    434 }
    435 
    436 TEST_P(SpdySMProxyTest, AddToOutputOrder) {
    437   uint32 stream_id = 13;
    438   MemCacheIter mci;
    439   mci.stream_id = stream_id;
    440 
    441   {
    442     BalsaHeaders headers;
    443     std::string filename = "foobar";
    444     memory_cache_->InsertFile(&headers, filename, "");
    445     mci.file_data = memory_cache_->GetFileData(filename);
    446   }
    447 
    448   interface_->AddToOutputOrder(mci);
    449   ASSERT_TRUE(HasStream(stream_id));
    450 }
    451 
    452 TEST_P(SpdySMProxyTest, SendErrorNotFound_SPDY2) {
    453   if (GetParam() != SPDY2) {
    454     // This test is for SPDY2.
    455     return;
    456   }
    457   uint32 stream_id = 82;
    458   SpdyHeaderBlock actual_header_block;
    459   const char* actual_data;
    460   size_t actual_size;
    461   testing::MockFunction<void(int)> checkpoint;  // NOLINT
    462 
    463   interface_->SendErrorNotFound(stream_id);
    464 
    465   ASSERT_EQ(2u, connection_->output_list()->size());
    466 
    467   {
    468     InSequence s;
    469     if (GetParam() < SPDY4) {
    470       EXPECT_CALL(*spdy_framer_visitor_, OnSynReply(stream_id, false, _))
    471           .WillOnce(SaveArg<2>(&actual_header_block));
    472     } else {
    473       EXPECT_CALL(*spdy_framer_visitor_, OnHeaders(stream_id, false, _))
    474           .WillOnce(SaveArg<2>(&actual_header_block));
    475     }
    476     EXPECT_CALL(checkpoint, Call(0));
    477     EXPECT_CALL(*spdy_framer_visitor_,
    478                 OnDataFrameHeader(stream_id, _, true));
    479     EXPECT_CALL(*spdy_framer_visitor_,
    480                 OnStreamFrameData(stream_id, _, _, false)).Times(1)
    481         .WillOnce(DoAll(SaveArg<1>(&actual_data),
    482                         SaveArg<2>(&actual_size)));
    483     EXPECT_CALL(*spdy_framer_visitor_,
    484                 OnStreamFrameData(stream_id, NULL, 0, true)).Times(1);
    485   }
    486 
    487   std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin();
    488   DataFrame* df = *i++;
    489   spdy_framer_->ProcessInput(df->data, df->size);
    490   checkpoint.Call(0);
    491   df = *i++;
    492   spdy_framer_->ProcessInput(df->data, df->size);
    493 
    494   ASSERT_EQ(2, spdy_framer_->frames_received());
    495   ASSERT_EQ(2u, actual_header_block.size());
    496   ASSERT_EQ("404 Not Found", actual_header_block["status"]);
    497   ASSERT_EQ("HTTP/1.1", actual_header_block["version"]);
    498   ASSERT_EQ("wtf?", StringPiece(actual_data, actual_size));
    499 }
    500 
    501 TEST_P(SpdySMProxyTest, SendErrorNotFound) {
    502   if (GetParam() == SPDY2) {
    503     // This test is not for SPDY2.
    504     return;
    505   }
    506   uint32 stream_id = 82;
    507   SpdyHeaderBlock actual_header_block;
    508   const char* actual_data;
    509   size_t actual_size;
    510   testing::MockFunction<void(int)> checkpoint;  // NOLINT
    511 
    512   interface_->SendErrorNotFound(stream_id);
    513 
    514   ASSERT_EQ(2u, connection_->output_list()->size());
    515 
    516   {
    517     InSequence s;
    518     if (GetParam() < SPDY4) {
    519       EXPECT_CALL(*spdy_framer_visitor_,
    520                   OnSynReply(stream_id, false, _))
    521           .WillOnce(SaveArg<2>(&actual_header_block));
    522     } else {
    523       EXPECT_CALL(*spdy_framer_visitor_,
    524                   OnHeaders(stream_id, false, _))
    525           .WillOnce(SaveArg<2>(&actual_header_block));
    526     }
    527     EXPECT_CALL(checkpoint, Call(0));
    528     EXPECT_CALL(*spdy_framer_visitor_,
    529                 OnDataFrameHeader(stream_id, _, true));
    530     EXPECT_CALL(*spdy_framer_visitor_,
    531                 OnStreamFrameData(stream_id, _, _, false)).Times(1)
    532         .WillOnce(DoAll(SaveArg<1>(&actual_data),
    533                         SaveArg<2>(&actual_size)));
    534     EXPECT_CALL(*spdy_framer_visitor_,
    535                 OnStreamFrameData(stream_id, NULL, 0, true)).Times(1);
    536   }
    537 
    538   std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin();
    539   DataFrame* df = *i++;
    540   spdy_framer_->ProcessInput(df->data, df->size);
    541   checkpoint.Call(0);
    542   df = *i++;
    543   spdy_framer_->ProcessInput(df->data, df->size);
    544 
    545   ASSERT_EQ(2, spdy_framer_->frames_received());
    546   ASSERT_EQ(2u, actual_header_block.size());
    547   ASSERT_EQ("404 Not Found", actual_header_block[":status"]);
    548   ASSERT_EQ("HTTP/1.1", actual_header_block[":version"]);
    549   ASSERT_EQ("wtf?", StringPiece(actual_data, actual_size));
    550 }
    551 
    552 TEST_P(SpdySMProxyTest, SendSynStream_SPDY2) {
    553   if (GetParam() != SPDY2) {
    554     // This test is for SPDY2.
    555     return;
    556   }
    557   uint32 stream_id = 82;
    558   BalsaHeaders headers;
    559   SpdyHeaderBlock actual_header_block;
    560   headers.AppendHeader("key1", "value1");
    561   headers.SetRequestFirstlineFromStringPieces("GET", "/path", "HTTP/1.0");
    562 
    563   interface_->SendSynStream(stream_id, headers);
    564 
    565   ASSERT_EQ(1u, connection_->output_list()->size());
    566   std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin();
    567   DataFrame* df = *i++;
    568 
    569   {
    570     InSequence s;
    571     EXPECT_CALL(*spdy_framer_visitor_,
    572                 OnSynStream(stream_id, 0, _, false, false, _))
    573         .WillOnce(SaveArg<5>(&actual_header_block));
    574   }
    575 
    576   spdy_framer_->ProcessInput(df->data, df->size);
    577   ASSERT_EQ(1, spdy_framer_->frames_received());
    578   ASSERT_EQ(4u, actual_header_block.size());
    579   ASSERT_EQ("GET", actual_header_block["method"]);
    580   ASSERT_EQ("HTTP/1.0", actual_header_block["version"]);
    581   ASSERT_EQ("/path", actual_header_block["url"]);
    582   ASSERT_EQ("value1", actual_header_block["key1"]);
    583 }
    584 
    585 TEST_P(SpdySMProxyTest, SendSynStream) {
    586   if (GetParam() == SPDY2) {
    587     // This test is not for SPDY2.
    588     return;
    589   }
    590   uint32 stream_id = 82;
    591   BalsaHeaders headers;
    592   SpdyHeaderBlock actual_header_block;
    593   headers.AppendHeader("key1", "value1");
    594   headers.AppendHeader("Host", "www.example.com");
    595   headers.SetRequestFirstlineFromStringPieces("GET", "/path", "HTTP/1.1");
    596 
    597   interface_->SendSynStream(stream_id, headers);
    598 
    599   ASSERT_EQ(1u, connection_->output_list()->size());
    600   std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin();
    601   DataFrame* df = *i++;
    602 
    603   {
    604     InSequence s;
    605     EXPECT_CALL(*spdy_framer_visitor_,
    606                 OnSynStream(stream_id, 0, _, false, false, _))
    607         .WillOnce(SaveArg<5>(&actual_header_block));
    608   }
    609 
    610   spdy_framer_->ProcessInput(df->data, df->size);
    611   ASSERT_EQ(1, spdy_framer_->frames_received());
    612   ASSERT_EQ(5u, actual_header_block.size());
    613   ASSERT_EQ("GET", actual_header_block[":method"]);
    614   ASSERT_EQ("HTTP/1.1", actual_header_block[":version"]);
    615   ASSERT_EQ("/path", actual_header_block[":path"]);
    616   ASSERT_EQ("www.example.com", actual_header_block[":host"]);
    617   ASSERT_EQ("value1", actual_header_block["key1"]);
    618 }
    619 
    620 TEST_P(SpdySMProxyTest, SendSynReply_SPDY2) {
    621   if (GetParam() != SPDY2) {
    622     // This test is for SPDY2.
    623     return;
    624   }
    625   uint32 stream_id = 82;
    626   BalsaHeaders headers;
    627   SpdyHeaderBlock actual_header_block;
    628   headers.AppendHeader("key1", "value1");
    629   headers.SetResponseFirstlineFromStringPieces("HTTP/1.1", "200", "OK");
    630 
    631   interface_->SendSynReply(stream_id, headers);
    632 
    633   ASSERT_EQ(1u, connection_->output_list()->size());
    634   std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin();
    635   DataFrame* df = *i++;
    636 
    637   {
    638     InSequence s;
    639     if (GetParam() < SPDY4) {
    640       EXPECT_CALL(*spdy_framer_visitor_, OnSynReply(stream_id, false, _))
    641           .WillOnce(SaveArg<2>(&actual_header_block));
    642     } else {
    643       EXPECT_CALL(*spdy_framer_visitor_, OnHeaders(stream_id, false, _))
    644           .WillOnce(SaveArg<2>(&actual_header_block));
    645     }
    646   }
    647 
    648   spdy_framer_->ProcessInput(df->data, df->size);
    649   ASSERT_EQ(1, spdy_framer_->frames_received());
    650   ASSERT_EQ(3u, actual_header_block.size());
    651   ASSERT_EQ("200 OK", actual_header_block["status"]);
    652   ASSERT_EQ("HTTP/1.1", actual_header_block["version"]);
    653   ASSERT_EQ("value1", actual_header_block["key1"]);
    654 }
    655 
    656 TEST_P(SpdySMProxyTest, SendSynReply) {
    657   if (GetParam() == SPDY2) {
    658     // This test is not for SPDY2.
    659     return;
    660   }
    661   uint32 stream_id = 82;
    662   BalsaHeaders headers;
    663   SpdyHeaderBlock actual_header_block;
    664   headers.AppendHeader("key1", "value1");
    665   headers.SetResponseFirstlineFromStringPieces("HTTP/1.1", "200", "OK");
    666 
    667   interface_->SendSynReply(stream_id, headers);
    668 
    669   ASSERT_EQ(1u, connection_->output_list()->size());
    670   std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin();
    671   DataFrame* df = *i++;
    672 
    673   {
    674     InSequence s;
    675     if (GetParam() < SPDY4) {
    676       EXPECT_CALL(*spdy_framer_visitor_, OnSynReply(stream_id, false, _))
    677           .WillOnce(SaveArg<2>(&actual_header_block));
    678     } else {
    679       EXPECT_CALL(*spdy_framer_visitor_, OnHeaders(stream_id, false, _))
    680           .WillOnce(SaveArg<2>(&actual_header_block));
    681     }
    682   }
    683 
    684   spdy_framer_->ProcessInput(df->data, df->size);
    685   ASSERT_EQ(1, spdy_framer_->frames_received());
    686   ASSERT_EQ(3u, actual_header_block.size());
    687   ASSERT_EQ("200 OK", actual_header_block[":status"]);
    688   ASSERT_EQ("HTTP/1.1", actual_header_block[":version"]);
    689   ASSERT_EQ("value1", actual_header_block["key1"]);
    690 }
    691 
    692 TEST_P(SpdySMProxyTest, SendDataFrame) {
    693   uint32 stream_id = 133;
    694   SpdyDataFlags flags = DATA_FLAG_NONE;
    695   const char* actual_data;
    696   size_t actual_size;
    697 
    698   interface_->SendDataFrame(stream_id, "hello", 5, flags, true);
    699 
    700   ASSERT_EQ(1u, connection_->output_list()->size());
    701   std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin();
    702   DataFrame* df = *i++;
    703 
    704   {
    705     InSequence s;
    706     EXPECT_CALL(*spdy_framer_visitor_,
    707                 OnDataFrameHeader(stream_id, _, false));
    708     EXPECT_CALL(*spdy_framer_visitor_,
    709                 OnStreamFrameData(stream_id, _, _, false))
    710         .WillOnce(DoAll(SaveArg<1>(&actual_data), SaveArg<2>(&actual_size)));
    711   }
    712 
    713   spdy_framer_->ProcessInput(df->data, df->size);
    714   ASSERT_EQ(1, spdy_framer_->frames_received());
    715   ASSERT_EQ("hello", StringPiece(actual_data, actual_size));
    716 }
    717 
    718 TEST_P(SpdySMProxyTest, SendLongDataFrame) {
    719   uint32 stream_id = 133;
    720   SpdyDataFlags flags = DATA_FLAG_NONE;
    721   const char* actual_data;
    722   size_t actual_size;
    723 
    724   std::string data = std::string(kSpdySegmentSize, 'a') +
    725                      std::string(kSpdySegmentSize, 'b') + "c";
    726   interface_->SendDataFrame(stream_id, data.data(), data.size(), flags, true);
    727 
    728   {
    729     InSequence s;
    730     for (int i = 0; i < 3; ++i) {
    731         EXPECT_CALL(*spdy_framer_visitor_,
    732                     OnDataFrameHeader(stream_id, _, false));
    733         EXPECT_CALL(*spdy_framer_visitor_,
    734                     OnStreamFrameData(stream_id, _, _, false))
    735             .WillOnce(DoAll(SaveArg<1>(&actual_data),
    736                             SaveArg<2>(&actual_size)));
    737     }
    738   }
    739 
    740   ASSERT_EQ(3u, connection_->output_list()->size());
    741   std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin();
    742   DataFrame* df = *i++;
    743   spdy_framer_->ProcessInput(df->data, df->size);
    744   ASSERT_EQ(std::string(kSpdySegmentSize, 'a'),
    745             StringPiece(actual_data, actual_size));
    746 
    747   df = *i++;
    748   spdy_framer_->ProcessInput(df->data, df->size);
    749   ASSERT_EQ(std::string(kSpdySegmentSize, 'b'),
    750             StringPiece(actual_data, actual_size));
    751 
    752   df = *i++;
    753   spdy_framer_->ProcessInput(df->data, df->size);
    754   ASSERT_EQ("c", StringPiece(actual_data, actual_size));
    755 }
    756 
    757 TEST_P(SpdySMProxyTest, SendEOF_SPDY2) {
    758   // This test is for SPDY2.
    759   if (GetParam() != SPDY2) {
    760     return;
    761   }
    762 
    763   uint32 stream_id = 82;
    764   // SPDY2 data frame
    765   char empty_data_frame[] = {'\0', '\0', '\0', '\x52', '\x1', '\0', '\0', '\0'};
    766   MemCacheIter mci;
    767   mci.stream_id = stream_id;
    768 
    769   {
    770     BalsaHeaders headers;
    771     std::string filename = "foobar";
    772     memory_cache_->InsertFile(&headers, filename, "");
    773     mci.file_data = memory_cache_->GetFileData(filename);
    774   }
    775 
    776   interface_->AddToOutputOrder(mci);
    777   ASSERT_TRUE(HasStream(stream_id));
    778   interface_->SendEOF(stream_id);
    779   ASSERT_FALSE(HasStream(stream_id));
    780 
    781   ASSERT_EQ(1u, connection_->output_list()->size());
    782   std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin();
    783   DataFrame* df = *i++;
    784   ASSERT_EQ(StringPiece(empty_data_frame, sizeof(empty_data_frame)),
    785             StringPiece(df->data, df->size));
    786 }
    787 
    788 TEST_P(SpdySMProxyTest, SendEmptyDataFrame_SPDY2) {
    789   // This test is for SPDY2.
    790   if (GetParam() != SPDY2) {
    791     return;
    792   }
    793 
    794   uint32 stream_id = 133;
    795   SpdyDataFlags flags = DATA_FLAG_NONE;
    796   // SPDY2 data frame
    797   char expected[] = {'\0', '\0', '\0', '\x85', '\0', '\0', '\0', '\0'};
    798 
    799   interface_->SendDataFrame(stream_id, "hello", 0, flags, true);
    800 
    801   ASSERT_EQ(1u, connection_->output_list()->size());
    802   std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin();
    803   DataFrame* df = *i++;
    804 
    805   ASSERT_EQ(StringPiece(expected, sizeof(expected)),
    806             StringPiece(df->data, df->size));
    807 }
    808 
    809 TEST_P(SpdySMServerTest, OnSynStream) {
    810   BufferedSpdyFramerVisitorInterface* visitor = interface_.get();
    811   uint32 stream_id = 82;
    812   SpdyHeaderBlock spdy_headers;
    813   spdy_headers["url"] = "http://www.example.com/path";
    814   spdy_headers["method"] = "GET";
    815   spdy_headers["scheme"] = "http";
    816   spdy_headers["version"] = "HTTP/1.1";
    817 
    818   {
    819     BalsaHeaders headers;
    820     memory_cache_->InsertFile(&headers, "GET_/path", "");
    821   }
    822   visitor->OnSynStream(stream_id, 0, 0, true, true, spdy_headers);
    823   ASSERT_TRUE(HasStream(stream_id));
    824 }
    825 
    826 TEST_P(SpdySMServerTest, NewStream) {
    827   uint32 stream_id = 13;
    828   std::string filename = "foobar";
    829 
    830   {
    831     BalsaHeaders headers;
    832     memory_cache_->InsertFile(&headers, filename, "");
    833   }
    834 
    835   interface_->NewStream(stream_id, 0, filename);
    836   ASSERT_TRUE(HasStream(stream_id));
    837 }
    838 
    839 TEST_P(SpdySMServerTest, NewStreamError) {
    840   uint32 stream_id = 82;
    841   SpdyHeaderBlock actual_header_block;
    842   const char* actual_data;
    843   size_t actual_size;
    844   testing::MockFunction<void(int)> checkpoint;  // NOLINT
    845 
    846   interface_->NewStream(stream_id, 0, "nonexistingfile");
    847 
    848   ASSERT_EQ(2u, connection_->output_list()->size());
    849 
    850   {
    851     InSequence s;
    852     if (GetParam() < SPDY4) {
    853       EXPECT_CALL(*spdy_framer_visitor_, OnSynReply(stream_id, false, _))
    854           .WillOnce(SaveArg<2>(&actual_header_block));
    855     } else {
    856       EXPECT_CALL(*spdy_framer_visitor_, OnHeaders(stream_id, false, _))
    857           .WillOnce(SaveArg<2>(&actual_header_block));
    858     }
    859     EXPECT_CALL(checkpoint, Call(0));
    860     EXPECT_CALL(*spdy_framer_visitor_,
    861                 OnDataFrameHeader(stream_id, _, true));
    862     EXPECT_CALL(*spdy_framer_visitor_,
    863                 OnStreamFrameData(stream_id, _, _, false)).Times(1)
    864         .WillOnce(DoAll(SaveArg<1>(&actual_data),
    865                         SaveArg<2>(&actual_size)));
    866     EXPECT_CALL(*spdy_framer_visitor_,
    867                 OnStreamFrameData(stream_id, NULL, 0, true)).Times(1);
    868   }
    869 
    870   std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin();
    871   DataFrame* df = *i++;
    872   spdy_framer_->ProcessInput(df->data, df->size);
    873   checkpoint.Call(0);
    874   df = *i++;
    875   spdy_framer_->ProcessInput(df->data, df->size);
    876 
    877   ASSERT_EQ(2, spdy_framer_->frames_received());
    878   ASSERT_EQ(2u, actual_header_block.size());
    879   ASSERT_EQ("404 Not Found", actual_header_block["status"]);
    880   ASSERT_EQ("HTTP/1.1", actual_header_block["version"]);
    881   ASSERT_EQ("wtf?", StringPiece(actual_data, actual_size));
    882 }
    883 
    884 }  // namespace
    885 
    886 }  // namespace net
    887