| 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 |