| 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 #include <memory> | |
| 9 | |
| 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 inline bool operator==(StringPiece x, | |
| 31 const SpdyHeaderBlock::StringPieceProxy& y) { | |
| 32 return x == y.operator StringPiece(); | |
| 33 } | |
| 34 | |
| 35 namespace { | |
| 36 | |
| 37 struct StringSaver { | |
| 38 public: | |
| 39 StringSaver() : data(NULL), size(0) {} | |
| 40 void Save() { string = std::string(data, size); } | |
| 41 | |
| 42 const char* data; | |
| 43 size_t size; | |
| 44 std::string string; | |
| 45 }; | |
| 46 | |
| 47 class SpdyFramerVisitor : public BufferedSpdyFramerVisitorInterface { | |
| 48 public: | |
| 49 virtual ~SpdyFramerVisitor() {} | |
| 50 MOCK_METHOD1(OnError, void(SpdyFramer::SpdyError)); | |
| 51 MOCK_METHOD2(OnStreamError, void(SpdyStreamId, const std::string&)); | |
| 52 // SaveArg cannot be used on non-copyable types like SpdyHeaderBlock. | |
| 53 void OnHeaders(SpdyStreamId stream_id, | |
| 54 bool has_priority, | |
| 55 int weight, | |
| 56 SpdyStreamId parent_stream_id, | |
| 57 bool exclusive, | |
| 58 bool fin, | |
| 59 const SpdyHeaderBlock& headers) override { | |
| 60 actual_header_block_ = headers.Clone(); | |
| 61 OnHeadersMock(stream_id, has_priority, weight, parent_stream_id, exclusive, | |
| 62 fin, headers); | |
| 63 } | |
| 64 MOCK_METHOD7(OnHeadersMock, | |
| 65 void(SpdyStreamId stream_id, | |
| 66 bool has_priority, | |
| 67 int weight, | |
| 68 SpdyStreamId parent_stream_id, | |
| 69 bool exclusive, | |
| 70 bool fin, | |
| 71 const SpdyHeaderBlock& headers)); | |
| 72 MOCK_METHOD3(OnDataFrameHeader, void(SpdyStreamId, size_t, bool)); | |
| 73 MOCK_METHOD3(OnStreamFrameData, void(SpdyStreamId, const char*, size_t)); | |
| 74 MOCK_METHOD1(OnStreamEnd, void(SpdyStreamId)); | |
| 75 MOCK_METHOD2(OnStreamPadding, void(SpdyStreamId, size_t)); | |
| 76 MOCK_METHOD1(OnHeaderFrameStart, | |
| 77 SpdyHeadersHandlerInterface*(SpdyStreamId stream_id)); | |
| 78 MOCK_METHOD2(OnHeaderFrameEnd, | |
| 79 void(SpdyStreamId stream_id, bool end_headers)); | |
| 80 MOCK_METHOD1(OnSettings, void(bool clear_persisted)); | |
| 81 MOCK_METHOD3(OnSetting, void(SpdySettingsIds, uint8_t, uint32_t)); | |
| 82 MOCK_METHOD2(OnPing, void(SpdyPingId unique_id, bool is_ack)); | |
| 83 MOCK_METHOD2(OnRstStream, void(SpdyStreamId, SpdyRstStreamStatus)); | |
| 84 MOCK_METHOD3(OnGoAway, void(SpdyStreamId, SpdyGoAwayStatus, StringPiece)); | |
| 85 MOCK_METHOD2(OnWindowUpdate, void(SpdyStreamId, int)); | |
| 86 MOCK_METHOD3(OnPushPromise, | |
| 87 void(SpdyStreamId, SpdyStreamId, const SpdyHeaderBlock&)); | |
| 88 MOCK_METHOD3(OnAltSvc, | |
| 89 void(SpdyStreamId, | |
| 90 base::StringPiece, | |
| 91 const SpdyAltSvcWireFormat::AlternativeServiceVector&)); | |
| 92 MOCK_METHOD2(OnUnknownFrame, bool(SpdyStreamId stream_id, int frame_type)); | |
| 93 | |
| 94 SpdyHeaderBlock actual_header_block_; | |
| 95 }; | |
| 96 | |
| 97 class FakeSMConnection : public SMConnection { | |
| 98 public: | |
| 99 FakeSMConnection(EpollServer* epoll_server, | |
| 100 SSLState* ssl_state, | |
| 101 MemoryCache* memory_cache, | |
| 102 FlipAcceptor* acceptor, | |
| 103 std::string log_prefix) | |
| 104 : SMConnection(epoll_server, | |
| 105 ssl_state, | |
| 106 memory_cache, | |
| 107 acceptor, | |
| 108 log_prefix) {} | |
| 109 | |
| 110 MOCK_METHOD0(Cleanup, void()); | |
| 111 MOCK_METHOD8(InitSMConnection, | |
| 112 void(SMConnectionPoolInterface*, | |
| 113 SMInterface*, | |
| 114 EpollServer*, | |
| 115 int, | |
| 116 std::string, | |
| 117 std::string, | |
| 118 std::string, | |
| 119 bool)); | |
| 120 }; | |
| 121 | |
| 122 // This class is almost SpdySM, except one function. | |
| 123 // This class is the test target of tests in this file. | |
| 124 class TestSpdySM : public SpdySM { | |
| 125 public: | |
| 126 virtual ~TestSpdySM() {} | |
| 127 TestSpdySM(SMConnection* connection, | |
| 128 SMInterface* sm_http_interface, | |
| 129 EpollServer* epoll_server, | |
| 130 MemoryCache* memory_cache, | |
| 131 FlipAcceptor* acceptor) | |
| 132 : SpdySM(connection, | |
| 133 sm_http_interface, | |
| 134 epoll_server, | |
| 135 memory_cache, | |
| 136 acceptor) {} | |
| 137 | |
| 138 MOCK_METHOD2(FindOrMakeNewSMConnectionInterface, | |
| 139 SMInterface*(const std::string&, const std::string&)); | |
| 140 }; | |
| 141 | |
| 142 class SpdySMTestBase : public ::testing::Test { | |
| 143 public: | |
| 144 explicit SpdySMTestBase(FlipHandlerType type) { | |
| 145 SSLState* ssl_state = NULL; | |
| 146 mock_another_interface_.reset(new MockSMInterface); | |
| 147 memory_cache_.reset(new MemoryCache); | |
| 148 acceptor_.reset(new FlipAcceptor(type, | |
| 149 "127.0.0.1", | |
| 150 "8941", | |
| 151 "ssl_cert_filename", | |
| 152 "ssl_key_filename", | |
| 153 "127.0.0.1", | |
| 154 "8942", | |
| 155 "127.0.0.1", | |
| 156 "8943", | |
| 157 1, | |
| 158 0, | |
| 159 true, | |
| 160 1, | |
| 161 false, | |
| 162 true, | |
| 163 NULL)); | |
| 164 epoll_server_.reset(new EpollServer); | |
| 165 connection_.reset(new FakeSMConnection(epoll_server_.get(), | |
| 166 ssl_state, | |
| 167 memory_cache_.get(), | |
| 168 acceptor_.get(), | |
| 169 "log_prefix")); | |
| 170 | |
| 171 interface_.reset(new TestSpdySM( | |
| 172 connection_.get(), mock_another_interface_.get(), epoll_server_.get(), | |
| 173 memory_cache_.get(), acceptor_.get())); | |
| 174 | |
| 175 spdy_framer_.reset(new BufferedSpdyFramer()); | |
| 176 spdy_framer_visitor_.reset(new SpdyFramerVisitor); | |
| 177 spdy_framer_->set_visitor(spdy_framer_visitor_.get()); | |
| 178 } | |
| 179 | |
| 180 ~SpdySMTestBase() override { | |
| 181 if (acceptor_->listen_fd_ >= 0) { | |
| 182 epoll_server_->UnregisterFD(acceptor_->listen_fd_); | |
| 183 close(acceptor_->listen_fd_); | |
| 184 acceptor_->listen_fd_ = -1; | |
| 185 } | |
| 186 OutputList& output_list = *connection_->output_list(); | |
| 187 for (OutputList::const_iterator i = output_list.begin(); | |
| 188 i != output_list.end(); | |
| 189 ++i) { | |
| 190 delete *i; | |
| 191 } | |
| 192 output_list.clear(); | |
| 193 } | |
| 194 | |
| 195 bool HasStream(uint32_t stream_id) { | |
| 196 return interface_->output_ordering().ExistsInPriorityMaps(stream_id); | |
| 197 } | |
| 198 | |
| 199 protected: | |
| 200 std::unique_ptr<MockSMInterface> mock_another_interface_; | |
| 201 std::unique_ptr<MemoryCache> memory_cache_; | |
| 202 std::unique_ptr<FlipAcceptor> acceptor_; | |
| 203 std::unique_ptr<EpollServer> epoll_server_; | |
| 204 std::unique_ptr<FakeSMConnection> connection_; | |
| 205 std::unique_ptr<TestSpdySM> interface_; | |
| 206 std::unique_ptr<BufferedSpdyFramer> spdy_framer_; | |
| 207 std::unique_ptr<SpdyFramerVisitor> spdy_framer_visitor_; | |
| 208 }; | |
| 209 | |
| 210 class SpdySMProxyTest : public SpdySMTestBase { | |
| 211 public: | |
| 212 SpdySMProxyTest() : SpdySMTestBase(FLIP_HANDLER_PROXY) {} | |
| 213 ~SpdySMProxyTest() override {} | |
| 214 }; | |
| 215 | |
| 216 class SpdySMServerTest : public SpdySMTestBase { | |
| 217 public: | |
| 218 SpdySMServerTest() : SpdySMTestBase(FLIP_HANDLER_SPDY_SERVER) {} | |
| 219 ~SpdySMServerTest() override {} | |
| 220 }; | |
| 221 | |
| 222 TEST_F(SpdySMProxyTest, InitSMConnection) { | |
| 223 { | |
| 224 InSequence s; | |
| 225 EXPECT_CALL(*connection_, InitSMConnection(_, _, _, _, _, _, _, _)); | |
| 226 } | |
| 227 interface_->InitSMConnection( | |
| 228 NULL, NULL, epoll_server_.get(), -1, "", "", "", false); | |
| 229 } | |
| 230 | |
| 231 TEST_F(SpdySMProxyTest, OnRstStream) { | |
| 232 BufferedSpdyFramerVisitorInterface* visitor = interface_.get(); | |
| 233 uint32_t stream_id = 82; | |
| 234 MemCacheIter mci; | |
| 235 mci.stream_id = stream_id; | |
| 236 | |
| 237 { | |
| 238 BalsaHeaders headers; | |
| 239 std::string filename = "foobar"; | |
| 240 memory_cache_->InsertFile(&headers, filename, ""); | |
| 241 mci.file_data = memory_cache_->GetFileData(filename); | |
| 242 } | |
| 243 | |
| 244 interface_->AddToOutputOrder(mci); | |
| 245 ASSERT_TRUE(HasStream(stream_id)); | |
| 246 visitor->OnRstStream(stream_id, RST_STREAM_INVALID); | |
| 247 ASSERT_FALSE(HasStream(stream_id)); | |
| 248 } | |
| 249 | |
| 250 TEST_F(SpdySMProxyTest, ProcessReadInput) { | |
| 251 ASSERT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, | |
| 252 interface_->spdy_framer()->state()); | |
| 253 interface_->ProcessReadInput("", 1); | |
| 254 ASSERT_EQ(SpdyFramer::SPDY_READING_COMMON_HEADER, | |
| 255 interface_->spdy_framer()->state()); | |
| 256 } | |
| 257 | |
| 258 TEST_F(SpdySMProxyTest, ResetForNewConnection) { | |
| 259 uint32_t stream_id = 13; | |
| 260 MemCacheIter mci; | |
| 261 mci.stream_id = stream_id; | |
| 262 // incomplete input | |
| 263 const char input[] = {'\0', '\0', '\0'}; | |
| 264 | |
| 265 { | |
| 266 BalsaHeaders headers; | |
| 267 std::string filename = "foobar"; | |
| 268 memory_cache_->InsertFile(&headers, filename, ""); | |
| 269 mci.file_data = memory_cache_->GetFileData(filename); | |
| 270 } | |
| 271 | |
| 272 interface_->AddToOutputOrder(mci); | |
| 273 ASSERT_TRUE(HasStream(stream_id)); | |
| 274 interface_->ProcessReadInput(input, sizeof(input)); | |
| 275 ASSERT_NE(SpdyFramer::SPDY_READY_FOR_FRAME, | |
| 276 interface_->spdy_framer()->state()); | |
| 277 | |
| 278 interface_->ResetForNewConnection(); | |
| 279 ASSERT_FALSE(HasStream(stream_id)); | |
| 280 ASSERT_TRUE(interface_->spdy_framer() == NULL); | |
| 281 } | |
| 282 | |
| 283 TEST_F(SpdySMProxyTest, CreateFramer) { | |
| 284 interface_->ResetForNewConnection(); | |
| 285 interface_->CreateFramer(); | |
| 286 ASSERT_TRUE(interface_->spdy_framer()); | |
| 287 } | |
| 288 | |
| 289 TEST_F(SpdySMProxyTest, PostAcceptHook) { | |
| 290 interface_->PostAcceptHook(); | |
| 291 | |
| 292 ASSERT_EQ(1u, connection_->output_list()->size()); | |
| 293 std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin(); | |
| 294 DataFrame* df = *i++; | |
| 295 | |
| 296 { | |
| 297 InSequence s; | |
| 298 EXPECT_CALL(*spdy_framer_visitor_, OnSettings(false)); | |
| 299 EXPECT_CALL(*spdy_framer_visitor_, | |
| 300 OnSetting(SETTINGS_MAX_CONCURRENT_STREAMS, 0u, 100u)); | |
| 301 } | |
| 302 spdy_framer_->ProcessInput(df->data, df->size); | |
| 303 } | |
| 304 | |
| 305 TEST_F(SpdySMProxyTest, NewStream) { | |
| 306 // TODO(yhirano): SpdySM::NewStream leads to crash when | |
| 307 // acceptor_->flip_handler_type_ != FLIP_HANDLER_SPDY_SERVER. | |
| 308 // It should be fixed though I don't know the solution now. | |
| 309 } | |
| 310 | |
| 311 TEST_F(SpdySMProxyTest, AddToOutputOrder) { | |
| 312 uint32_t stream_id = 13; | |
| 313 MemCacheIter mci; | |
| 314 mci.stream_id = stream_id; | |
| 315 | |
| 316 { | |
| 317 BalsaHeaders headers; | |
| 318 std::string filename = "foobar"; | |
| 319 memory_cache_->InsertFile(&headers, filename, ""); | |
| 320 mci.file_data = memory_cache_->GetFileData(filename); | |
| 321 } | |
| 322 | |
| 323 interface_->AddToOutputOrder(mci); | |
| 324 ASSERT_TRUE(HasStream(stream_id)); | |
| 325 } | |
| 326 | |
| 327 TEST_F(SpdySMProxyTest, SendErrorNotFound) { | |
| 328 uint32_t stream_id = 82; | |
| 329 const char* actual_data; | |
| 330 size_t actual_size; | |
| 331 testing::MockFunction<void(int)> checkpoint; // NOLINT | |
| 332 | |
| 333 interface_->SendErrorNotFound(stream_id); | |
| 334 | |
| 335 ASSERT_EQ(2u, connection_->output_list()->size()); | |
| 336 | |
| 337 { | |
| 338 InSequence s; | |
| 339 EXPECT_CALL(*spdy_framer_visitor_, | |
| 340 OnHeadersMock(stream_id, /*has_priority=*/false, _, _, _, | |
| 341 /*fin=*/false, _)); | |
| 342 EXPECT_CALL(checkpoint, Call(0)); | |
| 343 EXPECT_CALL(*spdy_framer_visitor_, | |
| 344 OnDataFrameHeader(stream_id, _, true)); | |
| 345 EXPECT_CALL(*spdy_framer_visitor_, OnStreamFrameData(stream_id, _, _)) | |
| 346 .Times(1) | |
| 347 .WillOnce(DoAll(SaveArg<1>(&actual_data), SaveArg<2>(&actual_size))); | |
| 348 EXPECT_CALL(*spdy_framer_visitor_, OnStreamFrameData(stream_id, NULL, 0)) | |
| 349 .Times(1); | |
| 350 } | |
| 351 | |
| 352 std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin(); | |
| 353 DataFrame* df = *i++; | |
| 354 spdy_framer_->ProcessInput(df->data, df->size); | |
| 355 checkpoint.Call(0); | |
| 356 df = *i++; | |
| 357 spdy_framer_->ProcessInput(df->data, df->size); | |
| 358 | |
| 359 ASSERT_EQ(2, spdy_framer_->frames_received()); | |
| 360 ASSERT_EQ(2u, spdy_framer_visitor_->actual_header_block_.size()); | |
| 361 ASSERT_EQ("404 Not Found", | |
| 362 spdy_framer_visitor_->actual_header_block_[":status"]); | |
| 363 ASSERT_EQ("HTTP/1.1", spdy_framer_visitor_->actual_header_block_[":version"]); | |
| 364 ASSERT_EQ("wtf?", StringPiece(actual_data, actual_size)); | |
| 365 } | |
| 366 | |
| 367 TEST_F(SpdySMProxyTest, SendSynReply) { | |
| 368 uint32_t stream_id = 82; | |
| 369 BalsaHeaders headers; | |
| 370 headers.AppendHeader("key1", "value1"); | |
| 371 headers.SetResponseFirstlineFromStringPieces("HTTP/1.1", "200", "OK"); | |
| 372 | |
| 373 interface_->SendSynReply(stream_id, headers); | |
| 374 | |
| 375 ASSERT_EQ(1u, connection_->output_list()->size()); | |
| 376 std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin(); | |
| 377 DataFrame* df = *i++; | |
| 378 | |
| 379 { | |
| 380 InSequence s; | |
| 381 EXPECT_CALL(*spdy_framer_visitor_, | |
| 382 OnHeadersMock(stream_id, /*has_priority=*/false, _, _, _, | |
| 383 /*fin=*/false, _)); | |
| 384 } | |
| 385 | |
| 386 spdy_framer_->ProcessInput(df->data, df->size); | |
| 387 ASSERT_EQ(1, spdy_framer_->frames_received()); | |
| 388 ASSERT_EQ(3u, spdy_framer_visitor_->actual_header_block_.size()); | |
| 389 ASSERT_EQ("200 OK", spdy_framer_visitor_->actual_header_block_[":status"]); | |
| 390 ASSERT_EQ("HTTP/1.1", spdy_framer_visitor_->actual_header_block_[":version"]); | |
| 391 ASSERT_EQ("value1", spdy_framer_visitor_->actual_header_block_["key1"]); | |
| 392 } | |
| 393 | |
| 394 TEST_F(SpdySMProxyTest, SendDataFrame) { | |
| 395 uint32_t stream_id = 133; | |
| 396 SpdyDataFlags flags = DATA_FLAG_NONE; | |
| 397 const char* actual_data; | |
| 398 size_t actual_size; | |
| 399 | |
| 400 interface_->SendDataFrame(stream_id, "hello", 5, flags, true); | |
| 401 | |
| 402 ASSERT_EQ(1u, connection_->output_list()->size()); | |
| 403 std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin(); | |
| 404 DataFrame* df = *i++; | |
| 405 | |
| 406 { | |
| 407 InSequence s; | |
| 408 EXPECT_CALL(*spdy_framer_visitor_, | |
| 409 OnDataFrameHeader(stream_id, _, false)); | |
| 410 EXPECT_CALL(*spdy_framer_visitor_, OnStreamFrameData(stream_id, _, _)) | |
| 411 .WillOnce(DoAll(SaveArg<1>(&actual_data), SaveArg<2>(&actual_size))); | |
| 412 } | |
| 413 | |
| 414 spdy_framer_->ProcessInput(df->data, df->size); | |
| 415 ASSERT_EQ(1, spdy_framer_->frames_received()); | |
| 416 ASSERT_EQ("hello", StringPiece(actual_data, actual_size)); | |
| 417 } | |
| 418 | |
| 419 TEST_F(SpdySMProxyTest, SendLongDataFrame) { | |
| 420 uint32_t stream_id = 133; | |
| 421 SpdyDataFlags flags = DATA_FLAG_NONE; | |
| 422 const char* actual_data; | |
| 423 size_t actual_size; | |
| 424 | |
| 425 std::string data = std::string(kSpdySegmentSize, 'a') + | |
| 426 std::string(kSpdySegmentSize, 'b') + "c"; | |
| 427 interface_->SendDataFrame(stream_id, data.data(), data.size(), flags, true); | |
| 428 | |
| 429 { | |
| 430 InSequence s; | |
| 431 for (int i = 0; i < 3; ++i) { | |
| 432 EXPECT_CALL(*spdy_framer_visitor_, | |
| 433 OnDataFrameHeader(stream_id, _, false)); | |
| 434 EXPECT_CALL(*spdy_framer_visitor_, OnStreamFrameData(stream_id, _, _)) | |
| 435 .WillOnce( | |
| 436 DoAll(SaveArg<1>(&actual_data), SaveArg<2>(&actual_size))); | |
| 437 } | |
| 438 } | |
| 439 | |
| 440 ASSERT_EQ(3u, connection_->output_list()->size()); | |
| 441 std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin(); | |
| 442 DataFrame* df = *i++; | |
| 443 spdy_framer_->ProcessInput(df->data, df->size); | |
| 444 ASSERT_EQ(std::string(kSpdySegmentSize, 'a'), | |
| 445 StringPiece(actual_data, actual_size)); | |
| 446 | |
| 447 df = *i++; | |
| 448 spdy_framer_->ProcessInput(df->data, df->size); | |
| 449 ASSERT_EQ(std::string(kSpdySegmentSize, 'b'), | |
| 450 StringPiece(actual_data, actual_size)); | |
| 451 | |
| 452 df = *i++; | |
| 453 spdy_framer_->ProcessInput(df->data, df->size); | |
| 454 ASSERT_EQ("c", StringPiece(actual_data, actual_size)); | |
| 455 } | |
| 456 | |
| 457 TEST_F(SpdySMServerTest, NewStream) { | |
| 458 uint32_t stream_id = 13; | |
| 459 std::string filename = "foobar"; | |
| 460 | |
| 461 { | |
| 462 BalsaHeaders headers; | |
| 463 memory_cache_->InsertFile(&headers, filename, ""); | |
| 464 } | |
| 465 | |
| 466 interface_->NewStream(stream_id, 0, filename); | |
| 467 ASSERT_TRUE(HasStream(stream_id)); | |
| 468 } | |
| 469 | |
| 470 TEST_F(SpdySMServerTest, NewStreamError) { | |
| 471 uint32_t stream_id = 82; | |
| 472 const char* actual_data; | |
| 473 size_t actual_size; | |
| 474 testing::MockFunction<void(int)> checkpoint; // NOLINT | |
| 475 | |
| 476 interface_->NewStream(stream_id, 0, "nonexistingfile"); | |
| 477 | |
| 478 ASSERT_EQ(2u, connection_->output_list()->size()); | |
| 479 | |
| 480 { | |
| 481 InSequence s; | |
| 482 EXPECT_CALL(*spdy_framer_visitor_, | |
| 483 OnHeadersMock(stream_id, /*has_priority=*/false, _, _, _, | |
| 484 /*fin=*/false, _)); | |
| 485 EXPECT_CALL(checkpoint, Call(0)); | |
| 486 EXPECT_CALL(*spdy_framer_visitor_, | |
| 487 OnDataFrameHeader(stream_id, _, true)); | |
| 488 EXPECT_CALL(*spdy_framer_visitor_, OnStreamFrameData(stream_id, _, _)) | |
| 489 .Times(1) | |
| 490 .WillOnce(DoAll(SaveArg<1>(&actual_data), SaveArg<2>(&actual_size))); | |
| 491 EXPECT_CALL(*spdy_framer_visitor_, OnStreamFrameData(stream_id, NULL, 0)) | |
| 492 .Times(1); | |
| 493 } | |
| 494 | |
| 495 std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin(); | |
| 496 DataFrame* df = *i++; | |
| 497 spdy_framer_->ProcessInput(df->data, df->size); | |
| 498 checkpoint.Call(0); | |
| 499 df = *i++; | |
| 500 spdy_framer_->ProcessInput(df->data, df->size); | |
| 501 | |
| 502 ASSERT_EQ(2, spdy_framer_->frames_received()); | |
| 503 ASSERT_EQ(2u, spdy_framer_visitor_->actual_header_block_.size()); | |
| 504 ASSERT_EQ("404 Not Found", | |
| 505 spdy_framer_visitor_->actual_header_block_["status"]); | |
| 506 ASSERT_EQ("HTTP/1.1", spdy_framer_visitor_->actual_header_block_["version"]); | |
| 507 ASSERT_EQ("wtf?", StringPiece(actual_data, actual_size)); | |
| 508 } | |
| 509 | |
| 510 } // namespace | |
| 511 | |
| 512 } // namespace net | |
| OLD | NEW |