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