/work/auto_tests/tox_many_tcp_test.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Auto Tests: Many TCP. |
2 | | */ |
3 | | |
4 | | #include <stdio.h> |
5 | | #include <string.h> |
6 | | #include <time.h> |
7 | | |
8 | | #include "../testing/misc_tools.h" |
9 | | #include "../toxcore/crypto_core.h" |
10 | | #include "../toxcore/os_random.h" |
11 | | #include "../toxcore/tox.h" |
12 | | #include "auto_test_support.h" |
13 | | #include "check_compat.h" |
14 | | |
15 | | #ifndef USE_IPV6 |
16 | | #define USE_IPV6 1 |
17 | | #endif |
18 | | |
19 | | #ifdef TOX_LOCALHOST |
20 | | #undef TOX_LOCALHOST |
21 | | #endif |
22 | | #if USE_IPV6 |
23 | | #define TOX_LOCALHOST "::1" |
24 | | #else |
25 | | #define TOX_LOCALHOST "127.0.0.1" |
26 | | #endif |
27 | | |
28 | | typedef struct State { |
29 | | uint32_t to_comp; |
30 | | Tox *tox; |
31 | | } State; |
32 | | |
33 | | static bool enable_broken_tests = false; |
34 | | |
35 | | static void accept_friend_request(const Tox_Event_Friend_Request *event, void *userdata) |
36 | 50 | { |
37 | 50 | State *state = (State *)userdata; |
38 | | |
39 | 50 | const uint8_t *public_key = tox_event_friend_request_get_public_key(event); |
40 | 50 | const uint8_t *message = tox_event_friend_request_get_message(event); |
41 | 50 | const uint32_t message_length = tox_event_friend_request_get_message_length(event); |
42 | | |
43 | 50 | if (state->to_comp != 974536) { |
44 | 0 | return; |
45 | 0 | } |
46 | | |
47 | 50 | if (message_length == 7 && memcmp("Gentoo", message, 7) == 0) { |
48 | 50 | tox_friend_add_norequest(state->tox, public_key, nullptr); |
49 | 50 | } |
50 | 50 | } |
51 | | |
52 | 200 | #define NUM_FRIENDS 50 |
53 | 12.4k | #define NUM_TOXES_TCP 40 |
54 | | |
55 | | static uint16_t tcp_relay_port = 33448; |
56 | | |
57 | | static void test_many_clients_tcp(void) |
58 | 1 | { |
59 | 1 | const Random *rng = os_random(); |
60 | 1 | ck_assert(rng != nullptr); |
61 | 1 | long long unsigned int cur_time = time(nullptr); |
62 | 1 | Tox *toxes[NUM_TOXES_TCP]; |
63 | 1 | uint32_t index[NUM_TOXES_TCP]; |
64 | 1 | uint32_t to_comp = 974536; |
65 | | |
66 | 41 | for (uint32_t i = 0; i < NUM_TOXES_TCP; ++i) { |
67 | 40 | struct Tox_Options *opts = tox_options_new(nullptr); |
68 | | |
69 | 40 | if (i == 0) { |
70 | 1 | tox_options_set_tcp_port(opts, tcp_relay_port); |
71 | 39 | } else { |
72 | 39 | tox_options_set_udp_enabled(opts, false); |
73 | 39 | } |
74 | | |
75 | 40 | index[i] = i + 1; |
76 | 40 | Tox_Err_New err; |
77 | 40 | toxes[i] = tox_new_log(opts, &err, &index[i]); |
78 | 40 | if (i == 0 && err == TOX_ERR_NEW_PORT_ALLOC) { |
79 | 0 | ck_assert(toxes[i] == nullptr); |
80 | 0 | --i; |
81 | 0 | ++tcp_relay_port; |
82 | 0 | tox_options_free(opts); |
83 | 0 | continue; |
84 | 0 | } |
85 | 40 | ck_assert_msg(toxes[i] != nullptr, "Failed to create tox instances %u", i); |
86 | 40 | tox_events_init(toxes[i]); |
87 | 40 | uint8_t dpk[TOX_PUBLIC_KEY_SIZE]; |
88 | 40 | tox_self_get_dht_id(toxes[0], dpk); |
89 | 40 | Tox_Err_Bootstrap error; |
90 | 40 | ck_assert_msg(tox_add_tcp_relay(toxes[i], TOX_LOCALHOST, tcp_relay_port, dpk, &error), "add relay error, %u, %u", i, |
91 | 40 | error); |
92 | 40 | uint16_t first_port = tox_self_get_udp_port(toxes[0], nullptr); |
93 | 40 | ck_assert_msg(tox_bootstrap(toxes[i], TOX_LOCALHOST, first_port, dpk, nullptr), "Bootstrap error"); |
94 | | |
95 | 40 | tox_options_free(opts); |
96 | 40 | } |
97 | | |
98 | 1 | Tox_Dispatch *dispatch = tox_dispatch_new(nullptr); |
99 | 1 | ck_assert(dispatch != nullptr); |
100 | | |
101 | 1 | tox_events_callback_friend_request(dispatch, accept_friend_request); |
102 | | |
103 | 1 | struct { |
104 | 1 | uint16_t tox1; |
105 | 1 | uint16_t tox2; |
106 | 1 | } pairs[NUM_FRIENDS]; |
107 | | |
108 | 1 | uint8_t address[TOX_ADDRESS_SIZE]; |
109 | | |
110 | 51 | for (uint32_t i = 0; i < NUM_FRIENDS; ++i) { |
111 | 50 | loop_top: |
112 | 50 | pairs[i].tox1 = random_u32(rng) % NUM_TOXES_TCP; |
113 | 50 | pairs[i].tox2 = (pairs[i].tox1 + random_u32(rng) % (NUM_TOXES_TCP - 1) + 1) % NUM_TOXES_TCP; |
114 | | |
115 | 1.27k | for (uint32_t j = 0; j < i; ++j) { |
116 | 1.22k | if (pairs[j].tox2 == pairs[i].tox1 && pairs[j].tox1 == pairs[i].tox2) { |
117 | 0 | goto loop_top; |
118 | 0 | } |
119 | 1.22k | } |
120 | | |
121 | 50 | tox_self_get_address(toxes[pairs[i].tox1], address); |
122 | | |
123 | 50 | Tox_Err_Friend_Add test; |
124 | 50 | uint32_t num = tox_friend_add(toxes[pairs[i].tox2], address, (const uint8_t *)"Gentoo", 7, &test); |
125 | | |
126 | 50 | if (test == TOX_ERR_FRIEND_ADD_ALREADY_SENT) { |
127 | 0 | goto loop_top; |
128 | 0 | } |
129 | | |
130 | 50 | ck_assert_msg(num != UINT32_MAX && test == TOX_ERR_FRIEND_ADD_OK, "Failed to add friend error code: %u", test); |
131 | 50 | } |
132 | | |
133 | 149 | while (true) { |
134 | 149 | uint16_t counter = 0; |
135 | | |
136 | 6.10k | for (uint32_t i = 0; i < NUM_TOXES_TCP; ++i) { |
137 | 14.3k | for (uint32_t j = 0; j < tox_self_get_friend_list_size(toxes[i]); ++j) { |
138 | 8.41k | if (tox_friend_get_connection_status(toxes[i], j, nullptr) == TOX_CONNECTION_TCP) { |
139 | 297 | ++counter; |
140 | 297 | } |
141 | 8.41k | } |
142 | 5.96k | } |
143 | | |
144 | 149 | if (counter == NUM_FRIENDS * 2) { |
145 | 1 | break; |
146 | 1 | } |
147 | | |
148 | 6.06k | for (uint32_t i = 0; i < NUM_TOXES_TCP; ++i) { |
149 | 5.92k | Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK; |
150 | 5.92k | Tox_Events *events = tox_events_iterate(toxes[i], true, &err); |
151 | 5.92k | ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK); |
152 | 5.92k | State state = {to_comp, toxes[i]}; |
153 | 5.92k | tox_dispatch_invoke(dispatch, events, &state); |
154 | 5.92k | tox_events_free(events); |
155 | 5.92k | } |
156 | | |
157 | 148 | c_sleep(50); |
158 | 148 | } |
159 | | |
160 | 1 | tox_dispatch_free(dispatch); |
161 | 41 | for (uint32_t i = 0; i < NUM_TOXES_TCP; ++i) { |
162 | 40 | tox_kill(toxes[i]); |
163 | 40 | } |
164 | | |
165 | 1 | printf("test_many_clients_tcp succeeded, took %llu seconds\n", time(nullptr) - cur_time); |
166 | 1 | } |
167 | | |
168 | 0 | #define NUM_TCP_RELAYS 3 |
169 | | |
170 | | static void test_many_clients_tcp_b(void) |
171 | 0 | { |
172 | 0 | const Random *rng = os_random(); |
173 | 0 | ck_assert(rng != nullptr); |
174 | 0 | long long unsigned int cur_time = time(nullptr); |
175 | 0 | Tox *toxes[NUM_TOXES_TCP]; |
176 | 0 | uint32_t index[NUM_TOXES_TCP]; |
177 | 0 | uint32_t to_comp = 974536; |
178 | |
|
179 | 0 | for (uint32_t i = 0; i < NUM_TOXES_TCP; ++i) { |
180 | 0 | struct Tox_Options *opts = tox_options_new(nullptr); |
181 | |
|
182 | 0 | if (i < NUM_TCP_RELAYS) { |
183 | 0 | tox_options_set_tcp_port(opts, tcp_relay_port + i); |
184 | 0 | } else { |
185 | 0 | tox_options_set_udp_enabled(opts, 0); |
186 | 0 | } |
187 | |
|
188 | 0 | index[i] = i + 1; |
189 | 0 | toxes[i] = tox_new_log(opts, nullptr, &index[i]); |
190 | 0 | ck_assert_msg(toxes[i] != nullptr, "Failed to create tox instances %u", i); |
191 | 0 | tox_events_init(toxes[i]); |
192 | 0 | uint8_t dpk[TOX_PUBLIC_KEY_SIZE]; |
193 | 0 | tox_self_get_dht_id(toxes[(i % NUM_TCP_RELAYS)], dpk); |
194 | 0 | ck_assert_msg(tox_add_tcp_relay(toxes[i], TOX_LOCALHOST, tcp_relay_port + (i % NUM_TCP_RELAYS), dpk, nullptr), |
195 | 0 | "add relay error"); |
196 | 0 | tox_self_get_dht_id(toxes[0], dpk); |
197 | 0 | uint16_t first_port = tox_self_get_udp_port(toxes[0], nullptr); |
198 | 0 | ck_assert_msg(tox_bootstrap(toxes[i], TOX_LOCALHOST, first_port, dpk, nullptr), "Bootstrap error"); |
199 | | |
200 | 0 | tox_options_free(opts); |
201 | 0 | } |
202 | | |
203 | 0 | Tox_Dispatch *dispatch = tox_dispatch_new(nullptr); |
204 | 0 | ck_assert(dispatch != nullptr); |
205 | | |
206 | 0 | tox_events_callback_friend_request(dispatch, accept_friend_request); |
207 | |
|
208 | 0 | struct { |
209 | 0 | uint16_t tox1; |
210 | 0 | uint16_t tox2; |
211 | 0 | } pairs[NUM_FRIENDS]; |
212 | |
|
213 | 0 | uint8_t address[TOX_ADDRESS_SIZE]; |
214 | |
|
215 | 0 | for (uint32_t i = 0; i < NUM_FRIENDS; ++i) { |
216 | 0 | loop_top: |
217 | 0 | pairs[i].tox1 = random_u32(rng) % NUM_TOXES_TCP; |
218 | 0 | pairs[i].tox2 = (pairs[i].tox1 + random_u32(rng) % (NUM_TOXES_TCP - 1) + 1) % NUM_TOXES_TCP; |
219 | |
|
220 | 0 | for (uint32_t j = 0; j < i; ++j) { |
221 | 0 | if (pairs[j].tox2 == pairs[i].tox1 && pairs[j].tox1 == pairs[i].tox2) { |
222 | 0 | goto loop_top; |
223 | 0 | } |
224 | 0 | } |
225 | | |
226 | 0 | tox_self_get_address(toxes[pairs[i].tox1], address); |
227 | |
|
228 | 0 | Tox_Err_Friend_Add test; |
229 | 0 | uint32_t num = tox_friend_add(toxes[pairs[i].tox2], address, (const uint8_t *)"Gentoo", 7, &test); |
230 | |
|
231 | 0 | if (test == TOX_ERR_FRIEND_ADD_ALREADY_SENT) { |
232 | 0 | goto loop_top; |
233 | 0 | } |
234 | | |
235 | 0 | ck_assert_msg(num != UINT32_MAX && test == TOX_ERR_FRIEND_ADD_OK, "Failed to add friend error code: %u", test); |
236 | 0 | } |
237 | | |
238 | 0 | uint16_t last_count = 0; |
239 | |
|
240 | 0 | while (true) { |
241 | 0 | uint16_t counter = 0; |
242 | |
|
243 | 0 | for (uint32_t i = 0; i < NUM_TOXES_TCP; ++i) { |
244 | 0 | for (uint32_t j = 0; j < tox_self_get_friend_list_size(toxes[i]); ++j) { |
245 | 0 | if (tox_friend_get_connection_status(toxes[i], j, nullptr) == TOX_CONNECTION_TCP) { |
246 | 0 | ++counter; |
247 | 0 | } |
248 | 0 | } |
249 | 0 | } |
250 | |
|
251 | 0 | if (counter != last_count) { |
252 | 0 | printf("many_clients_tcp_b got to %u\n", counter); |
253 | 0 | last_count = counter; |
254 | 0 | } |
255 | |
|
256 | 0 | if (counter == NUM_FRIENDS * 2) { |
257 | 0 | break; |
258 | 0 | } |
259 | | |
260 | 0 | for (uint32_t i = 0; i < NUM_TOXES_TCP; ++i) { |
261 | 0 | Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK; |
262 | 0 | Tox_Events *events = tox_events_iterate(toxes[i], true, &err); |
263 | 0 | ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK); |
264 | 0 | State state = {to_comp, toxes[i]}; |
265 | 0 | tox_dispatch_invoke(dispatch, events, &state); |
266 | 0 | tox_events_free(events); |
267 | 0 | } |
268 | | |
269 | 0 | c_sleep(30); |
270 | 0 | } |
271 | | |
272 | 0 | tox_dispatch_free(dispatch); |
273 | 0 | for (uint32_t i = 0; i < NUM_TOXES_TCP; ++i) { |
274 | 0 | tox_kill(toxes[i]); |
275 | 0 | } |
276 | |
|
277 | 0 | printf("test_many_clients_tcp_b succeeded, took %llu seconds\n", time(nullptr) - cur_time); |
278 | 0 | } |
279 | | |
280 | | static void tox_suite(void) |
281 | 1 | { |
282 | | /* Each tox connects to a single tox TCP */ |
283 | 1 | test_many_clients_tcp(); |
284 | | |
285 | 1 | if (enable_broken_tests) { |
286 | | /* Try to make a connection to each "older sibling" tox instance via TCP */ |
287 | | /* Currently this test intermittently fails for unknown reasons. */ |
288 | 0 | test_many_clients_tcp_b(); |
289 | 0 | } |
290 | 1 | } |
291 | | |
292 | | int main(void) |
293 | 545 | { |
294 | 545 | setvbuf(stdout, nullptr, _IONBF, 0); |
295 | 545 | tox_suite(); |
296 | 545 | return 0; |
297 | 545 | } |