1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
|
#include <library/cpp/testing/common/env.h>
#include <library/cpp/testing/common/network.h>
#include <library/cpp/testing/common/scope.h>
#include <library/cpp/testing/gtest/gtest.h>
#include <util/generic/hash_set.h>
#include <util/folder/dirut.h>
#include <util/folder/path.h>
#include <util/folder/tempdir.h>
#include <util/generic/scope.h>
#include <util/network/sock.h>
#include <util/system/file.h>
#include <util/system/fs.h>
#include <util/system/sysstat.h>
class NetworkTestBase: public ::testing::Test {
protected:
void SetUp() override {
TmpDir.ConstructInPlace();
}
void TearDown() override {
TmpDir.Clear();
}
public:
TMaybe<TTempDir> TmpDir;
};
class NetworkTest: public NetworkTestBase {};
class FreePortTest: public NetworkTestBase {};
TEST_F(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) {
ports.push_back(NTesting::GetFreePort());
}
THashSet<ui16> uniqPorts;
for (auto& port : ports) {
const TString guardPath = TmpDir->Path() / ToString(static_cast<ui16>(port));
EXPECT_TRUE(NFs::Exists(guardPath));
EXPECT_TRUE(uniqPorts.emplace(port).second);
TInetStreamSocket sock;
TSockAddrInet addr(TIpHost{INADDR_ANY}, port);
ASSERT_EQ(0, SetSockOpt(sock, SOL_SOCKET, SO_REUSEADDR, 1));
EXPECT_EQ(0, sock.Bind(&addr));
}
ports.clear();
for (ui16 port : uniqPorts) {
const TString guardPath = TmpDir->Path() / ToString(port);
EXPECT_FALSE(NFs::Exists(guardPath));
}
}
TEST_F(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_F(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_F(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_F(NetworkTest, Permissions) {
constexpr ui16 loPort = 3456;
constexpr ui16 hiPort = 7654;
NTesting::TScopedEnvironment envGuard{{
{"PORT_SYNC_PATH", TmpDir->Name()},
{"VALID_PORT_RANGE", ToString(loPort) + ":" + ToString(hiPort)},
}};
NTesting::InitPortManagerFromEnv();
TVector<NTesting::TPortHolder> ports(Reserve(100));
for (ui64 port = loPort; port <= hiPort; ++port) {
const TString guardPath = TmpDir->Path() / ToString(static_cast<ui16>(port));
TFile f{guardPath, OpenAlways | RdOnly};
ASSERT_TRUE(f.IsOpen());
ASSERT_TRUE(Chmod(f.GetName().c_str(), 0444) != -1);
}
Y_DEFER {
Chmod(TmpDir->Path().c_str(), NFs::FP_COMMON_FILE);
};
ASSERT_TRUE(Chmod(TmpDir->Path().c_str(), 0555) != -1) << errno << " " << strerror(errno); // Lock dir
for (size_t i = 0; i < 100; ++i) {
NTesting::TPortHolder p;
EXPECT_NO_THROW(p = NTesting::GetFreePort());
ui16 port = p;
ASSERT_GE(port, 3456u);
ASSERT_LE(port, 7654u);
}
}
TEST_F(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);
ASSERT_EQ(i, ports.size());
for (ui16 j = 1; j < i; ++j) {
EXPECT_EQ(static_cast<ui16>(ports[j]), static_cast<ui16>(ports[0]) + j);
}
}
}
|