blob: dca06bddae203d6cc60cd0e23367ac7622f30f12 [file] [log] [blame]
// Copyright (c) 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/tools/quic/quic_client.h"
#include <dirent.h>
#include <stdio.h>
#include <memory>
#include "base/strings/string_util.h"
#include "net/quic/test_tools/crypto_test_utils.h"
#include "net/quic/test_tools/quic_test_utils.h"
#include "net/tools/epoll_server/epoll_server.h"
#include "net/tools/quic/test_tools/quic_client_peer.h"
#include "testing/gtest/include/gtest/gtest.h"
using net::EpollServer;
using net::test::CryptoTestUtils;
namespace net {
namespace test {
namespace {
int NumOpenFDs() {
int number_of_open_fds = 0;
char buf[256];
struct dirent* dp;
base::snprintf(buf, arraysize(buf), "/proc/%i/fd/", getpid());
DIR* dir = opendir(buf);
while ((dp = readdir(dir)) != NULL)
number_of_open_fds++;
closedir(dir);
return number_of_open_fds;
}
// Creates a new QuicClient and Initializes it. Caller is responsible for
// deletion.
QuicClient* CreateAndInitializeQuicClient(EpollServer* eps, uint16_t port) {
IPEndPoint server_address(IPEndPoint(net::test::Loopback4(), port));
QuicServerId server_id("hostname", server_address.port(),
PRIVACY_MODE_DISABLED);
QuicVersionVector versions = QuicSupportedVersions();
QuicClient* client =
new QuicClient(server_address, server_id, versions, eps,
CryptoTestUtils::ProofVerifierForTesting());
EXPECT_TRUE(client->Initialize());
return client;
}
TEST(QuicClientTest, DoNotLeakFDs) {
// Create a ProofVerifier before counting the number of open FDs to work
// around some ASAN weirdness.
delete CryptoTestUtils::ProofVerifierForTesting();
// Make sure that the QuicClient doesn't leak FDs. Doing so could cause port
// exhaustion in long running processes which repeatedly create clients.
// Record initial number of FDs, after creation of EpollServer.
EpollServer eps;
int number_of_open_fds = NumOpenFDs();
// Create a number of clients, initialize them, and verify this has resulted
// in additional FDs being opened.
const int kNumClients = 50;
for (int i = 0; i < kNumClients; ++i) {
std::unique_ptr<QuicClient> client(
CreateAndInitializeQuicClient(&eps, net::test::kTestPort + i));
// Initializing the client will create a new FD.
EXPECT_LT(number_of_open_fds, NumOpenFDs());
}
// The FDs created by the QuicClients should now be closed.
EXPECT_EQ(number_of_open_fds, NumOpenFDs());
}
TEST(QuicClientTest, CreateAndCleanUpUDPSockets) {
// Create a ProofVerifier before counting the number of open FDs to work
// around some ASAN weirdness.
delete CryptoTestUtils::ProofVerifierForTesting();
EpollServer eps;
int number_of_open_fds = NumOpenFDs();
std::unique_ptr<QuicClient> client(
CreateAndInitializeQuicClient(&eps, net::test::kTestPort));
EXPECT_EQ(number_of_open_fds + 1, NumOpenFDs());
// Create more UDP sockets.
EXPECT_TRUE(QuicClientPeer::CreateUDPSocketAndBind(client.get()));
EXPECT_EQ(number_of_open_fds + 2, NumOpenFDs());
EXPECT_TRUE(QuicClientPeer::CreateUDPSocketAndBind(client.get()));
EXPECT_EQ(number_of_open_fds + 3, NumOpenFDs());
// Clean up UDP sockets.
QuicClientPeer::CleanUpUDPSocket(client.get(), client->GetLatestFD());
EXPECT_EQ(number_of_open_fds + 2, NumOpenFDs());
QuicClientPeer::CleanUpUDPSocket(client.get(), client->GetLatestFD());
EXPECT_EQ(number_of_open_fds + 1, NumOpenFDs());
}
} // namespace
} // namespace test
} // namespace net