flush
[m6w6/libmemcached] / testing / lib / random.cpp
1 #include "testing/lib/random.hpp"
2 #include "testing/lib/Connection.hpp"
3
4 #include <chrono>
5 #include <random>
6
7 #include <unistd.h> // getpid()
8
9
10 template<typename T>
11 enable_if_t<is_integral_v<T>, T> random_num(T min, T max) {
12 using namespace chrono;
13 using rnd = mt19937;
14 using dst = uniform_int_distribution<T>;
15
16 auto time = duration_cast<microseconds>(system_clock::now().time_since_epoch());
17 auto seed = static_cast<rnd::result_type>(time.count() % numeric_limits<T>::max());
18 auto rgen = rnd{seed};
19 return dst(min, max)(rgen);
20 }
21
22 unsigned random_port() {
23 retry:
24 auto port = random_num(2<<9, 2<<15);
25 Connection conn(port);
26
27 if (!conn.open()) {
28 return port;
29 }
30 if (!conn.isOpen()) {
31 return port;
32 }
33 goto retry;
34 }
35
36 string random_socket(const string &prefix) {
37 return prefix + to_string(random_num(1U, UINT32_MAX)) + "@" + to_string(getpid()) + ".sock";
38 }
39
40 string random_socket_or_port_string(const string &what) {
41 if (what == "-s") {
42 return random_socket();
43 }
44
45 return to_string(random_port());
46 }
47
48 string random_socket_or_port_flag(const string &binary) {
49 (void) binary;
50 return random_num(0, 1) ? "-p" : "-s";
51 }
52
53 char random_ascii(char min, char max) {
54 return static_cast<char>(random_num(min, max));
55 }
56
57 string random_ascii_string(size_t len, char min, char max) {
58 string s;
59 s.reserve(len + 1);
60
61 for (size_t rem = 0; rem < len; ++rem) {
62 s += random_ascii(min, max);
63 }
64
65 s[len] = '\0';
66 assert(strlen(s.c_str()) == s.size());
67
68 return s;
69 }
70
71 pair<string, string> random_ascii_pair(size_t minlen, size_t maxlen) {
72 return {
73 random_ascii_string(random_num(minlen, maxlen)),
74 random_ascii_string(random_num(minlen, maxlen))
75 };
76 }
77