Rename InputLatency::ScrollUpdate to Latency::ScrollUpdate
[chromium-blink-merge.git] / net / tools / flip_server / spdy_interface_test.cc
blob6aa3d308a8e567cf3d34e8674b72f1e8f04b9509
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"
7 #include <list>
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"
20 namespace net {
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;
30 namespace {
32 struct StringSaver {
33 public:
34 StringSaver() : data(NULL), size(0) {}
35 void Save() { string = std::string(data, size); }
37 const char* data;
38 size_t size;
39 std::string string;
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_METHOD2(OnStreamPadding, void(SpdyStreamId, size_t));
67 MOCK_METHOD1(OnSettings, void(bool clear_persisted));
68 MOCK_METHOD3(OnSetting, void(SpdySettingsIds, uint8, uint32));
69 MOCK_METHOD2(OnPing, void(SpdyPingId unique_id, bool is_ack));
70 MOCK_METHOD2(OnRstStream, void(SpdyStreamId, SpdyRstStreamStatus));
71 MOCK_METHOD2(OnGoAway, void(SpdyStreamId, SpdyGoAwayStatus));
72 MOCK_METHOD2(OnWindowUpdate, void(SpdyStreamId, uint32));
73 MOCK_METHOD3(OnPushPromise,
74 void(SpdyStreamId, SpdyStreamId, const SpdyHeaderBlock&));
75 MOCK_METHOD2(OnUnknownFrame, bool(SpdyStreamId stream_id, int frame_type));
78 class FakeSMConnection : public SMConnection {
79 public:
80 FakeSMConnection(EpollServer* epoll_server,
81 SSLState* ssl_state,
82 MemoryCache* memory_cache,
83 FlipAcceptor* acceptor,
84 std::string log_prefix)
85 : SMConnection(epoll_server,
86 ssl_state,
87 memory_cache,
88 acceptor,
89 log_prefix) {}
91 MOCK_METHOD0(Cleanup, void());
92 MOCK_METHOD8(InitSMConnection,
93 void(SMConnectionPoolInterface*,
94 SMInterface*,
95 EpollServer*,
96 int,
97 std::string,
98 std::string,
99 std::string,
100 bool));
103 // This class is almost SpdySM, except one function.
104 // This class is the test target of tests in this file.
105 class TestSpdySM : public SpdySM {
106 public:
107 virtual ~TestSpdySM() {}
108 TestSpdySM(SMConnection* connection,
109 SMInterface* sm_http_interface,
110 EpollServer* epoll_server,
111 MemoryCache* memory_cache,
112 FlipAcceptor* acceptor,
113 SpdyMajorVersion version)
114 : SpdySM(connection,
115 sm_http_interface,
116 epoll_server,
117 memory_cache,
118 acceptor,
119 version) {}
121 MOCK_METHOD2(FindOrMakeNewSMConnectionInterface,
122 SMInterface*(const std::string&, const std::string&));
125 class SpdySMTestBase : public ::testing::TestWithParam<SpdyMajorVersion> {
126 public:
127 explicit SpdySMTestBase(FlipHandlerType type) {
128 SSLState* ssl_state = NULL;
129 mock_another_interface_.reset(new MockSMInterface);
130 memory_cache_.reset(new MemoryCache);
131 acceptor_.reset(new FlipAcceptor(type,
132 "127.0.0.1",
133 "8941",
134 "ssl_cert_filename",
135 "ssl_key_filename",
136 "127.0.0.1",
137 "8942",
138 "127.0.0.1",
139 "8943",
142 true,
144 false,
145 true,
146 NULL));
147 epoll_server_.reset(new EpollServer);
148 connection_.reset(new FakeSMConnection(epoll_server_.get(),
149 ssl_state,
150 memory_cache_.get(),
151 acceptor_.get(),
152 "log_prefix"));
154 interface_.reset(new TestSpdySM(connection_.get(),
155 mock_another_interface_.get(),
156 epoll_server_.get(),
157 memory_cache_.get(),
158 acceptor_.get(),
159 GetParam()));
161 spdy_framer_.reset(new BufferedSpdyFramer(GetParam(), true));
162 spdy_framer_visitor_.reset(new SpdyFramerVisitor);
163 spdy_framer_->set_visitor(spdy_framer_visitor_.get());
166 virtual ~SpdySMTestBase() {
167 if (acceptor_->listen_fd_ >= 0) {
168 epoll_server_->UnregisterFD(acceptor_->listen_fd_);
169 close(acceptor_->listen_fd_);
170 acceptor_->listen_fd_ = -1;
172 OutputList& output_list = *connection_->output_list();
173 for (OutputList::const_iterator i = output_list.begin();
174 i != output_list.end();
175 ++i) {
176 delete *i;
178 output_list.clear();
181 bool HasStream(uint32 stream_id) {
182 return interface_->output_ordering().ExistsInPriorityMaps(stream_id);
185 protected:
186 scoped_ptr<MockSMInterface> mock_another_interface_;
187 scoped_ptr<MemoryCache> memory_cache_;
188 scoped_ptr<FlipAcceptor> acceptor_;
189 scoped_ptr<EpollServer> epoll_server_;
190 scoped_ptr<FakeSMConnection> connection_;
191 scoped_ptr<TestSpdySM> interface_;
192 scoped_ptr<BufferedSpdyFramer> spdy_framer_;
193 scoped_ptr<SpdyFramerVisitor> spdy_framer_visitor_;
196 class SpdySMProxyTest : public SpdySMTestBase {
197 public:
198 SpdySMProxyTest() : SpdySMTestBase(FLIP_HANDLER_PROXY) {}
199 virtual ~SpdySMProxyTest() {}
202 class SpdySMServerTest : public SpdySMTestBase {
203 public:
204 SpdySMServerTest() : SpdySMTestBase(FLIP_HANDLER_SPDY_SERVER) {}
205 virtual ~SpdySMServerTest() {}
208 INSTANTIATE_TEST_CASE_P(SpdySMProxyTest,
209 SpdySMProxyTest,
210 Values(SPDY3, SPDY4));
211 INSTANTIATE_TEST_CASE_P(SpdySMServerTest, SpdySMServerTest, Values(SPDY4));
213 TEST_P(SpdySMProxyTest, InitSMConnection) {
215 InSequence s;
216 EXPECT_CALL(*connection_, InitSMConnection(_, _, _, _, _, _, _, _));
218 interface_->InitSMConnection(
219 NULL, NULL, epoll_server_.get(), -1, "", "", "", false);
222 TEST_P(SpdySMProxyTest, OnStreamFrameData) {
223 BufferedSpdyFramerVisitorInterface* visitor = interface_.get();
224 scoped_ptr<MockSMInterface> mock_interface(new MockSMInterface);
225 uint32 stream_id = 92;
226 uint32 associated_id = 43;
227 SpdyHeaderBlock block;
228 testing::MockFunction<void(int)> checkpoint; // NOLINT
230 scoped_ptr<SpdyFrame> frame(spdy_framer_->CreatePingFrame(12, false));
231 block[":method"] = "GET";
232 block[":host"] = "www.example.com";
233 block[":path"] = "/path";
234 block[":scheme"] = "http";
235 block["foo"] = "bar";
237 InSequence s;
238 EXPECT_CALL(*interface_,
239 FindOrMakeNewSMConnectionInterface(_, _))
240 .WillOnce(Return(mock_interface.get()));
241 EXPECT_CALL(*mock_interface, SetStreamID(stream_id));
242 EXPECT_CALL(*mock_interface, ProcessWriteInput(_, _)).Times(1);
243 EXPECT_CALL(checkpoint, Call(0));
244 EXPECT_CALL(*mock_interface,
245 ProcessWriteInput(frame->data(), frame->size())).Times(1);
248 visitor->OnSynStream(stream_id, associated_id, 0, false, false, block);
249 checkpoint.Call(0);
250 visitor->OnStreamFrameData(stream_id, frame->data(), frame->size(), true);
253 TEST_P(SpdySMProxyTest, OnRstStream) {
254 BufferedSpdyFramerVisitorInterface* visitor = interface_.get();
255 uint32 stream_id = 82;
256 MemCacheIter mci;
257 mci.stream_id = stream_id;
260 BalsaHeaders headers;
261 std::string filename = "foobar";
262 memory_cache_->InsertFile(&headers, filename, "");
263 mci.file_data = memory_cache_->GetFileData(filename);
266 interface_->AddToOutputOrder(mci);
267 ASSERT_TRUE(HasStream(stream_id));
268 visitor->OnRstStream(stream_id, RST_STREAM_INVALID);
269 ASSERT_FALSE(HasStream(stream_id));
272 TEST_P(SpdySMProxyTest, ProcessReadInput) {
273 ASSERT_EQ(SpdyFramer::SPDY_RESET, interface_->spdy_framer()->state());
274 interface_->ProcessReadInput("", 1);
275 ASSERT_EQ(SpdyFramer::SPDY_READING_COMMON_HEADER,
276 interface_->spdy_framer()->state());
279 TEST_P(SpdySMProxyTest, ResetForNewConnection) {
280 uint32 stream_id = 13;
281 MemCacheIter mci;
282 mci.stream_id = stream_id;
283 // incomplete input
284 const char input[] = {'\0', '\0', '\0'};
287 BalsaHeaders headers;
288 std::string filename = "foobar";
289 memory_cache_->InsertFile(&headers, filename, "");
290 mci.file_data = memory_cache_->GetFileData(filename);
293 interface_->AddToOutputOrder(mci);
294 ASSERT_TRUE(HasStream(stream_id));
295 interface_->ProcessReadInput(input, sizeof(input));
296 ASSERT_NE(SpdyFramer::SPDY_RESET, interface_->spdy_framer()->state());
298 interface_->ResetForNewConnection();
299 ASSERT_FALSE(HasStream(stream_id));
300 ASSERT_TRUE(interface_->spdy_framer() == NULL);
303 TEST_P(SpdySMProxyTest, CreateFramer) {
304 interface_->ResetForNewConnection();
305 interface_->CreateFramer(SPDY3);
306 ASSERT_TRUE(interface_->spdy_framer() != NULL);
307 ASSERT_EQ(interface_->spdy_version(), SPDY3);
309 interface_->ResetForNewConnection();
310 interface_->CreateFramer(SPDY4);
311 ASSERT_TRUE(interface_->spdy_framer() != NULL);
312 ASSERT_EQ(interface_->spdy_version(), SPDY4);
315 TEST_P(SpdySMProxyTest, PostAcceptHook) {
316 interface_->PostAcceptHook();
318 ASSERT_EQ(1u, connection_->output_list()->size());
319 std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin();
320 DataFrame* df = *i++;
323 InSequence s;
324 EXPECT_CALL(*spdy_framer_visitor_, OnSettings(false));
325 EXPECT_CALL(*spdy_framer_visitor_,
326 OnSetting(SETTINGS_MAX_CONCURRENT_STREAMS, 0u, 100u));
328 spdy_framer_->ProcessInput(df->data, df->size);
331 TEST_P(SpdySMProxyTest, NewStream) {
332 // TODO(yhirano): SpdySM::NewStream leads to crash when
333 // acceptor_->flip_handler_type_ != FLIP_HANDLER_SPDY_SERVER.
334 // It should be fixed though I don't know the solution now.
337 TEST_P(SpdySMProxyTest, AddToOutputOrder) {
338 uint32 stream_id = 13;
339 MemCacheIter mci;
340 mci.stream_id = stream_id;
343 BalsaHeaders headers;
344 std::string filename = "foobar";
345 memory_cache_->InsertFile(&headers, filename, "");
346 mci.file_data = memory_cache_->GetFileData(filename);
349 interface_->AddToOutputOrder(mci);
350 ASSERT_TRUE(HasStream(stream_id));
353 TEST_P(SpdySMProxyTest, SendErrorNotFound) {
354 uint32 stream_id = 82;
355 SpdyHeaderBlock actual_header_block;
356 const char* actual_data;
357 size_t actual_size;
358 testing::MockFunction<void(int)> checkpoint; // NOLINT
360 interface_->SendErrorNotFound(stream_id);
362 ASSERT_EQ(2u, connection_->output_list()->size());
365 InSequence s;
366 if (GetParam() < SPDY4) {
367 EXPECT_CALL(*spdy_framer_visitor_,
368 OnSynReply(stream_id, false, _))
369 .WillOnce(SaveArg<2>(&actual_header_block));
370 } else {
371 EXPECT_CALL(*spdy_framer_visitor_,
372 OnHeaders(stream_id, false, 0, false, _))
373 .WillOnce(SaveArg<4>(&actual_header_block));
375 EXPECT_CALL(checkpoint, Call(0));
376 EXPECT_CALL(*spdy_framer_visitor_,
377 OnDataFrameHeader(stream_id, _, true));
378 EXPECT_CALL(*spdy_framer_visitor_,
379 OnStreamFrameData(stream_id, _, _, false)).Times(1)
380 .WillOnce(DoAll(SaveArg<1>(&actual_data),
381 SaveArg<2>(&actual_size)));
382 EXPECT_CALL(*spdy_framer_visitor_,
383 OnStreamFrameData(stream_id, NULL, 0, true)).Times(1);
386 std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin();
387 DataFrame* df = *i++;
388 spdy_framer_->ProcessInput(df->data, df->size);
389 checkpoint.Call(0);
390 df = *i++;
391 spdy_framer_->ProcessInput(df->data, df->size);
393 ASSERT_EQ(2, spdy_framer_->frames_received());
394 ASSERT_EQ(2u, actual_header_block.size());
395 ASSERT_EQ("404 Not Found", actual_header_block[":status"]);
396 ASSERT_EQ("HTTP/1.1", actual_header_block[":version"]);
397 ASSERT_EQ("wtf?", StringPiece(actual_data, actual_size));
400 TEST_P(SpdySMProxyTest, SendSynStream) {
401 uint32 stream_id = 82;
402 BalsaHeaders headers;
403 SpdyHeaderBlock actual_header_block;
404 headers.AppendHeader("key1", "value1");
405 headers.AppendHeader("Host", "www.example.com");
406 headers.SetRequestFirstlineFromStringPieces("GET", "/path", "HTTP/1.1");
408 interface_->SendSynStream(stream_id, headers);
410 ASSERT_EQ(1u, connection_->output_list()->size());
411 std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin();
412 DataFrame* df = *i++;
415 InSequence s;
416 EXPECT_CALL(*spdy_framer_visitor_,
417 OnSynStream(stream_id, 0, _, false, false, _))
418 .WillOnce(SaveArg<5>(&actual_header_block));
421 spdy_framer_->ProcessInput(df->data, df->size);
422 ASSERT_EQ(1, spdy_framer_->frames_received());
423 ASSERT_EQ(5u, actual_header_block.size());
424 ASSERT_EQ("GET", actual_header_block[":method"]);
425 ASSERT_EQ("HTTP/1.1", actual_header_block[":version"]);
426 ASSERT_EQ("/path", actual_header_block[":path"]);
427 ASSERT_EQ("www.example.com", actual_header_block[":host"]);
428 ASSERT_EQ("value1", actual_header_block["key1"]);
431 TEST_P(SpdySMProxyTest, SendSynReply) {
432 uint32 stream_id = 82;
433 BalsaHeaders headers;
434 SpdyHeaderBlock actual_header_block;
435 headers.AppendHeader("key1", "value1");
436 headers.SetResponseFirstlineFromStringPieces("HTTP/1.1", "200", "OK");
438 interface_->SendSynReply(stream_id, headers);
440 ASSERT_EQ(1u, connection_->output_list()->size());
441 std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin();
442 DataFrame* df = *i++;
445 InSequence s;
446 if (GetParam() < SPDY4) {
447 EXPECT_CALL(*spdy_framer_visitor_, OnSynReply(stream_id, false, _))
448 .WillOnce(SaveArg<2>(&actual_header_block));
449 } else {
450 EXPECT_CALL(*spdy_framer_visitor_,
451 OnHeaders(stream_id, false, 0, false, _))
452 .WillOnce(SaveArg<4>(&actual_header_block));
456 spdy_framer_->ProcessInput(df->data, df->size);
457 ASSERT_EQ(1, spdy_framer_->frames_received());
458 ASSERT_EQ(3u, actual_header_block.size());
459 ASSERT_EQ("200 OK", actual_header_block[":status"]);
460 ASSERT_EQ("HTTP/1.1", actual_header_block[":version"]);
461 ASSERT_EQ("value1", actual_header_block["key1"]);
464 TEST_P(SpdySMProxyTest, SendDataFrame) {
465 uint32 stream_id = 133;
466 SpdyDataFlags flags = DATA_FLAG_NONE;
467 const char* actual_data;
468 size_t actual_size;
470 interface_->SendDataFrame(stream_id, "hello", 5, flags, true);
472 ASSERT_EQ(1u, connection_->output_list()->size());
473 std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin();
474 DataFrame* df = *i++;
477 InSequence s;
478 EXPECT_CALL(*spdy_framer_visitor_,
479 OnDataFrameHeader(stream_id, _, false));
480 EXPECT_CALL(*spdy_framer_visitor_,
481 OnStreamFrameData(stream_id, _, _, false))
482 .WillOnce(DoAll(SaveArg<1>(&actual_data), SaveArg<2>(&actual_size)));
485 spdy_framer_->ProcessInput(df->data, df->size);
486 ASSERT_EQ(1, spdy_framer_->frames_received());
487 ASSERT_EQ("hello", StringPiece(actual_data, actual_size));
490 TEST_P(SpdySMProxyTest, SendLongDataFrame) {
491 uint32 stream_id = 133;
492 SpdyDataFlags flags = DATA_FLAG_NONE;
493 const char* actual_data;
494 size_t actual_size;
496 std::string data = std::string(kSpdySegmentSize, 'a') +
497 std::string(kSpdySegmentSize, 'b') + "c";
498 interface_->SendDataFrame(stream_id, data.data(), data.size(), flags, true);
501 InSequence s;
502 for (int i = 0; i < 3; ++i) {
503 EXPECT_CALL(*spdy_framer_visitor_,
504 OnDataFrameHeader(stream_id, _, false));
505 EXPECT_CALL(*spdy_framer_visitor_,
506 OnStreamFrameData(stream_id, _, _, false))
507 .WillOnce(DoAll(SaveArg<1>(&actual_data),
508 SaveArg<2>(&actual_size)));
512 ASSERT_EQ(3u, connection_->output_list()->size());
513 std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin();
514 DataFrame* df = *i++;
515 spdy_framer_->ProcessInput(df->data, df->size);
516 ASSERT_EQ(std::string(kSpdySegmentSize, 'a'),
517 StringPiece(actual_data, actual_size));
519 df = *i++;
520 spdy_framer_->ProcessInput(df->data, df->size);
521 ASSERT_EQ(std::string(kSpdySegmentSize, 'b'),
522 StringPiece(actual_data, actual_size));
524 df = *i++;
525 spdy_framer_->ProcessInput(df->data, df->size);
526 ASSERT_EQ("c", StringPiece(actual_data, actual_size));
529 TEST_P(SpdySMServerTest, OnSynStream) {
530 BufferedSpdyFramerVisitorInterface* visitor = interface_.get();
531 uint32 stream_id = 82;
532 SpdyHeaderBlock spdy_headers;
533 spdy_headers["url"] = "http://www.example.com/path";
534 spdy_headers["method"] = "GET";
535 spdy_headers["scheme"] = "http";
536 spdy_headers["version"] = "HTTP/1.1";
539 BalsaHeaders headers;
540 memory_cache_->InsertFile(&headers, "GET_/path", "");
542 visitor->OnSynStream(stream_id, 0, 0, true, true, spdy_headers);
543 ASSERT_TRUE(HasStream(stream_id));
546 TEST_P(SpdySMServerTest, NewStream) {
547 uint32 stream_id = 13;
548 std::string filename = "foobar";
551 BalsaHeaders headers;
552 memory_cache_->InsertFile(&headers, filename, "");
555 interface_->NewStream(stream_id, 0, filename);
556 ASSERT_TRUE(HasStream(stream_id));
559 TEST_P(SpdySMServerTest, NewStreamError) {
560 uint32 stream_id = 82;
561 SpdyHeaderBlock actual_header_block;
562 const char* actual_data;
563 size_t actual_size;
564 testing::MockFunction<void(int)> checkpoint; // NOLINT
566 interface_->NewStream(stream_id, 0, "nonexistingfile");
568 ASSERT_EQ(2u, connection_->output_list()->size());
571 InSequence s;
572 if (GetParam() < SPDY4) {
573 EXPECT_CALL(*spdy_framer_visitor_, OnSynReply(stream_id, false, _))
574 .WillOnce(SaveArg<2>(&actual_header_block));
575 } else {
576 EXPECT_CALL(*spdy_framer_visitor_,
577 OnHeaders(stream_id, false, 0, false, _))
578 .WillOnce(SaveArg<4>(&actual_header_block));
580 EXPECT_CALL(checkpoint, Call(0));
581 EXPECT_CALL(*spdy_framer_visitor_,
582 OnDataFrameHeader(stream_id, _, true));
583 EXPECT_CALL(*spdy_framer_visitor_,
584 OnStreamFrameData(stream_id, _, _, false)).Times(1)
585 .WillOnce(DoAll(SaveArg<1>(&actual_data),
586 SaveArg<2>(&actual_size)));
587 EXPECT_CALL(*spdy_framer_visitor_,
588 OnStreamFrameData(stream_id, NULL, 0, true)).Times(1);
591 std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin();
592 DataFrame* df = *i++;
593 spdy_framer_->ProcessInput(df->data, df->size);
594 checkpoint.Call(0);
595 df = *i++;
596 spdy_framer_->ProcessInput(df->data, df->size);
598 ASSERT_EQ(2, spdy_framer_->frames_received());
599 ASSERT_EQ(2u, actual_header_block.size());
600 ASSERT_EQ("404 Not Found", actual_header_block["status"]);
601 ASSERT_EQ("HTTP/1.1", actual_header_block["version"]);
602 ASSERT_EQ("wtf?", StringPiece(actual_data, actual_size));
605 } // namespace
607 } // namespace net