summaryrefslogtreecommitdiff
path: root/auto_tests/tox_one_test.c
diff options
context:
space:
mode:
authoriphydf <iphydf@users.noreply.github.com>2016-09-27 09:40:29 +0100
committeriphydf <iphydf@users.noreply.github.com>2016-10-06 16:46:35 +0100
commitd9f37e4c3342d467920c295031bac58af6b92675 (patch)
treec28274c113944107651ddee30f94ca5c18aae2fe /auto_tests/tox_one_test.c
parent0fb79c54b8fefc2579c043bf88cfc42e30a30132 (diff)
Duplicate tox_test to 4 other files.
In a next step, we will remove tests from each file to have a per-binary split of tests. This will help identify which tests fail most often on Travis CI. In another future step, we will split the large one_test into several auto tests, which will make testing quite a bit slower (adding about 10 seconds setup time to each), but hopefully a lot more stable ("Tox went offline" should not happen as much anymore).
Diffstat (limited to 'auto_tests/tox_one_test.c')
-rw-r--r--auto_tests/tox_one_test.c1431
1 files changed, 1431 insertions, 0 deletions
diff --git a/auto_tests/tox_one_test.c b/auto_tests/tox_one_test.c
new file mode 100644
index 00000000..6ab03365
--- /dev/null
+++ b/auto_tests/tox_one_test.c
@@ -0,0 +1,1431 @@
1/* Auto Tests
2 *
3 * Tox Tests
4 *
5 * The following tests were written with a small Tox network in mind. Therefore,
6 * each test timeout was set to one for a small Tox Network. If connected to the
7 * 'Global' Tox Network, traversing the DHT would take MUCH longer than the
8 * timeouts allow. Because of this running these tests require NO other Tox
9 * clients running or accessible on/to localhost.
10 *
11 */
12
13#ifdef HAVE_CONFIG_H
14#include "config.h"
15#endif
16
17#include <check.h>
18#include <stdint.h>
19#include <stdio.h>
20#include <stdlib.h>
21#include <string.h>
22#include <sys/param.h>
23#include <sys/types.h>
24#include <time.h>
25#include <inttypes.h>
26
27#include "../toxcore/tox.h"
28#include "../toxcore/util.h"
29
30#include "helpers.h"
31
32#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
33#include <windows.h>
34#define c_sleep(x) Sleep(1*x)
35#else
36#include <unistd.h>
37#define c_sleep(x) usleep(1000*x)
38#endif
39
40/* The Travis-CI container responds poorly to ::1 as a localhost address
41 * You're encouraged to -D FORCE_TESTS_IPV6 on a local test */
42#ifdef FORCE_TESTS_IPV6
43#define TOX_LOCALHOST "::1"
44#else
45#define TOX_LOCALHOST "127.0.0.1"
46#endif
47
48static void accept_friend_request(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata)
49{
50 if (*((uint32_t *)userdata) != 974536) {
51 return;
52 }
53
54 if (length == 7 && memcmp("Gentoo", data, 7) == 0) {
55 tox_friend_add_norequest(m, public_key, 0);
56 }
57}
58static uint32_t messages_received;
59
60static void print_message(Tox *m, uint32_t friendnumber, TOX_MESSAGE_TYPE type, const uint8_t *string, size_t length,
61 void *userdata)
62{
63 if (*((uint32_t *)userdata) != 974536) {
64 return;
65 }
66
67 if (type != TOX_MESSAGE_TYPE_NORMAL) {
68 ck_abort_msg("Bad type");
69 }
70
71 uint8_t cmp_msg[TOX_MAX_MESSAGE_LENGTH];
72 memset(cmp_msg, 'G', sizeof(cmp_msg));
73
74 if (length == TOX_MAX_MESSAGE_LENGTH && memcmp(string, cmp_msg, sizeof(cmp_msg)) == 0) {
75 ++messages_received;
76 }
77}
78
79static uint32_t name_changes;
80
81static void print_nickchange(Tox *m, uint32_t friendnumber, const uint8_t *string, size_t length, void *userdata)
82{
83 if (*((uint32_t *)userdata) != 974536) {
84 return;
85 }
86
87 if (length == sizeof("Gentoo") && memcmp(string, "Gentoo", sizeof("Gentoo")) == 0) {
88 ++name_changes;
89 }
90}
91
92static uint32_t status_m_changes;
93static void print_status_m_change(Tox *tox, uint32_t friend_number, const uint8_t *message, size_t length,
94 void *user_data)
95{
96 if (*((uint32_t *)user_data) != 974536) {
97 return;
98 }
99
100 if (length == sizeof("Installing Gentoo") &&
101 memcmp(message, "Installing Gentoo", sizeof("Installing Gentoo")) == 0) {
102 ++status_m_changes;
103 }
104}
105
106static uint32_t typing_changes;
107
108static void print_typingchange(Tox *m, uint32_t friendnumber, bool typing, void *userdata)
109{
110 if (*((uint32_t *)userdata) != 974536) {
111 return;
112 }
113
114 if (!typing) {
115 typing_changes = 1;
116 } else {
117 typing_changes = 2;
118 }
119}
120
121static uint32_t custom_packet;
122
123static void handle_custom_packet(Tox *m, uint32_t friend_num, const uint8_t *data, size_t len, void *object)
124{
125 uint8_t number = *((uint32_t *)object);
126
127 if (len != TOX_MAX_CUSTOM_PACKET_SIZE) {
128 return;
129 }
130
131 uint8_t f_data[len];
132 memset(f_data, number, len);
133
134 if (memcmp(f_data, data, len) == 0) {
135 ++custom_packet;
136 } else {
137 ck_abort_msg("Custom packet fail. %u", number);
138 }
139
140 return;
141}
142
143static uint64_t size_recv;
144static uint64_t sending_pos;
145
146static uint8_t file_cmp_id[TOX_FILE_ID_LENGTH];
147static uint32_t file_accepted;
148static uint64_t file_size;
149static void tox_file_receive(Tox *tox, uint32_t friend_number, uint32_t file_number, uint32_t kind, uint64_t filesize,
150 const uint8_t *filename, size_t filename_length, void *userdata)
151{
152 if (*((uint32_t *)userdata) != 974536) {
153 return;
154 }
155
156 if (kind != TOX_FILE_KIND_DATA) {
157 ck_abort_msg("Bad kind");
158 return;
159 }
160
161 if (!(filename_length == sizeof("Gentoo.exe") && memcmp(filename, "Gentoo.exe", sizeof("Gentoo.exe")) == 0)) {
162 ck_abort_msg("Bad filename");
163 return;
164 }
165
166 uint8_t file_id[TOX_FILE_ID_LENGTH];
167
168 if (!tox_file_get_file_id(tox, friend_number, file_number, file_id, 0)) {
169 ck_abort_msg("tox_file_get_file_id error");
170 }
171
172 if (memcmp(file_id, file_cmp_id, TOX_FILE_ID_LENGTH) != 0) {
173 ck_abort_msg("bad file_id");
174 }
175
176 uint8_t empty[TOX_FILE_ID_LENGTH] = {0};
177
178 if (memcmp(empty, file_cmp_id, TOX_FILE_ID_LENGTH) == 0) {
179 ck_abort_msg("empty file_id");
180 }
181
182 file_size = filesize;
183
184 if (filesize) {
185 sending_pos = size_recv = 1337;
186
187 TOX_ERR_FILE_SEEK err_s;
188
189 if (!tox_file_seek(tox, friend_number, file_number, 1337, &err_s)) {
190 ck_abort_msg("tox_file_seek error");
191 }
192
193 ck_assert_msg(err_s == TOX_ERR_FILE_SEEK_OK, "tox_file_seek wrong error");
194 } else {
195 sending_pos = size_recv = 0;
196 }
197
198 TOX_ERR_FILE_CONTROL error;
199
200 if (tox_file_control(tox, friend_number, file_number, TOX_FILE_CONTROL_RESUME, &error)) {
201 ++file_accepted;
202 } else {
203 ck_abort_msg("tox_file_control failed. %i", error);
204 }
205
206 TOX_ERR_FILE_SEEK err_s;
207
208 if (tox_file_seek(tox, friend_number, file_number, 1234, &err_s)) {
209 ck_abort_msg("tox_file_seek no error");
210 }
211
212 ck_assert_msg(err_s == TOX_ERR_FILE_SEEK_DENIED, "tox_file_seek wrong error");
213}
214
215static uint32_t sendf_ok;
216static void file_print_control(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_CONTROL control,
217 void *userdata)
218{
219 if (*((uint32_t *)userdata) != 974536) {
220 return;
221 }
222
223 /* First send file num is 0.*/
224 if (file_number == 0 && control == TOX_FILE_CONTROL_RESUME) {
225 sendf_ok = 1;
226 }
227}
228
229static uint64_t max_sending;
230static bool m_send_reached;
231static uint8_t sending_num;
232static bool file_sending_done;
233static void tox_file_chunk_request(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position,
234 size_t length,
235 void *user_data)
236{
237 if (*((uint32_t *)user_data) != 974536) {
238 return;
239 }
240
241 if (!sendf_ok) {
242 ck_abort_msg("Didn't get resume control");
243 }
244
245 if (sending_pos != position) {
246 ck_abort_msg("Bad position %llu", position);
247 return;
248 }
249
250 if (length == 0) {
251 if (file_sending_done) {
252 ck_abort_msg("File sending already done.");
253 }
254
255 file_sending_done = 1;
256 return;
257 }
258
259 if (position + length > max_sending) {
260 if (m_send_reached) {
261 ck_abort_msg("Requested done file tranfer.");
262 }
263
264 length = max_sending - position;
265 m_send_reached = 1;
266 }
267
268 TOX_ERR_FILE_SEND_CHUNK error;
269 uint8_t f_data[length];
270 memset(f_data, sending_num, length);
271
272 if (tox_file_send_chunk(tox, friend_number, file_number, position, f_data, length, &error)) {
273 ++sending_num;
274 sending_pos += length;
275 } else {
276 ck_abort_msg("Could not send chunk %i", error);
277 }
278
279 if (error != TOX_ERR_FILE_SEND_CHUNK_OK) {
280 ck_abort_msg("Wrong error code");
281 }
282}
283
284
285static uint8_t num;
286static bool file_recv;
287static void write_file(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint64_t position, const uint8_t *data,
288 size_t length, void *user_data)
289{
290 if (*((uint32_t *)user_data) != 974536) {
291 return;
292 }
293
294 if (size_recv != position) {
295 ck_abort_msg("Bad position");
296 return;
297 }
298
299 if (length == 0) {
300 file_recv = 1;
301 return;
302 }
303
304 uint8_t f_data[length];
305 memset(f_data, num, length);
306 ++num;
307
308 if (memcmp(f_data, data, length) == 0) {
309 size_recv += length;
310 } else {
311 ck_abort_msg("FILE_CORRUPTED");
312 }
313}
314
315static unsigned int connected_t1;
316static void tox_connection_status(Tox *tox, TOX_CONNECTION connection_status, void *user_data)
317{
318 if (*((uint32_t *)user_data) != 974536) {
319 return;
320 }
321
322 if (connected_t1 && !connection_status) {
323 ck_abort_msg("Tox went offline");
324 }
325
326 ck_assert_msg(connection_status == TOX_CONNECTION_UDP, "wrong status %u", connection_status);
327
328 connected_t1 = connection_status;
329}
330
331START_TEST(test_one)
332{
333 {
334 TOX_ERR_OPTIONS_NEW o_err;
335 struct Tox_Options *o1 = tox_options_new(&o_err);
336 struct Tox_Options o2;
337 tox_options_default(&o2);
338 ck_assert_msg(o_err == TOX_ERR_OPTIONS_NEW_OK, "tox_options_new wrong error");
339 ck_assert_msg(memcmp(o1, &o2, sizeof(struct Tox_Options)) == 0, "tox_options_new error");
340 tox_options_free(o1);
341 }
342
343 Tox *tox1 = tox_new(0, 0);
344 Tox *tox2 = tox_new(0, 0);
345
346 {
347 TOX_ERR_GET_PORT error;
348 ck_assert_msg(tox_self_get_udp_port(tox1, &error) == 33445, "First Tox instance did not bind to udp port 33445.\n");
349 ck_assert_msg(error == TOX_ERR_GET_PORT_OK, "wrong error");
350 }
351
352 uint8_t address[TOX_ADDRESS_SIZE];
353 tox_self_get_address(tox1, address);
354 TOX_ERR_FRIEND_ADD error;
355 uint32_t ret = tox_friend_add(tox1, address, (const uint8_t *)"m", 1, &error);
356 ck_assert_msg(ret == UINT32_MAX && error == TOX_ERR_FRIEND_ADD_OWN_KEY, "Adding own address worked.");
357
358 tox_self_get_address(tox2, address);
359 uint8_t message[TOX_MAX_FRIEND_REQUEST_LENGTH + 1];
360 ret = tox_friend_add(tox1, address, NULL, 0, &error);
361 ck_assert_msg(ret == UINT32_MAX && error == TOX_ERR_FRIEND_ADD_NULL, "Sending request with no message worked.");
362 ret = tox_friend_add(tox1, address, message, 0, &error);
363 ck_assert_msg(ret == UINT32_MAX && error == TOX_ERR_FRIEND_ADD_NO_MESSAGE, "Sending request with no message worked.");
364 ret = tox_friend_add(tox1, address, message, sizeof(message), &error);
365 ck_assert_msg(ret == UINT32_MAX && error == TOX_ERR_FRIEND_ADD_TOO_LONG,
366 "TOX_MAX_FRIEND_REQUEST_LENGTH is too big.");
367
368 address[0]++;
369 ret = tox_friend_add(tox1, address, (const uint8_t *)"m", 1, &error);
370 ck_assert_msg(ret == UINT32_MAX && error == TOX_ERR_FRIEND_ADD_BAD_CHECKSUM,
371 "Adding address with bad checksum worked.");
372
373 tox_self_get_address(tox2, address);
374 ret = tox_friend_add(tox1, address, message, TOX_MAX_FRIEND_REQUEST_LENGTH, &error);
375 ck_assert_msg(ret == 0 && error == TOX_ERR_FRIEND_ADD_OK, "Failed to add friend.");
376 ret = tox_friend_add(tox1, address, message, TOX_MAX_FRIEND_REQUEST_LENGTH, &error);
377 ck_assert_msg(ret == UINT32_MAX && error == TOX_ERR_FRIEND_ADD_ALREADY_SENT, "Adding friend twice worked.");
378
379 uint8_t name[TOX_MAX_NAME_LENGTH];
380 int i;
381
382 for (i = 0; i < TOX_MAX_NAME_LENGTH; ++i) {
383 name[i] = rand();
384 }
385
386 tox_self_set_name(tox1, name, sizeof(name), 0);
387 ck_assert_msg(tox_self_get_name_size(tox1) == sizeof(name), "Can't set name of TOX_MAX_NAME_LENGTH");
388
389 tox_self_get_address(tox1, address);
390 size_t save_size = tox_get_savedata_size(tox1);
391 uint8_t data[save_size];
392 tox_get_savedata(tox1, data);
393
394 tox_kill(tox2);
395 TOX_ERR_NEW err_n;
396
397 struct Tox_Options options;
398 tox_options_default(&options);
399 options.savedata_type = TOX_SAVEDATA_TYPE_TOX_SAVE;
400 options.savedata_data = data;
401 options.savedata_length = save_size;
402 tox2 = tox_new(&options, &err_n);
403 ck_assert_msg(err_n == TOX_ERR_NEW_OK, "Load failed");
404
405 ck_assert_msg(tox_self_get_name_size(tox2) == sizeof name, "Wrong name size.");
406
407 uint8_t address2[TOX_ADDRESS_SIZE];
408 tox_self_get_address(tox2, address2);
409 ck_assert_msg(memcmp(address2, address, TOX_ADDRESS_SIZE) == 0, "Wrong address.");
410 uint8_t new_name[TOX_MAX_NAME_LENGTH] = { 0 };
411 tox_self_get_name(tox2, new_name);
412 ck_assert_msg(memcmp(name, new_name, TOX_MAX_NAME_LENGTH) == 0, "Wrong name");
413
414 uint8_t sk[TOX_SECRET_KEY_SIZE];
415 tox_self_get_secret_key(tox2, sk);
416 tox_kill(tox2);
417
418 tox_options_default(&options);
419 options.savedata_type = TOX_SAVEDATA_TYPE_SECRET_KEY;
420 options.savedata_data = sk;
421 options.savedata_length = sizeof(sk);
422 tox2 = tox_new(&options, &err_n);
423 ck_assert_msg(err_n == TOX_ERR_NEW_OK, "Load failed");
424 uint8_t address3[TOX_ADDRESS_SIZE];
425 tox_self_get_address(tox2, address3);
426 ck_assert_msg(memcmp(address3, address, TOX_PUBLIC_KEY_SIZE) == 0, "Wrong public key.");
427 uint8_t pk[TOX_PUBLIC_KEY_SIZE];
428 tox_self_get_public_key(tox2, pk);
429 ck_assert_msg(memcmp(pk, address, TOX_PUBLIC_KEY_SIZE) == 0, "Wrong public key.");
430
431 tox_kill(tox1);
432 tox_kill(tox2);
433}
434END_TEST
435
436START_TEST(test_few_clients)
437{
438 long long unsigned int con_time, cur_time = time(NULL);
439 TOX_ERR_NEW t_n_error;
440 Tox *tox1 = tox_new(0, &t_n_error);
441 ck_assert_msg(t_n_error == TOX_ERR_NEW_OK, "wrong error");
442 Tox *tox2 = tox_new(0, &t_n_error);
443 ck_assert_msg(t_n_error == TOX_ERR_NEW_OK, "wrong error");
444 Tox *tox3 = tox_new(0, &t_n_error);
445 ck_assert_msg(t_n_error == TOX_ERR_NEW_OK, "wrong error");
446
447 ck_assert_msg(tox1 && tox2 && tox3, "Failed to create 3 tox instances");
448
449 {
450 TOX_ERR_GET_PORT error;
451 ck_assert_msg(tox_self_get_udp_port(tox1, &error) == 33445, "First Tox instance did not bind to udp port 33445.\n");
452 ck_assert_msg(error == TOX_ERR_GET_PORT_OK, "wrong error");
453 }
454
455 {
456 TOX_ERR_GET_PORT error;
457 ck_assert_msg(tox_self_get_udp_port(tox2, &error) == 33446, "Second Tox instance did not bind to udp port 33446.\n");
458 ck_assert_msg(error == TOX_ERR_GET_PORT_OK, "wrong error");
459 }
460
461 {
462 TOX_ERR_GET_PORT error;
463 ck_assert_msg(tox_self_get_udp_port(tox3, &error) == 33447, "Third Tox instance did not bind to udp port 33447.\n");
464 ck_assert_msg(error == TOX_ERR_GET_PORT_OK, "wrong error");
465 }
466
467 uint32_t to_compare = 974536;
468 connected_t1 = 0;
469 tox_callback_self_connection_status(tox1, tox_connection_status);
470 tox_callback_friend_request(tox2, accept_friend_request);
471 uint8_t address[TOX_ADDRESS_SIZE];
472 tox_self_get_address(tox2, address);
473 uint32_t test = tox_friend_add(tox3, address, (const uint8_t *)"Gentoo", 7, 0);
474 ck_assert_msg(test == 0, "Failed to add friend error code: %i", test);
475
476 uint8_t off = 1;
477
478 while (1) {
479 tox_iterate(tox1, &to_compare);
480 tox_iterate(tox2, &to_compare);
481 tox_iterate(tox3, &to_compare);
482
483 if (tox_self_get_connection_status(tox1) && tox_self_get_connection_status(tox2)
484 && tox_self_get_connection_status(tox3)) {
485 if (off) {
486 printf("Toxes are online, took %llu seconds\n", time(NULL) - cur_time);
487 con_time = time(NULL);
488 off = 0;
489 }
490
491 if (tox_friend_get_connection_status(tox2, 0, 0) == TOX_CONNECTION_UDP
492 && tox_friend_get_connection_status(tox3, 0, 0) == TOX_CONNECTION_UDP) {
493 break;
494 }
495 }
496
497 c_sleep(50);
498 }
499
500 ck_assert_msg(connected_t1, "Tox1 isn't connected. %u", connected_t1);
501 printf("tox clients connected took %llu seconds\n", time(NULL) - con_time);
502 to_compare = 974536;
503 tox_callback_friend_message(tox3, print_message);
504 uint8_t msgs[TOX_MAX_MESSAGE_LENGTH + 1];
505 memset(msgs, 'G', sizeof(msgs));
506 TOX_ERR_FRIEND_SEND_MESSAGE errm;
507 tox_friend_send_message(tox2, 0, TOX_MESSAGE_TYPE_NORMAL, msgs, TOX_MAX_MESSAGE_LENGTH + 1, &errm);
508 ck_assert_msg(errm == TOX_ERR_FRIEND_SEND_MESSAGE_TOO_LONG, "TOX_MAX_MESSAGE_LENGTH is too small\n");
509 tox_friend_send_message(tox2, 0, TOX_MESSAGE_TYPE_NORMAL, msgs, TOX_MAX_MESSAGE_LENGTH, &errm);
510 ck_assert_msg(errm == TOX_ERR_FRIEND_SEND_MESSAGE_OK, "TOX_MAX_MESSAGE_LENGTH is too big\n");
511
512 while (1) {
513 messages_received = 0;
514 tox_iterate(tox1, &to_compare);
515 tox_iterate(tox2, &to_compare);
516 tox_iterate(tox3, &to_compare);
517
518 if (messages_received) {
519 break;
520 }
521
522 c_sleep(50);
523 }
524
525 printf("tox clients messaging succeeded\n");
526
527 unsigned int save_size1 = tox_get_savedata_size(tox2);
528 ck_assert_msg(save_size1 != 0 && save_size1 < 4096, "save is invalid size %u", save_size1);
529 printf("%u\n", save_size1);
530 uint8_t save1[save_size1];
531 tox_get_savedata(tox2, save1);
532 tox_kill(tox2);
533
534 struct Tox_Options options;
535 tox_options_default(&options);
536 options.savedata_type = TOX_SAVEDATA_TYPE_TOX_SAVE;
537 options.savedata_data = save1;
538 options.savedata_length = save_size1;
539 tox2 = tox_new(&options, NULL);
540 cur_time = time(NULL);
541 off = 1;
542
543 while (1) {
544 tox_iterate(tox1, &to_compare);
545 tox_iterate(tox2, &to_compare);
546 tox_iterate(tox3, &to_compare);
547
548 if (tox_self_get_connection_status(tox1) && tox_self_get_connection_status(tox2)
549 && tox_self_get_connection_status(tox3)) {
550 if (off) {
551 printf("Toxes are online again after reloading, took %llu seconds\n", time(NULL) - cur_time);
552 con_time = time(NULL);
553 off = 0;
554 }
555
556 if (tox_friend_get_connection_status(tox2, 0, 0) == TOX_CONNECTION_UDP
557 && tox_friend_get_connection_status(tox3, 0, 0) == TOX_CONNECTION_UDP) {
558 break;
559 }
560 }
561
562 c_sleep(50);
563 }
564
565 printf("tox clients connected took %llu seconds\n", time(NULL) - con_time);
566 tox_callback_friend_name(tox3, print_nickchange);
567 TOX_ERR_SET_INFO err_n;
568 bool succ = tox_self_set_name(tox2, (const uint8_t *)"Gentoo", sizeof("Gentoo"), &err_n);
569 ck_assert_msg(succ && err_n == TOX_ERR_SET_INFO_OK, "tox_self_set_name failed because %u\n", err_n);
570
571 while (1) {
572 name_changes = 0;
573 tox_iterate(tox1, &to_compare);
574 tox_iterate(tox2, &to_compare);
575 tox_iterate(tox3, &to_compare);
576
577 if (name_changes) {
578 break;
579 }
580
581 c_sleep(50);
582 }
583
584 ck_assert_msg(tox_friend_get_name_size(tox3, 0, 0) == sizeof("Gentoo"), "Name length not correct");
585 uint8_t temp_name[sizeof("Gentoo")];
586 tox_friend_get_name(tox3, 0, temp_name, 0);
587 ck_assert_msg(memcmp(temp_name, "Gentoo", sizeof("Gentoo")) == 0, "Name not correct");
588
589 tox_callback_friend_status_message(tox3, print_status_m_change);
590 succ = tox_self_set_status_message(tox2, (const uint8_t *)"Installing Gentoo", sizeof("Installing Gentoo"), &err_n);
591 ck_assert_msg(succ && err_n == TOX_ERR_SET_INFO_OK, "tox_self_set_status_message failed because %u\n", err_n);
592
593 while (1) {
594 status_m_changes = 0;
595 tox_iterate(tox1, &to_compare);
596 tox_iterate(tox2, &to_compare);
597 tox_iterate(tox3, &to_compare);
598
599 if (status_m_changes) {
600 break;
601 }
602
603 c_sleep(50);
604 }
605
606 ck_assert_msg(tox_friend_get_status_message_size(tox3, 0, 0) == sizeof("Installing Gentoo"),
607 "status message length not correct");
608 uint8_t temp_status_m[sizeof("Installing Gentoo")];
609 tox_friend_get_status_message(tox3, 0, temp_status_m, 0);
610 ck_assert_msg(memcmp(temp_status_m, "Installing Gentoo", sizeof("Installing Gentoo")) == 0,
611 "status message not correct");
612
613 tox_callback_friend_typing(tox2, &print_typingchange);
614 tox_self_set_typing(tox3, 0, 1, 0);
615
616 while (1) {
617 typing_changes = 0;
618 tox_iterate(tox1, &to_compare);
619 tox_iterate(tox2, &to_compare);
620 tox_iterate(tox3, &to_compare);
621
622 if (typing_changes == 2) {
623 break;
624 }
625
626 ck_assert_msg(typing_changes == 0, "Typing fail");
627
628 c_sleep(50);
629 }
630
631 ck_assert_msg(tox_friend_get_typing(tox2, 0, 0) == 1, "Typing fail");
632 tox_self_set_typing(tox3, 0, 0, 0);
633
634 while (1) {
635 typing_changes = 0;
636 tox_iterate(tox1, &to_compare);
637 tox_iterate(tox2, &to_compare);
638 tox_iterate(tox3, &to_compare);
639
640 if (typing_changes == 1) {
641 break;
642 }
643
644 ck_assert_msg(typing_changes == 0, "Typing fail");
645
646 c_sleep(50);
647 }
648
649 TOX_ERR_FRIEND_QUERY err_t;
650 ck_assert_msg(tox_friend_get_typing(tox2, 0, &err_t) == 0, "Typing fail");
651 ck_assert_msg(err_t == TOX_ERR_FRIEND_QUERY_OK, "Typing fail");
652
653 uint32_t packet_number = 160;
654 tox_callback_friend_lossless_packet(tox3, &handle_custom_packet);
655 uint8_t data_c[TOX_MAX_CUSTOM_PACKET_SIZE + 1];
656 memset(data_c, ((uint8_t)packet_number), sizeof(data_c));
657 int ret = tox_friend_send_lossless_packet(tox2, 0, data_c, sizeof(data_c), 0);
658 ck_assert_msg(ret == 0, "tox_friend_send_lossless_packet bigger fail %i", ret);
659 ret = tox_friend_send_lossless_packet(tox2, 0, data_c, TOX_MAX_CUSTOM_PACKET_SIZE, 0);
660 ck_assert_msg(ret == 1, "tox_friend_send_lossless_packet fail %i", ret);
661
662 while (1) {
663 custom_packet = 0;
664 tox_iterate(tox1, &to_compare);
665 tox_iterate(tox2, &to_compare);
666 tox_iterate(tox3, &packet_number);
667
668 if (custom_packet == 1) {
669 break;
670 }
671
672 ck_assert_msg(custom_packet == 0, "Lossless packet fail");
673
674 c_sleep(50);
675 }
676
677 packet_number = 200;
678 tox_callback_friend_lossy_packet(tox3, &handle_custom_packet);
679 memset(data_c, ((uint8_t)packet_number), sizeof(data_c));
680 ret = tox_friend_send_lossy_packet(tox2, 0, data_c, sizeof(data_c), 0);
681 ck_assert_msg(ret == 0, "tox_friend_send_lossy_packet bigger fail %i", ret);
682 ret = tox_friend_send_lossy_packet(tox2, 0, data_c, TOX_MAX_CUSTOM_PACKET_SIZE, 0);
683 ck_assert_msg(ret == 1, "tox_friend_send_lossy_packet fail %i", ret);
684
685 while (1) {
686 custom_packet = 0;
687 tox_iterate(tox1, &to_compare);
688 tox_iterate(tox2, &to_compare);
689 tox_iterate(tox3, &packet_number);
690
691 if (custom_packet == 1) {
692 break;
693 }
694
695 ck_assert_msg(custom_packet == 0, "lossy packet fail");
696
697 c_sleep(50);
698 }
699
700 printf("Starting file transfer test.\n");
701
702 file_accepted = file_size = sendf_ok = size_recv = 0;
703 file_recv = 0;
704 max_sending = UINT64_MAX;
705 long long unsigned int f_time = time(NULL);
706 tox_callback_file_recv_chunk(tox3, write_file);
707 tox_callback_file_recv_control(tox2, file_print_control);
708 tox_callback_file_chunk_request(tox2, tox_file_chunk_request);
709 tox_callback_file_recv_control(tox3, file_print_control);
710 tox_callback_file_recv(tox3, tox_file_receive);
711 uint64_t totalf_size = 100 * 1024 * 1024;
712 uint32_t fnum = tox_file_send(tox2, 0, TOX_FILE_KIND_DATA, totalf_size, 0, (const uint8_t *)"Gentoo.exe",
713 sizeof("Gentoo.exe"), 0);
714 ck_assert_msg(fnum != UINT32_MAX, "tox_new_file_sender fail");
715
716 TOX_ERR_FILE_GET gfierr;
717 ck_assert_msg(!tox_file_get_file_id(tox2, 1, fnum, file_cmp_id, &gfierr), "tox_file_get_file_id didn't fail");
718 ck_assert_msg(gfierr == TOX_ERR_FILE_GET_FRIEND_NOT_FOUND, "wrong error");
719 ck_assert_msg(!tox_file_get_file_id(tox2, 0, fnum + 1, file_cmp_id, &gfierr), "tox_file_get_file_id didn't fail");
720 ck_assert_msg(gfierr == TOX_ERR_FILE_GET_NOT_FOUND, "wrong error");
721 ck_assert_msg(tox_file_get_file_id(tox2, 0, fnum, file_cmp_id, &gfierr), "tox_file_get_file_id failed");
722 ck_assert_msg(gfierr == TOX_ERR_FILE_GET_OK, "wrong error");
723
724 while (1) {
725 tox_iterate(tox1, &to_compare);
726 tox_iterate(tox2, &to_compare);
727 tox_iterate(tox3, &to_compare);
728
729 if (file_sending_done) {
730 if (sendf_ok && file_recv && totalf_size == file_size && size_recv == file_size && sending_pos == size_recv
731 && file_accepted == 1) {
732 break;
733 }
734
735 ck_abort_msg("Something went wrong in file transfer %u %u %u %u %u %u %llu %llu %llu", sendf_ok, file_recv,
736 totalf_size == file_size, size_recv == file_size, sending_pos == size_recv, file_accepted == 1, totalf_size, size_recv,
737 sending_pos);
738 }
739
740 uint32_t tox1_interval = tox_iteration_interval(tox1);
741 uint32_t tox2_interval = tox_iteration_interval(tox2);
742 uint32_t tox3_interval = tox_iteration_interval(tox3);
743
744 c_sleep(MIN(tox1_interval, MIN(tox2_interval, tox3_interval)));
745 }
746
747 printf("100MB file sent in %llu seconds\n", time(NULL) - f_time);
748
749 printf("Starting file streaming transfer test.\n");
750
751 file_sending_done = file_accepted = file_size = sendf_ok = size_recv = 0;
752 file_recv = 0;
753 tox_callback_file_recv_chunk(tox3, write_file);
754 tox_callback_file_recv_control(tox2, file_print_control);
755 tox_callback_file_chunk_request(tox2, tox_file_chunk_request);
756 tox_callback_file_recv_control(tox3, file_print_control);
757 tox_callback_file_recv(tox3, tox_file_receive);
758 totalf_size = UINT64_MAX;
759 fnum = tox_file_send(tox2, 0, TOX_FILE_KIND_DATA, totalf_size, 0, (const uint8_t *)"Gentoo.exe", sizeof("Gentoo.exe"),
760 0);
761 ck_assert_msg(fnum != UINT32_MAX, "tox_new_file_sender fail");
762
763 ck_assert_msg(!tox_file_get_file_id(tox2, 1, fnum, file_cmp_id, &gfierr), "tox_file_get_file_id didn't fail");
764 ck_assert_msg(gfierr == TOX_ERR_FILE_GET_FRIEND_NOT_FOUND, "wrong error");
765 ck_assert_msg(!tox_file_get_file_id(tox2, 0, fnum + 1, file_cmp_id, &gfierr), "tox_file_get_file_id didn't fail");
766 ck_assert_msg(gfierr == TOX_ERR_FILE_GET_NOT_FOUND, "wrong error");
767 ck_assert_msg(tox_file_get_file_id(tox2, 0, fnum, file_cmp_id, &gfierr), "tox_file_get_file_id failed");
768 ck_assert_msg(gfierr == TOX_ERR_FILE_GET_OK, "wrong error");
769
770 max_sending = 100 * 1024;
771 m_send_reached = 0;
772
773 while (1) {
774 tox_iterate(tox1, &to_compare);
775 tox_iterate(tox2, &to_compare);
776 tox_iterate(tox3, &to_compare);
777
778 if (file_sending_done) {
779 if (sendf_ok && file_recv && m_send_reached && totalf_size == file_size && size_recv == max_sending
780 && sending_pos == size_recv && file_accepted == 1) {
781 break;
782 }
783
784 ck_abort_msg("Something went wrong in file transfer %u %u %u %u %u %u %u %llu %llu %llu %llu", sendf_ok, file_recv,
785 m_send_reached, totalf_size == file_size, size_recv == max_sending, sending_pos == size_recv, file_accepted == 1,
786 totalf_size, file_size,
787 size_recv, sending_pos);
788 }
789
790 uint32_t tox1_interval = tox_iteration_interval(tox1);
791 uint32_t tox2_interval = tox_iteration_interval(tox2);
792 uint32_t tox3_interval = tox_iteration_interval(tox3);
793
794 c_sleep(MIN(tox1_interval, MIN(tox2_interval, tox3_interval)));
795 }
796
797 printf("Starting file 0 transfer test.\n");
798
799 file_sending_done = file_accepted = file_size = sendf_ok = size_recv = 0;
800 file_recv = 0;
801 tox_callback_file_recv_chunk(tox3, write_file);
802 tox_callback_file_recv_control(tox2, file_print_control);
803 tox_callback_file_chunk_request(tox2, tox_file_chunk_request);
804 tox_callback_file_recv_control(tox3, file_print_control);
805 tox_callback_file_recv(tox3, tox_file_receive);
806 totalf_size = 0;
807 fnum = tox_file_send(tox2, 0, TOX_FILE_KIND_DATA, totalf_size, 0, (const uint8_t *)"Gentoo.exe", sizeof("Gentoo.exe"),
808 0);
809 ck_assert_msg(fnum != UINT32_MAX, "tox_new_file_sender fail");
810
811 ck_assert_msg(!tox_file_get_file_id(tox2, 1, fnum, file_cmp_id, &gfierr), "tox_file_get_file_id didn't fail");
812 ck_assert_msg(gfierr == TOX_ERR_FILE_GET_FRIEND_NOT_FOUND, "wrong error");
813 ck_assert_msg(!tox_file_get_file_id(tox2, 0, fnum + 1, file_cmp_id, &gfierr), "tox_file_get_file_id didn't fail");
814 ck_assert_msg(gfierr == TOX_ERR_FILE_GET_NOT_FOUND, "wrong error");
815 ck_assert_msg(tox_file_get_file_id(tox2, 0, fnum, file_cmp_id, &gfierr), "tox_file_get_file_id failed");
816 ck_assert_msg(gfierr == TOX_ERR_FILE_GET_OK, "wrong error");
817
818 while (1) {
819 tox_iterate(tox1, &to_compare);
820 tox_iterate(tox2, &to_compare);
821 tox_iterate(tox3, &to_compare);
822
823 if (file_sending_done) {
824 if (sendf_ok && file_recv && totalf_size == file_size && size_recv == file_size && sending_pos == size_recv
825 && file_accepted == 1) {
826 break;
827 }
828
829 ck_abort_msg("Something went wrong in file transfer %u %u %u %u %u %u %llu %llu %llu", sendf_ok, file_recv,
830 totalf_size == file_size, size_recv == file_size, sending_pos == size_recv, file_accepted == 1, totalf_size, size_recv,
831 sending_pos);
832 }
833
834 uint32_t tox1_interval = tox_iteration_interval(tox1);
835 uint32_t tox2_interval = tox_iteration_interval(tox2);
836 uint32_t tox3_interval = tox_iteration_interval(tox3);
837
838 c_sleep(MIN(tox1_interval, MIN(tox2_interval, tox3_interval)));
839 }
840
841 printf("test_few_clients succeeded, took %llu seconds\n", time(NULL) - cur_time);
842
843 tox_kill(tox1);
844 tox_kill(tox2);
845 tox_kill(tox3);
846}
847END_TEST
848
849#define NUM_TOXES 90
850#define NUM_FRIENDS 50
851
852START_TEST(test_many_clients)
853{
854 long long unsigned int cur_time = time(NULL);
855 Tox *toxes[NUM_TOXES];
856 uint32_t i, j;
857 uint32_t to_comp = 974536;
858
859 for (i = 0; i < NUM_TOXES; ++i) {
860 toxes[i] = tox_new(0, 0);
861 ck_assert_msg(toxes[i] != 0, "Failed to create tox instances %u", i);
862 tox_callback_friend_request(toxes[i], accept_friend_request);
863 }
864
865 {
866 TOX_ERR_GET_PORT error;
867 ck_assert_msg(tox_self_get_udp_port(toxes[0], &error) == 33445, "First Tox instance did not bind to udp port 33445.\n");
868 ck_assert_msg(error == TOX_ERR_GET_PORT_OK, "wrong error");
869 }
870
871 struct {
872 uint16_t tox1;
873 uint16_t tox2;
874 } pairs[NUM_FRIENDS];
875
876 uint8_t address[TOX_ADDRESS_SIZE];
877
878 unsigned int num_f = 0;
879
880 for (i = 0; i < NUM_TOXES; ++i) {
881 num_f += tox_self_get_friend_list_size(toxes[i]);
882 }
883
884 ck_assert_msg(num_f == 0, "bad num friends: %u", num_f);
885
886 for (i = 0; i < NUM_FRIENDS; ++i) {
887loop_top:
888 pairs[i].tox1 = rand() % NUM_TOXES;
889 pairs[i].tox2 = (pairs[i].tox1 + rand() % (NUM_TOXES - 1) + 1) % NUM_TOXES;
890
891 for (j = 0; j < i; ++j) {
892 if (pairs[j].tox2 == pairs[i].tox1 && pairs[j].tox1 == pairs[i].tox2) {
893 goto loop_top;
894 }
895 }
896
897 tox_self_get_address(toxes[pairs[i].tox1], address);
898
899 TOX_ERR_FRIEND_ADD test;
900 uint32_t num = tox_friend_add(toxes[pairs[i].tox2], address, (const uint8_t *)"Gentoo", 7, &test);
901
902 if (test == TOX_ERR_FRIEND_ADD_ALREADY_SENT) {
903 goto loop_top;
904 }
905
906 ck_assert_msg(num != UINT32_MAX && test == TOX_ERR_FRIEND_ADD_OK, "Failed to add friend error code: %i", test);
907 }
908
909 for (i = 0; i < NUM_TOXES; ++i) {
910 num_f += tox_self_get_friend_list_size(toxes[i]);
911 }
912
913 ck_assert_msg(num_f == NUM_FRIENDS, "bad num friends: %u", num_f);
914
915 uint16_t last_count = 0;
916
917 while (1) {
918 uint16_t counter = 0;
919
920 for (i = 0; i < NUM_TOXES; ++i) {
921 for (j = 0; j < tox_self_get_friend_list_size(toxes[i]); ++j) {
922 if (tox_friend_get_connection_status(toxes[i], j, 0) == TOX_CONNECTION_UDP) {
923 ++counter;
924 }
925 }
926 }
927
928 if (counter != last_count) {
929 printf("many_clients got to %u\n", counter);
930 last_count = counter;
931 }
932
933 if (counter == NUM_FRIENDS * 2) {
934 break;
935 }
936
937 for (i = 0; i < NUM_TOXES; ++i) {
938 tox_iterate(toxes[i], &to_comp);
939 }
940
941 c_sleep(50);
942 }
943
944 for (i = 0; i < NUM_TOXES; ++i) {
945 tox_kill(toxes[i]);
946 }
947
948 printf("test_many_clients succeeded, took %llu seconds\n", time(NULL) - cur_time);
949}
950END_TEST
951
952#define NUM_TOXES_TCP 40
953#define TCP_RELAY_PORT 33448
954
955START_TEST(test_many_clients_tcp)
956{
957 long long unsigned int cur_time = time(NULL);
958 Tox *toxes[NUM_TOXES_TCP];
959 uint32_t i, j;
960 uint32_t to_comp = 974536;
961
962 for (i = 0; i < NUM_TOXES_TCP; ++i) {
963 struct Tox_Options opts;
964 tox_options_default(&opts);
965
966 if (i == 0) {
967 opts.tcp_port = TCP_RELAY_PORT;
968 } else {
969 opts.udp_enabled = 0;
970 }
971
972 toxes[i] = tox_new(&opts, 0);
973 ck_assert_msg(toxes[i] != 0, "Failed to create tox instances %u", i);
974 tox_callback_friend_request(toxes[i], accept_friend_request);
975 uint8_t dpk[TOX_PUBLIC_KEY_SIZE];
976 tox_self_get_dht_id(toxes[0], dpk);
977 TOX_ERR_BOOTSTRAP error = TOX_ERR_BOOTSTRAP_OK;
978 ck_assert_msg(tox_add_tcp_relay(toxes[i], TOX_LOCALHOST, TCP_RELAY_PORT, dpk, &error), "add relay error, %i, %i", i,
979 error);
980 ck_assert_msg(tox_bootstrap(toxes[i], TOX_LOCALHOST, 33445, dpk, 0), "Bootstrap error");
981 }
982
983 {
984 TOX_ERR_GET_PORT error;
985 ck_assert_msg(tox_self_get_udp_port(toxes[0], &error) == 33445, "First Tox instance did not bind to udp port 33445.\n");
986 ck_assert_msg(error == TOX_ERR_GET_PORT_OK, "wrong error");
987 ck_assert_msg(tox_self_get_tcp_port(toxes[0], &error) == TCP_RELAY_PORT,
988 "First Tox instance did not bind to tcp port %u.\n", TCP_RELAY_PORT);
989 ck_assert_msg(error == TOX_ERR_GET_PORT_OK, "wrong error");
990 }
991
992 struct {
993 uint16_t tox1;
994 uint16_t tox2;
995 } pairs[NUM_FRIENDS];
996
997 uint8_t address[TOX_ADDRESS_SIZE];
998
999 for (i = 0; i < NUM_FRIENDS; ++i) {
1000loop_top:
1001 pairs[i].tox1 = rand() % NUM_TOXES_TCP;
1002 pairs[i].tox2 = (pairs[i].tox1 + rand() % (NUM_TOXES_TCP - 1) + 1) % NUM_TOXES_TCP;
1003
1004 for (j = 0; j < i; ++j) {
1005 if (pairs[j].tox2 == pairs[i].tox1 && pairs[j].tox1 == pairs[i].tox2) {
1006 goto loop_top;
1007 }
1008 }
1009
1010 tox_self_get_address(toxes[pairs[i].tox1], address);
1011
1012 TOX_ERR_FRIEND_ADD test;
1013 uint32_t num = tox_friend_add(toxes[pairs[i].tox2], address, (const uint8_t *)"Gentoo", 7, &test);
1014
1015 if (test == TOX_ERR_FRIEND_ADD_ALREADY_SENT) {
1016 goto loop_top;
1017 }
1018
1019 ck_assert_msg(num != UINT32_MAX && test == TOX_ERR_FRIEND_ADD_OK, "Failed to add friend error code: %i", test);
1020 }
1021
1022 while (1) {
1023 uint16_t counter = 0;
1024
1025 for (i = 0; i < NUM_TOXES_TCP; ++i) {
1026 for (j = 0; j < tox_self_get_friend_list_size(toxes[i]); ++j) {
1027 if (tox_friend_get_connection_status(toxes[i], j, 0) == TOX_CONNECTION_TCP) {
1028 ++counter;
1029 }
1030 }
1031 }
1032
1033 if (counter == NUM_FRIENDS * 2) {
1034 break;
1035 }
1036
1037 for (i = 0; i < NUM_TOXES_TCP; ++i) {
1038 tox_iterate(toxes[i], &to_comp);
1039 }
1040
1041 c_sleep(50);
1042 }
1043
1044 for (i = 0; i < NUM_TOXES_TCP; ++i) {
1045 tox_kill(toxes[i]);
1046 }
1047
1048 printf("test_many_clients_tcp succeeded, took %llu seconds\n", time(NULL) - cur_time);
1049}
1050END_TEST
1051
1052#define NUM_TCP_RELAYS 3
1053
1054START_TEST(test_many_clients_tcp_b)
1055{
1056 long long unsigned int cur_time = time(NULL);
1057 Tox *toxes[NUM_TOXES_TCP];
1058 uint32_t i, j;
1059 uint32_t to_comp = 974536;
1060
1061 for (i = 0; i < NUM_TOXES_TCP; ++i) {
1062 struct Tox_Options opts;
1063 tox_options_default(&opts);
1064
1065 if (i < NUM_TCP_RELAYS) {
1066 opts.tcp_port = TCP_RELAY_PORT + i;
1067 } else {
1068 opts.udp_enabled = 0;
1069 }
1070
1071 toxes[i] = tox_new(&opts, 0);
1072 ck_assert_msg(toxes[i] != 0, "Failed to create tox instances %u", i);
1073 tox_callback_friend_request(toxes[i], accept_friend_request);
1074 uint8_t dpk[TOX_PUBLIC_KEY_SIZE];
1075 tox_self_get_dht_id(toxes[(i % NUM_TCP_RELAYS)], dpk);
1076 ck_assert_msg(tox_add_tcp_relay(toxes[i], TOX_LOCALHOST, TCP_RELAY_PORT + (i % NUM_TCP_RELAYS), dpk, 0),
1077 "add relay error");
1078 tox_self_get_dht_id(toxes[0], dpk);
1079 ck_assert_msg(tox_bootstrap(toxes[i], TOX_LOCALHOST, 33445, dpk, 0), "Bootstrap error");
1080 }
1081
1082 {
1083 TOX_ERR_GET_PORT error;
1084 ck_assert_msg(tox_self_get_udp_port(toxes[0], &error) == 33445, "First Tox instance did not bind to udp port 33445.\n");
1085 ck_assert_msg(error == TOX_ERR_GET_PORT_OK, "wrong error");
1086 ck_assert_msg(tox_self_get_tcp_port(toxes[0], &error) == TCP_RELAY_PORT,
1087 "First Tox instance did not bind to tcp port %u.\n", TCP_RELAY_PORT);
1088 ck_assert_msg(error == TOX_ERR_GET_PORT_OK, "wrong error");
1089 }
1090
1091 struct {
1092 uint16_t tox1;
1093 uint16_t tox2;
1094 } pairs[NUM_FRIENDS];
1095
1096 uint8_t address[TOX_ADDRESS_SIZE];
1097
1098 for (i = 0; i < NUM_FRIENDS; ++i) {
1099loop_top:
1100 pairs[i].tox1 = rand() % NUM_TOXES_TCP;
1101 pairs[i].tox2 = (pairs[i].tox1 + rand() % (NUM_TOXES_TCP - 1) + 1) % NUM_TOXES_TCP;
1102
1103 for (j = 0; j < i; ++j) {
1104 if (pairs[j].tox2 == pairs[i].tox1 && pairs[j].tox1 == pairs[i].tox2) {
1105 goto loop_top;
1106 }
1107 }
1108
1109 tox_self_get_address(toxes[pairs[i].tox1], address);
1110
1111 TOX_ERR_FRIEND_ADD test;
1112 uint32_t num = tox_friend_add(toxes[pairs[i].tox2], address, (const uint8_t *)"Gentoo", 7, &test);
1113
1114 if (test == TOX_ERR_FRIEND_ADD_ALREADY_SENT) {
1115 goto loop_top;
1116 }
1117
1118 ck_assert_msg(num != UINT32_MAX && test == TOX_ERR_FRIEND_ADD_OK, "Failed to add friend error code: %i", test);
1119 }
1120
1121 uint16_t last_count = 0;
1122
1123 while (1) {
1124 uint16_t counter = 0;
1125
1126 for (i = 0; i < NUM_TOXES_TCP; ++i) {
1127 for (j = 0; j < tox_self_get_friend_list_size(toxes[i]); ++j) {
1128 if (tox_friend_get_connection_status(toxes[i], j, 0) == TOX_CONNECTION_TCP) {
1129 ++counter;
1130 }
1131 }
1132 }
1133
1134 if (counter != last_count) {
1135 printf("many_clients_tcp_b got to %u\n", counter);
1136 last_count = counter;
1137 }
1138
1139 if (counter == NUM_FRIENDS * 2) {
1140 break;
1141 }
1142
1143 for (i = 0; i < NUM_TOXES_TCP; ++i) {
1144 tox_iterate(toxes[i], &to_comp);
1145 }
1146
1147 c_sleep(30);
1148 }
1149
1150 for (i = 0; i < NUM_TOXES_TCP; ++i) {
1151 tox_kill(toxes[i]);
1152 }
1153
1154 printf("test_many_clients_tcp_b succeeded, took %llu seconds\n", time(NULL) - cur_time);
1155}
1156END_TEST
1157
1158
1159#define NUM_GROUP_TOX 32
1160
1161static void g_accept_friend_request(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length,
1162 void *userdata)
1163{
1164 if (*((uint32_t *)userdata) != 234212) {
1165 return;
1166 }
1167
1168 if (length == 7 && memcmp("Gentoo", data, 7) == 0) {
1169 tox_friend_add_norequest(m, public_key, 0);
1170 }
1171}
1172
1173static Tox *invite_tox;
1174static unsigned int invite_counter;
1175
1176static void print_group_invite_callback(Tox *tox, uint32_t friendnumber, TOX_CONFERENCE_TYPE type, const uint8_t *data,
1177 size_t length,
1178 void *userdata)
1179{
1180 if (*((uint32_t *)userdata) != 234212) {
1181 return;
1182 }
1183
1184 if (type != TOX_CONFERENCE_TYPE_TEXT) {
1185 return;
1186 }
1187
1188 uint32_t g_num;
1189
1190 if ((g_num = tox_conference_join(tox, friendnumber, data, length, NULL)) == UINT32_MAX) {
1191 return;
1192 }
1193
1194 ck_assert_msg(g_num == 0, "Group number was not 0");
1195 ck_assert_msg(tox_conference_join(tox, friendnumber, data, length, NULL) == -1,
1196 "Joining groupchat twice should be impossible.");
1197
1198 invite_tox = tox;
1199 invite_counter = 4;
1200}
1201
1202static unsigned int num_recv;
1203
1204static void print_group_message(Tox *tox, uint32_t groupnumber, uint32_t peernumber, TOX_MESSAGE_TYPE type,
1205 const uint8_t *message, size_t length,
1206 void *userdata)
1207{
1208 if (*((uint32_t *)userdata) != 234212) {
1209 return;
1210 }
1211
1212 if (length == (sizeof("Install Gentoo") - 1) && memcmp(message, "Install Gentoo", sizeof("Install Gentoo") - 1) == 0) {
1213 ++num_recv;
1214 }
1215}
1216
1217START_TEST(test_many_group)
1218{
1219 long long unsigned int test_start_time = time(NULL);
1220
1221group_test_restart:
1222 ;
1223
1224 Tox *toxes[NUM_GROUP_TOX];
1225 unsigned int i, j, k;
1226 uint32_t to_comp = 234212;
1227 int test_run = 0;
1228 long long unsigned int cur_time = time(NULL);
1229
1230 for (i = 0; i < NUM_GROUP_TOX; ++i) {
1231 toxes[i] = tox_new(0, 0);
1232 ck_assert_msg(toxes[i] != 0, "Failed to create tox instances %u", i);
1233 tox_callback_friend_request(toxes[i], &g_accept_friend_request);
1234 tox_callback_conference_invite(toxes[i], &print_group_invite_callback);
1235 }
1236
1237 {
1238 TOX_ERR_GET_PORT error;
1239 ck_assert_msg(tox_self_get_udp_port(toxes[0], &error) == 33445, "First Tox instance did not bind to udp port 33445.\n");
1240 ck_assert_msg(error == TOX_ERR_GET_PORT_OK, "wrong error");
1241 }
1242
1243 uint8_t address[TOX_ADDRESS_SIZE];
1244 tox_self_get_address(toxes[NUM_GROUP_TOX - 1], address);
1245
1246 for (i = 0; i < NUM_GROUP_TOX; ++i) {
1247 ck_assert_msg(tox_friend_add(toxes[i], address, (const uint8_t *)"Gentoo", 7, 0) == 0, "Failed to add friend");
1248
1249 tox_self_get_address(toxes[i], address);
1250 }
1251
1252 while (1) {
1253 for (i = 0; i < NUM_GROUP_TOX; ++i) {
1254 if (tox_friend_get_connection_status(toxes[i], 0, 0) != TOX_CONNECTION_UDP) {
1255 break;
1256 }
1257 }
1258
1259 if (i == NUM_GROUP_TOX) {
1260 break;
1261 }
1262
1263 for (i = 0; i < NUM_GROUP_TOX; ++i) {
1264 tox_iterate(toxes[i], &to_comp);
1265 }
1266
1267 c_sleep(25);
1268 }
1269
1270 printf("friends connected, took %llu seconds\n", time(NULL) - cur_time);
1271
1272 ck_assert_msg(tox_conference_new(toxes[0], NULL) != UINT32_MAX, "Failed to create group");
1273 ck_assert_msg(tox_conference_invite(toxes[0], 0, 0, NULL) != 0, "Failed to invite friend");
1274 ck_assert_msg(tox_conference_set_title(toxes[0], 0, (const uint8_t *)"Gentoo", sizeof("Gentoo") - 1, NULL) != 0,
1275 "Failed to set group title");
1276 invite_counter = ~0;
1277
1278 unsigned int done = ~0;
1279 done -= 5;
1280
1281 while (1) {
1282 for (i = 0; i < NUM_GROUP_TOX; ++i) {
1283 tox_iterate(toxes[i], &to_comp);
1284 }
1285
1286 if (!invite_counter) {
1287 ck_assert_msg(tox_conference_invite(invite_tox, 0, 0, NULL) != 0, "Failed to invite friend");
1288 }
1289
1290 if (done == invite_counter) {
1291 break;
1292 }
1293
1294 --invite_counter;
1295 c_sleep(50);
1296 }
1297
1298 for (i = 0; i < NUM_GROUP_TOX; ++i) {
1299 uint32_t peer_count = tox_conference_peer_count(toxes[i], 0, NULL);
1300
1301 /**
1302 * Group chats fail unpredictably, currently they'll rerun as many times
1303 * as they need to until they pass the test, or the time out is reached
1304 * Either way in this case it's fine */
1305 if (peer_count != NUM_GROUP_TOX) {
1306 ++test_run;
1307 printf("\tError starting up the first group (peer_count %"PRIu32" != %d, test_run = %d)\n", peer_count, NUM_GROUP_TOX,
1308 test_run);
1309
1310 for (j = 0; j < NUM_GROUP_TOX; ++j) {
1311 tox_kill(toxes[j]);
1312 }
1313
1314 c_sleep(1000);
1315
1316 goto group_test_restart;
1317 }
1318
1319 /**
1320 * This check will never fail because it'll jump before this event
1321 * I've decided to leave it in because eventually, we may want to only
1322 * restart this test once, in which case this check will become
1323 * important again.
1324 */
1325 ck_assert_msg(peer_count == NUM_GROUP_TOX, "\n\tBad number of group peers (pre check)."
1326 "\n\t\t\tExpected: %u but tox_instance(%u) only has: %"PRIu32"\n\n",
1327 NUM_GROUP_TOX, i, peer_count);
1328
1329 uint8_t title[2048];
1330 size_t ret = tox_conference_get_title_size(toxes[i], 0, NULL);
1331 ck_assert_msg(ret == sizeof("Gentoo") - 1, "Wrong title length");
1332 tox_conference_get_title(toxes[i], 0, title, NULL);
1333 ck_assert_msg(memcmp("Gentoo", title, ret) == 0, "Wrong title");
1334 }
1335
1336 printf("group connected\n");
1337
1338 for (i = 0; i < NUM_GROUP_TOX; ++i) {
1339 tox_callback_conference_message(toxes[i], &print_group_message);
1340 }
1341
1342 ck_assert_msg(
1343 tox_conference_send_message(
1344 toxes[rand() % NUM_GROUP_TOX], 0, TOX_MESSAGE_TYPE_NORMAL, (const uint8_t *)"Install Gentoo",
1345 sizeof("Install Gentoo") - 1, NULL) != 0, "Failed to send group message.");
1346 num_recv = 0;
1347
1348 for (j = 0; j < 20; ++j) {
1349 for (i = 0; i < NUM_GROUP_TOX; ++i) {
1350 tox_iterate(toxes[i], &to_comp);
1351 }
1352
1353 c_sleep(25);
1354 }
1355
1356 c_sleep(25);
1357 ck_assert_msg(num_recv == NUM_GROUP_TOX, "Failed to recv group messages.");
1358
1359 for (k = NUM_GROUP_TOX; k != 0 ; --k) {
1360 tox_conference_delete(toxes[k - 1], 0, NULL);
1361
1362 for (j = 0; j < 10; ++j) {
1363 for (i = 0; i < NUM_GROUP_TOX; ++i) {
1364 tox_iterate(toxes[i], &to_comp);
1365 }
1366
1367 c_sleep(50);
1368 }
1369
1370 for (i = 0; i < (k - 1); ++i) {
1371 uint32_t peer_count = tox_conference_peer_count(toxes[i], 0, NULL);
1372 ck_assert_msg(peer_count == (k - 1), "\n\tBad number of group peers (post check)."
1373 "\n\t\t\tExpected: %u but tox_instance(%u) only has: %"PRIu32"\n\n",
1374 (k - 1), i, peer_count);
1375 }
1376 }
1377
1378 for (i = 0; i < NUM_GROUP_TOX; ++i) {
1379 tox_kill(toxes[i]);
1380 }
1381
1382 printf("test_many_group succeeded, took %llu seconds\n", time(NULL) - test_start_time);
1383}
1384END_TEST
1385
1386#ifdef TRAVIS_ENV
1387static const uint8_t timeout_mux = 20;
1388#else
1389static const uint8_t timeout_mux = 10;
1390#endif
1391
1392static Suite *tox_suite(void)
1393{
1394 Suite *s = suite_create("Tox");
1395
1396 DEFTESTCASE(one);
1397 DEFTESTCASE_SLOW(few_clients, 8 * timeout_mux);
1398 DEFTESTCASE_SLOW(many_clients, 8 * timeout_mux);
1399
1400 /* Each tox connects to a single tox TCP */
1401 DEFTESTCASE_SLOW(many_clients_tcp, 4 * timeout_mux);
1402
1403 /* Try to make a connection to each "older sibling" tox instance via TCP */
1404 DEFTESTCASE_SLOW(many_clients_tcp_b, 8 * timeout_mux);
1405
1406 /* This test works VERY unreliably. So it's worthless in its current state.
1407 * Anyone reading this is welcome to try to fix it, but because there is a
1408 * new version of group chats for Tox already completed, and nearly ready to
1409 * merge, No one is willing/available to give this test the time in needs */
1410#ifndef DISABLE_GROUP_TESTS
1411 DEFTESTCASE_SLOW(many_group, 80);
1412#endif
1413
1414 return s;
1415}
1416
1417int main(int argc, char *argv[])
1418{
1419 srand((unsigned int) time(NULL));
1420
1421 Suite *tox = tox_suite();
1422 SRunner *test_runner = srunner_create(tox);
1423
1424 int number_failed = 0;
1425 srunner_run_all(test_runner, CK_NORMAL);
1426 number_failed = srunner_ntests_failed(test_runner);
1427
1428 srunner_free(test_runner);
1429
1430 return number_failed;
1431}