diff options
author | alexv-smirnov <alex@ydb.tech> | 2023-03-10 15:37:02 +0300 |
---|---|---|
committer | alexv-smirnov <alex@ydb.tech> | 2023-03-10 15:37:02 +0300 |
commit | 394219e982f65dd1ab4e4511051f4c97011c8712 (patch) | |
tree | d6a9c3984d7bac6e9564fa451bd28d6edcc063e3 /library/cpp/testing | |
parent | 7d576663c816bfaa02dcce5b6dfb8cfc3c7dec67 (diff) | |
download | ydb-394219e982f65dd1ab4e4511051f4c97011c8712.tar.gz |
Add GetPort(port) support to maintain compatibility with unittest TPortManager
Singleton did not allow reinitialisation, so in existing tests this line https://a.yandex-team.ru/arcadia/library/cpp/testing/common/ut/network_ut.cpp?rev=rXXXXXX#L45 did not have any effect. The tests worked just because in both tests the env var PORT_SYNC_PATH was the same and its changes did not affect the tests anyway.
As we need to change the env var NO_RANDOM_PORTS to run GetPort( port ) test, I had to make a reinitialisation method, which is now being called from inside the constructor, causing its double invocation during the tests. I could not find a better solution for Singleton(
Diffstat (limited to 'library/cpp/testing')
-rw-r--r-- | library/cpp/testing/common/network.cpp | 36 | ||||
-rw-r--r-- | library/cpp/testing/common/network.h | 7 | ||||
-rw-r--r-- | library/cpp/testing/common/ut/network_ut.cpp | 54 |
3 files changed, 89 insertions, 8 deletions
diff --git a/library/cpp/testing/common/network.cpp b/library/cpp/testing/common/network.cpp index 230c50ee6d..7a7ff2544c 100644 --- a/library/cpp/testing/common/network.cpp +++ b/library/cpp/testing/common/network.cpp @@ -96,27 +96,32 @@ namespace { static constexpr size_t Retries = 20; public: TPortManager() - : SyncDir_(GetEnv("PORT_SYNC_PATH")) - , Ranges_(GetPortRanges()) - , TotalCount_(0) { + InitFromEnv(); + } + + void InitFromEnv() { + SyncDir_ = TFsPath(GetEnv("PORT_SYNC_PATH")); if (!SyncDir_.IsDefined()) { - SyncDir_ = TFsPath(GetSystemTempDir()) / "yandex_port_locks"; + SyncDir_ = TFsPath(GetSystemTempDir()) / "testing_port_locks"; } Y_VERIFY(SyncDir_.IsDefined()); NFs::MakeDirectoryRecursive(SyncDir_); + Ranges_ = GetPortRanges(); + TotalCount_ = 0; for (auto [left, right] : Ranges_) { TotalCount_ += right - left; } Y_VERIFY(0 != TotalCount_); + + DisableRandomPorts_ = !GetEnv("NO_RANDOM_PORTS").empty(); } NTesting::TPortHolder GetFreePort() const { ui16 salt = RandomNumber<ui16>(); for (ui16 attempt = 0; attempt < TotalCount_; ++attempt) { ui16 probe = (salt + attempt) % TotalCount_; - for (auto [left, right] : Ranges_) { if (probe >= right - left) probe -= right - left; @@ -165,6 +170,17 @@ namespace { Y_FAIL("Cannot get range of %zu ports!", count); } + NTesting::TPortHolder GetPort(ui16 port) const { + if (port && DisableRandomPorts_) { + auto ackport = TryAcquirePort(port); + if (ackport) { + return NTesting::TPortHolder{std::move(ackport)}; + } + Y_FAIL("Cannot acquire port %hu!", port); + } + return GetFreePort(); + } + private: THolder<NTesting::IPort> TryAcquirePort(ui16 port) const { auto lock = MakeHolder<TFileLock>(TString(SyncDir_ / ::ToString(port))); @@ -178,7 +194,7 @@ namespace { TSockAddrInet6 addr("::", port); if (sock.Bind(&addr) != 0) { lock->Release(); - Y_VERIFY(EADDRINUSE == LastSystemError(), "unexpected error: %d", LastSystemError()); + Y_VERIFY(EADDRINUSE == LastSystemError(), "unexpected error: %d, port: %d", LastSystemError(), port); return nullptr; } return MakeHolder<TPortGuard>(port, std::move(lock)); @@ -188,15 +204,23 @@ namespace { TFsPath SyncDir_; TVector<std::pair<ui16, ui16>> Ranges_; size_t TotalCount_; + bool DisableRandomPorts_; }; } namespace NTesting { + void InitPortManagerFromEnv() { + Singleton<TPortManager>()->InitFromEnv(); + } + TPortHolder GetFreePort() { return Singleton<TPortManager>()->GetFreePort(); } namespace NLegacy { + TPortHolder GetPort( ui16 port ) { + return Singleton<TPortManager>()->GetPort(port); + } TVector<TPortHolder> GetFreePortsRange(size_t count) { return Singleton<TPortManager>()->GetFreePortsRange(count); } diff --git a/library/cpp/testing/common/network.h b/library/cpp/testing/common/network.h index eb4d32f3a1..4107145a7c 100644 --- a/library/cpp/testing/common/network.h +++ b/library/cpp/testing/common/network.h @@ -33,11 +33,16 @@ namespace NTesting { [[nodiscard]] TPortHolder GetFreePort(); namespace NLegacy { - // Do not use this method, it needs only for TPortManager from unittests. + // Do not use these methods made for Unittest TPortManager backward compatibility. // Returns continuous sequence of the specified number of ports. [[nodiscard]] TVector<TPortHolder> GetFreePortsRange(size_t count); + //@brief Returns port from parameter if NO_RANDOM_PORTS env var is set, otherwise first free port + [[nodiscard]] TPortHolder GetPort(ui16 port); } + //@brief Reinitialize singleton from environment vars for tests + void InitPortManagerFromEnv(); + //@brief helper class for inheritance struct TFreePortOwner { TFreePortOwner() : Port_(GetFreePort()) {} diff --git a/library/cpp/testing/common/ut/network_ut.cpp b/library/cpp/testing/common/ut/network_ut.cpp index 6a40775fd9..2016e26b09 100644 --- a/library/cpp/testing/common/ut/network_ut.cpp +++ b/library/cpp/testing/common/ut/network_ut.cpp @@ -15,7 +15,7 @@ static TTempDir TmpDir; TEST(NetworkTest, FreePort) { NTesting::TScopedEnvironment envGuard("PORT_SYNC_PATH", TmpDir.Name()); - + NTesting::InitPortManagerFromEnv(); TVector<NTesting::TPortHolder> ports(Reserve(100)); for (size_t i = 0; i < 100; ++i) { @@ -40,9 +40,61 @@ TEST(NetworkTest, FreePort) { } } +TEST(NetworkTest, FreePortWithinRanges) { + NTesting::TScopedEnvironment envGuard{{ + {"PORT_SYNC_PATH", TmpDir.Name()}, + {"VALID_PORT_RANGE", "3456:7654"}, + }}; + NTesting::InitPortManagerFromEnv(); + + for (size_t i = 0; i < 100; ++i) { + auto holder = NTesting::GetFreePort(); + ui16 port = holder; + ASSERT_GE(port, 3456u); + ASSERT_LE(port, 7654u); + } +} + +TEST(NetworkTest, GetPortRandom) { + NTesting::TScopedEnvironment envGuard{{ + {"PORT_SYNC_PATH", TmpDir.Name()}, + {"NO_RANDOM_PORTS", ""}, + }}; + NTesting::InitPortManagerFromEnv(); + + ui16 testPort = 80; // value just must be outside the assignable range + for (size_t i = 0; i < 10; ++i) { + NTesting::TPortHolder assigned = NTesting::NLegacy::GetPort(testPort); + ui16 assignedInt = assigned; + ASSERT_NE(testPort, assignedInt); + } +} + +TEST(NetworkTest, GetPortNonRandom) { + NTesting::TScopedEnvironment envGuard{{ + {"PORT_SYNC_PATH", TmpDir.Name()}, + {"NO_RANDOM_PORTS", "1"}, + }}; + NTesting::InitPortManagerFromEnv(); + + TVector<ui16> ports(Reserve(100)); // keep integers, we don't need the ports to remain allocated + + for (size_t i = 0; i < 10; ++i) { + auto portHolder = NTesting::GetFreePort(); + ports.push_back(portHolder); + } + + for (auto& testPort : ports) { + NTesting::TPortHolder assigned = NTesting::NLegacy::GetPort(testPort); + ui16 assignedInt = assigned; + ASSERT_EQ(testPort, assignedInt); + } +} + TEST(FreePortTest, FreePortsRange) { NTesting::TScopedEnvironment envGuard("PORT_SYNC_PATH", TmpDir.Name()); + NTesting::InitPortManagerFromEnv(); for (ui16 i = 2; i < 10; ++i) { TVector<NTesting::TPortHolder> ports = NTesting::NLegacy::GetFreePortsRange(i); |