Index: net/tools/quic/quic_server_test.cc |
diff --git a/net/tools/quic/quic_server_test.cc b/net/tools/quic/quic_server_test.cc |
index d9acf8658f81ae168c436414335b3a37f0bc7eed..4d99cff5ac627e908844fa4a1cbe7b474258a392 100644 |
--- a/net/tools/quic/quic_server_test.cc |
+++ b/net/tools/quic/quic_server_test.cc |
@@ -11,6 +11,7 @@ |
#include "net/tools/quic/quic_epoll_alarm_factory.h" |
#include "net/tools/quic/quic_epoll_connection_helper.h" |
#include "net/tools/quic/quic_simple_server_session_helper.h" |
+#include "net/tools/quic/test_tools/quic_server_peer.h" |
#include "testing/gtest/include/gtest/gtest.h" |
using ::testing::_; |
@@ -22,6 +23,120 @@ namespace test { |
namespace { |
+class MockQuicSimpleDispatcher : public QuicSimpleDispatcher { |
+ public: |
+ MockQuicSimpleDispatcher( |
+ const QuicConfig& config, |
+ const QuicCryptoServerConfig* crypto_config, |
+ QuicVersionManager* version_manager, |
+ std::unique_ptr<QuicConnectionHelperInterface> helper, |
+ std::unique_ptr<QuicServerSessionBase::Helper> session_helper, |
+ std::unique_ptr<QuicAlarmFactory> alarm_factory) |
+ : QuicSimpleDispatcher(config, |
+ crypto_config, |
+ version_manager, |
+ std::move(helper), |
+ std::move(session_helper), |
+ std::move(alarm_factory)) {} |
+ ~MockQuicSimpleDispatcher() override {} |
+ |
+ MOCK_METHOD0(OnCanWrite, void()); |
+ MOCK_CONST_METHOD0(HasPendingWrites, bool()); |
+ MOCK_CONST_METHOD0(HasChlosBuffered, bool()); |
+ MOCK_METHOD1(ProcessBufferedChlos, void(size_t)); |
+}; |
+ |
+class TestQuicServer : public QuicServer { |
+ public: |
+ TestQuicServer() : QuicServer(CryptoTestUtils::ProofSourceForTesting()) {} |
+ |
+ ~TestQuicServer() override {} |
+ |
+ MockQuicSimpleDispatcher* mock_dispatcher() { return mock_dispatcher_; } |
+ |
+ protected: |
+ QuicDispatcher* CreateQuicDispatcher() override { |
+ mock_dispatcher_ = new MockQuicSimpleDispatcher( |
+ config(), &crypto_config(), version_manager(), |
+ std::unique_ptr<QuicEpollConnectionHelper>( |
+ new QuicEpollConnectionHelper(epoll_server(), |
+ QuicAllocator::BUFFER_POOL)), |
+ std::unique_ptr<QuicServerSessionBase::Helper>( |
+ new QuicSimpleServerSessionHelper(QuicRandom::GetInstance())), |
+ std::unique_ptr<QuicEpollAlarmFactory>( |
+ new QuicEpollAlarmFactory(epoll_server()))); |
+ return mock_dispatcher_; |
+ } |
+ |
+ MockQuicSimpleDispatcher* mock_dispatcher_; |
+}; |
+ |
+class QuicServerEpollInTest : public ::testing::Test { |
+ public: |
+ QuicServerEpollInTest() |
+ : port_(net::test::kTestPort), server_address_(Loopback4(), port_) {} |
+ |
+ void StartListening() { |
+ server_.CreateUDPSocketAndListen(server_address_); |
+ ASSERT_TRUE(QuicServerPeer::SetSmallSocket(&server_)); |
+ |
+ if (!server_.overflow_supported()) { |
+ LOG(WARNING) << "Overflow not supported. Not testing."; |
+ return; |
+ } |
+ } |
+ |
+ protected: |
+ int port_; |
+ IPEndPoint server_address_; |
+ TestQuicServer server_; |
+}; |
+ |
+// Tests that if dispatcher has CHLOs waiting for connection creation, EPOLLIN |
+// event should try to create connections for them. And set epoll mask with |
+// EPOLLIN if there are still CHLOs remaining at the end of epoll event. |
+TEST_F(QuicServerEpollInTest, ProcessBufferedCHLOsOnEpollin) { |
+ FLAGS_quic_limit_num_new_sessions_per_epoll_loop = true; |
+ FLAGS_quic_buffer_packet_till_chlo = true; |
+ // Given an EPOLLIN event, try to create session for buffered CHLOs. In first |
+ // event, dispatcher can't create session for all of CHLOs. So listener should |
+ // register another EPOLLIN event by itself. Even without new packet arrival, |
+ // the rest CHLOs should be process in next epoll event. |
+ StartListening(); |
+ bool more_chlos = true; |
+ MockQuicSimpleDispatcher* dispatcher_ = server_.mock_dispatcher(); |
+ DCHECK(dispatcher_ != nullptr); |
+ EXPECT_CALL(*dispatcher_, OnCanWrite()).Times(testing::AnyNumber()); |
+ EXPECT_CALL(*dispatcher_, ProcessBufferedChlos(_)).Times(2); |
+ EXPECT_CALL(*dispatcher_, HasPendingWrites()).Times(testing::AnyNumber()); |
+ // Expect there are still CHLOs buffered after 1st event. But not any more |
+ // after 2nd event. |
+ EXPECT_CALL(*dispatcher_, HasChlosBuffered()) |
+ .WillOnce(testing::Return(true)) |
+ .WillOnce( |
+ DoAll(testing::Assign(&more_chlos, false), testing::Return(false))); |
+ |
+ // Send a packet to trigger epoll event. |
+ int fd = socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP); |
+ ASSERT_LT(0, fd); |
+ |
+ char buf[1024]; |
+ memset(buf, 0, arraysize(buf)); |
+ sockaddr_storage storage; |
+ socklen_t storage_size = sizeof(storage); |
+ ASSERT_TRUE(server_address_.ToSockAddr(reinterpret_cast<sockaddr*>(&storage), |
+ &storage_size)); |
+ int rc = sendto(fd, buf, arraysize(buf), 0, |
+ reinterpret_cast<sockaddr*>(&storage), storage_size); |
+ if (rc < 0) { |
+ DVLOG(1) << errno << " " << strerror(errno); |
+ } |
+ |
+ while (more_chlos) { |
+ server_.WaitForEvents(); |
+ } |
+} |
+ |
class QuicServerDispatchPacketTest : public ::testing::Test { |
public: |
QuicServerDispatchPacketTest() |