aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/testing/unittest/tests_data.h
blob: 14ea88eb7ca6ca2e38c336b67d161597e1eaf7b8 (plain) (blame)
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
#pragma once

#include <library/cpp/testing/common/env.h>

#include <util/generic/noncopyable.h>
#include <util/generic/ptr.h>
#include <util/generic/string.h> 
#include <util/network/sock.h>

class TInet6StreamSocket;

// set two options: SO_REUSEADDR and SO_REUSEPORT, both are required for
// correct implementation of TPortManager because of different operating systems
// incompatibility: singe SO_REUSEADDR is enough for Linux, but not enough for Darwin
template <class TSocketType>
void SetReuseAddressAndPort(const TSocketType& sock) {
    const int retAddr = SetSockOpt(sock, SOL_SOCKET, SO_REUSEADDR, 1);
    if (retAddr < 0) {
        ythrow yexception() << "can't set SO_REUSEADDR: " << LastSystemErrorText(-retAddr);
    }

#ifdef SO_REUSEPORT
    const int retPort = SetSockOpt(sock, SOL_SOCKET, SO_REUSEPORT, 1);
    if (retPort < 0) {
        ythrow yexception() << "can't set SO_REUSEPORT: " << LastSystemErrorText(-retPort);
    }
#endif
}

class TPortManager: public TNonCopyable {
public:
    TPortManager(bool reservePortsForCurrentTest = true);
    ~TPortManager();

    // Gets free TCP port
    ui16 GetPort(ui16 port = 0);

    // Gets free TCP port
    ui16 GetTcpPort(ui16 port = 0);

    // Gets free UDP port
    ui16 GetUdpPort(ui16 port = 0);

    // Gets one free port for use in both TCP and UDP protocols
    ui16 GetTcpAndUdpPort(ui16 port = 0);

    ui16 GetPortsRange(const ui16 startPort, const ui16 range);

private:
    class TPortManagerImpl;
    THolder<TPortManagerImpl> Impl_;
};

ui16 GetRandomPort();