summaryrefslogtreecommitdiff
path: root/auto_tests
diff options
context:
space:
mode:
authorzugz (tox) <mbays+tox@sdf.org>2019-02-10 00:00:00 +0000
committerzugz (tox) <mbays+tox@sdf.org>2019-02-10 00:00:00 +0000
commit49e2406ffabe2bbf04dc9416f6240ea63df4590d (patch)
treee81f432758d1f8a2aba7c037cc1c81a9550aef6f /auto_tests
parent0aad180d1e1d7dae7cbf2868e139af0a4dc34fe7 (diff)
Expose api functions for enabling and disabling AV in AV groups
A group loaded from a savefile starts with AV disabled.
Diffstat (limited to 'auto_tests')
-rw-r--r--auto_tests/Makefile.inc6
-rw-r--r--auto_tests/conference_av_test.c467
-rw-r--r--auto_tests/conference_test.c99
-rw-r--r--auto_tests/run_auto_test.h15
4 files changed, 545 insertions, 42 deletions
diff --git a/auto_tests/Makefile.inc b/auto_tests/Makefile.inc
index 3a4b6c7e..98f9db13 100644
--- a/auto_tests/Makefile.inc
+++ b/auto_tests/Makefile.inc
@@ -57,7 +57,7 @@ AUTOTEST_LDADD = \
57 57
58 58
59if BUILD_AV 59if BUILD_AV
60TESTS += toxav_basic_test toxav_many_test 60TESTS += conference_av_test toxav_basic_test toxav_many_test
61AUTOTEST_LDADD += libtoxav.la 61AUTOTEST_LDADD += libtoxav.la
62endif 62endif
63 63
@@ -221,6 +221,10 @@ version_test_LDADD = $(AUTOTEST_LDADD)
221 221
222if BUILD_AV 222if BUILD_AV
223 223
224conference_av_test_SOURCES = ../auto_tests/conference_av_test.c
225conference_av_test_CFLAGS = $(AUTOTEST_CFLAGS)
226conference_av_test_LDADD = $(AUTOTEST_LDADD)
227
224toxav_basic_test_SOURCES = ../auto_tests/toxav_basic_test.c 228toxav_basic_test_SOURCES = ../auto_tests/toxav_basic_test.c
225toxav_basic_test_CFLAGS = $(AUTOTEST_CFLAGS) 229toxav_basic_test_CFLAGS = $(AUTOTEST_CFLAGS)
226toxav_basic_test_LDADD = $(AUTOTEST_LDADD) $(AV_LIBS) 230toxav_basic_test_LDADD = $(AUTOTEST_LDADD) $(AV_LIBS)
diff --git a/auto_tests/conference_av_test.c b/auto_tests/conference_av_test.c
new file mode 100644
index 00000000..6d701751
--- /dev/null
+++ b/auto_tests/conference_av_test.c
@@ -0,0 +1,467 @@
1/* Auto Tests: Conferences AV.
2 */
3
4#ifdef HAVE_CONFIG_H
5#include "config.h"
6#endif
7
8#include <stdlib.h>
9#include <string.h>
10#include <time.h>
11#include <stdint.h>
12
13#include "../toxav/toxav.h"
14#include "check_compat.h"
15
16#define NUM_AV_GROUP_TOX 16
17#define NUM_AV_DISCONNECT (NUM_AV_GROUP_TOX / 2)
18#define NUM_AV_DISABLE (NUM_AV_GROUP_TOX / 2)
19
20typedef struct State {
21 uint32_t index;
22 uint64_t clock;
23
24 bool invited_next;
25
26 uint32_t received_audio_peers[NUM_AV_GROUP_TOX];
27 uint32_t received_audio_num;
28} State;
29
30#include "run_auto_test.h"
31
32static void handle_self_connection_status(
33 Tox *tox, Tox_Connection connection_status, void *user_data)
34{
35 const State *state = (State *)user_data;
36
37 if (connection_status != TOX_CONNECTION_NONE) {
38 printf("tox #%u: is now connected\n", state->index);
39 } else {
40 printf("tox #%u: is now disconnected\n", state->index);
41 }
42}
43
44static void handle_friend_connection_status(
45 Tox *tox, uint32_t friendnumber, Tox_Connection connection_status, void *user_data)
46{
47 const State *state = (State *)user_data;
48
49 if (connection_status != TOX_CONNECTION_NONE) {
50 printf("tox #%u: is now connected to friend %u\n", state->index, friendnumber);
51 } else {
52 printf("tox #%u: is now disconnected from friend %u\n", state->index, friendnumber);
53 }
54}
55
56static void audio_callback(void *tox, uint32_t groupnumber, uint32_t peernumber,
57 const int16_t *pcm, unsigned int samples, uint8_t channels, uint32_t
58 sample_rate, void *userdata)
59{
60 if (samples == 0) {
61 return;
62 }
63
64 State *state = (State *)userdata;
65
66 for (uint32_t i = 0; i < state->received_audio_num; ++i) {
67 if (state->received_audio_peers[i] == peernumber) {
68 return;
69 }
70 }
71
72 ck_assert(state->received_audio_num < NUM_AV_GROUP_TOX);
73
74 state->received_audio_peers[state->received_audio_num] = peernumber;
75 ++state->received_audio_num;
76}
77
78static void handle_conference_invite(
79 Tox *tox, uint32_t friendnumber, Tox_Conference_Type type,
80 const uint8_t *data, size_t length, void *user_data)
81{
82 const State *state = (State *)user_data;
83 ck_assert_msg(type == TOX_CONFERENCE_TYPE_AV, "tox #%u: wrong conference type: %d", state->index, type);
84
85 ck_assert_msg(toxav_join_av_groupchat(tox, friendnumber, data, length, audio_callback, user_data) == 0,
86 "tox #%u: failed to join group", state->index);
87}
88
89static void handle_conference_connected(
90 Tox *tox, uint32_t conference_number, void *user_data)
91{
92 State *state = (State *)user_data;
93
94 if (state->invited_next || tox_self_get_friend_list_size(tox) <= 1) {
95 return;
96 }
97
98 Tox_Err_Conference_Invite err;
99 tox_conference_invite(tox, 1, 0, &err);
100 ck_assert_msg(err == TOX_ERR_CONFERENCE_INVITE_OK, "tox #%u failed to invite next friend: err = %d", state->index, err);
101 printf("tox #%u: invited next friend\n", state->index);
102 state->invited_next = true;
103}
104
105static bool toxes_are_disconnected_from_group(uint32_t tox_count, Tox **toxes,
106 bool *disconnected)
107{
108 uint32_t num_disconnected = 0;
109
110 for (uint32_t i = 0; i < tox_count; ++i) {
111 num_disconnected += disconnected[i];
112 }
113
114 for (uint32_t i = 0; i < tox_count; i++) {
115 if (disconnected[i]) {
116 continue;
117 }
118
119 if (tox_conference_peer_count(toxes[i], 0, nullptr) > tox_count - num_disconnected) {
120 return false;
121 }
122 }
123
124 return true;
125}
126
127static void disconnect_toxes(uint32_t tox_count, Tox **toxes, State *state,
128 const bool *disconnect, const bool *exclude)
129{
130 /* Fake a network outage for a set of peers D by iterating only the other
131 * peers D' until the connections time out according to D', then iterating
132 * only D until the connections time out according to D. */
133
134 VLA(bool, disconnect_now, tox_count);
135 bool invert = false;
136
137 do {
138 for (uint32_t i = 0; i < tox_count; ++i) {
139 disconnect_now[i] = exclude[i] || (invert ^ disconnect[i]);
140 }
141
142 do {
143 for (uint32_t i = 0; i < tox_count; ++i) {
144 if (!disconnect_now[i]) {
145 tox_iterate(toxes[i], &state[i]);
146 state[i].clock += 1000;
147 }
148 }
149
150 c_sleep(20);
151 } while (!toxes_are_disconnected_from_group(tox_count, toxes, disconnect_now));
152
153 invert = !invert;
154 } while (invert);
155}
156
157static bool all_connected_to_group(uint32_t tox_count, Tox **toxes)
158{
159 for (uint32_t i = 0; i < tox_count; i++) {
160 if (tox_conference_peer_count(toxes[i], 0, nullptr) < tox_count) {
161 return false;
162 }
163 }
164
165 return true;
166}
167
168/**
169 * returns a random index at which a list of booleans is false
170 * (some such index is required to exist)
171 */
172static uint32_t random_false_index(bool *list, const uint32_t length)
173{
174 uint32_t index;
175
176 do {
177 index = random_u32() % length;
178 } while (list[index]);
179
180 return index;
181}
182
183static bool all_got_audio(State *state, const bool *disabled)
184{
185 uint32_t num_disabled = 0;
186
187 for (uint32_t i = 0; i < NUM_AV_GROUP_TOX; ++i) {
188 num_disabled += disabled[i];
189 }
190
191 for (uint32_t i = 0; i < NUM_AV_GROUP_TOX; ++i) {
192 if (disabled[i] ^ (state[i].received_audio_num
193 != NUM_AV_GROUP_TOX - num_disabled - 1)) {
194 return false;
195 }
196 }
197
198 return true;
199}
200
201static void reset_received_audio(Tox **toxes, State *state)
202{
203 for (uint32_t j = 0; j < NUM_AV_GROUP_TOX; ++j) {
204 state[j].received_audio_num = 0;
205 }
206}
207
208#define GROUP_AV_TEST_SAMPLES 960
209
210/* must have
211 * GROUP_AV_AUDIO_ITERATIONS - NUM_AV_GROUP_TOX >= 2^n >= GROUP_JBUF_SIZE
212 * for some n, to give messages time to be relayed and to let the jitter
213 * buffers fill up. */
214#define GROUP_AV_AUDIO_ITERATIONS (8 + NUM_AV_GROUP_TOX)
215
216static bool test_audio(Tox **toxes, State *state, const bool *disabled, bool quiet)
217{
218 if (!quiet) {
219 printf("testing sending and receiving audio\n");
220 }
221
222 int16_t PCM[GROUP_AV_TEST_SAMPLES];
223
224 reset_received_audio(toxes, state);
225
226 for (uint32_t n = 0; n < GROUP_AV_AUDIO_ITERATIONS; n++) {
227 for (uint32_t i = 0; i < NUM_AV_GROUP_TOX; ++i) {
228 if (disabled[i]) {
229 continue;
230 }
231
232 if (toxav_group_send_audio(toxes[i], 0, PCM, GROUP_AV_TEST_SAMPLES, 1, 48000) != 0) {
233 if (!quiet) {
234 ck_abort_msg("#%u failed to send audio", state[i].index);
235 }
236
237 return false;
238 }
239 }
240
241 iterate_all_wait(NUM_AV_GROUP_TOX, toxes, state, ITERATION_INTERVAL);
242
243 if (all_got_audio(state, disabled)) {
244 return true;
245 }
246 }
247
248 if (!quiet) {
249 ck_abort_msg("group failed to receive audio");
250 }
251
252 return false;
253}
254
255static void test_eventual_audio(Tox **toxes, State *state, const bool *disabled, uint64_t timeout)
256{
257 uint64_t start = state[0].clock;
258
259 while (state[0].clock < start + timeout) {
260 if (test_audio(toxes, state, disabled, true)
261 && test_audio(toxes, state, disabled, true)) {
262 printf("audio test successful after %d seconds\n", (int)((state[0].clock - start) / 1000));
263 return;
264 }
265 }
266
267 printf("audio seems not to be getting through: testing again with errors.\n");
268 test_audio(toxes, state, disabled, false);
269}
270
271static void do_audio(Tox **toxes, State *state, uint32_t iterations)
272{
273 int16_t PCM[GROUP_AV_TEST_SAMPLES];
274 printf("running audio for %u iterations\n", iterations);
275
276 for (uint32_t f = 0; f < iterations; ++f) {
277 for (uint32_t i = 0; i < NUM_AV_GROUP_TOX; ++i) {
278 ck_assert_msg(toxav_group_send_audio(toxes[i], 0, PCM, GROUP_AV_TEST_SAMPLES, 1, 48000) == 0,
279 "#%u failed to send audio", state[i].index);
280 iterate_all_wait(NUM_AV_GROUP_TOX, toxes, state, ITERATION_INTERVAL);
281 }
282 }
283}
284
285// should agree with value in groupav.c
286#define GROUP_JBUF_DEAD_SECONDS 4
287
288#define JITTER_SETTLE_TIME (GROUP_JBUF_DEAD_SECONDS*1000 + NUM_AV_GROUP_TOX*ITERATION_INTERVAL*(GROUP_AV_AUDIO_ITERATIONS+1))
289
290static void run_conference_tests(Tox **toxes, State *state)
291{
292 bool disabled[NUM_AV_GROUP_TOX] = {0};
293
294 test_audio(toxes, state, disabled, false);
295
296 /* have everyone send audio for a bit so we can test that the audio
297 * sequnums dropping to 0 on restart isn't a problem */
298 do_audio(toxes, state, 20);
299
300 printf("letting random toxes timeout\n");
301 bool disconnected[NUM_AV_GROUP_TOX] = {0};
302 bool restarting[NUM_AV_GROUP_TOX] = {0};
303
304 ck_assert(NUM_AV_DISCONNECT < NUM_AV_GROUP_TOX);
305
306 for (uint32_t i = 0; i < NUM_AV_DISCONNECT; ++i) {
307 uint32_t disconnect = random_false_index(disconnected, NUM_AV_GROUP_TOX);
308 disconnected[disconnect] = true;
309
310 if (i < NUM_AV_DISCONNECT / 2) {
311 restarting[disconnect] = true;
312 printf("Restarting #%u\n", state[disconnect].index);
313 } else {
314 printf("Disconnecting #%u\n", state[disconnect].index);
315 }
316 }
317
318 uint8_t *save[NUM_AV_GROUP_TOX];
319 size_t save_size[NUM_AV_GROUP_TOX];
320
321 for (uint32_t i = 0; i < NUM_AV_GROUP_TOX; ++i) {
322 if (restarting[i]) {
323 save_size[i] = tox_get_savedata_size(toxes[i]);
324 ck_assert_msg(save_size[i] != 0, "save is invalid size %u", (unsigned)save_size[i]);
325 save[i] = (uint8_t *)malloc(save_size[i]);
326 ck_assert_msg(save[i] != nullptr, "malloc failed");
327 tox_get_savedata(toxes[i], save[i]);
328 tox_kill(toxes[i]);
329 }
330 }
331
332 disconnect_toxes(NUM_AV_GROUP_TOX, toxes, state, disconnected, restarting);
333
334 for (uint32_t i = 0; i < NUM_AV_GROUP_TOX; ++i) {
335 if (restarting[i]) {
336 struct Tox_Options *const options = tox_options_new(nullptr);
337 tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_TOX_SAVE);
338 tox_options_set_savedata_data(options, save[i], save_size[i]);
339 toxes[i] = tox_new_log(options, nullptr, &state[i].index);
340 tox_options_free(options);
341 free(save[i]);
342
343 set_mono_time_callback(toxes[i], &state[i]);
344 }
345 }
346
347 printf("reconnecting toxes\n");
348
349 do {
350 iterate_all_wait(NUM_AV_GROUP_TOX, toxes, state, ITERATION_INTERVAL);
351 } while (!all_connected_to_group(NUM_AV_GROUP_TOX, toxes));
352
353 for (uint32_t i = 0; i < NUM_AV_GROUP_TOX; ++i) {
354 if (restarting[i]) {
355 ck_assert_msg(toxav_groupchat_enable_av(toxes[i], 0, audio_callback, &state[i]) == 0,
356 "#%u failed to re-enable av", state[i].index);
357 }
358 }
359
360 printf("testing audio\n");
361
362 /* Allow time for the jitter buffers to reset and for the group to become
363 * connected enough for lossy messages to get through
364 * (all_connected_to_group() only checks lossless connectivity, which is a
365 * looser condition). */
366 test_eventual_audio(toxes, state, disabled, JITTER_SETTLE_TIME + NUM_AV_GROUP_TOX * 1000);
367
368 printf("testing disabling av\n");
369
370 ck_assert(NUM_AV_DISABLE < NUM_AV_GROUP_TOX);
371
372 for (uint32_t i = 0; i < NUM_AV_DISABLE; ++i) {
373 uint32_t disable = random_false_index(disabled, NUM_AV_GROUP_TOX);
374 disabled[disable] = true;
375 printf("Disabling #%u\n", state[disable].index);
376 ck_assert_msg(toxav_groupchat_enable_av(toxes[disable], 0, audio_callback, &state[disable]) != 0,
377 "#%u could enable already enabled av!", state[i].index);
378 ck_assert_msg(toxav_groupchat_disable_av(toxes[disable], 0) == 0,
379 "#%u failed to disable av", state[i].index);
380 }
381
382 // Run test without error to clear out messages from now-disabled peers.
383 test_audio(toxes, state, disabled, true);
384
385 printf("testing audio with some peers having disabled their av\n");
386 test_audio(toxes, state, disabled, false);
387
388 for (uint32_t i = 0; i < NUM_AV_DISABLE; ++i) {
389 if (!disabled[i]) {
390 continue;
391 }
392
393 disabled[i] = false;
394 ck_assert_msg(toxav_groupchat_disable_av(toxes[i], 0) != 0,
395 "#%u could disable already disabled av!", state[i].index);
396 ck_assert_msg(toxav_groupchat_enable_av(toxes[i], 0, audio_callback, &state[i]) == 0,
397 "#%u failed to re-enable av", state[i].index);
398 }
399
400 printf("testing audio after re-enabling all av\n");
401 test_eventual_audio(toxes, state, disabled, JITTER_SETTLE_TIME);
402}
403
404static void test_groupav(Tox **toxes, State *state)
405{
406 const time_t test_start_time = time(nullptr);
407
408 for (uint32_t i = 0; i < NUM_AV_GROUP_TOX; ++i) {
409 tox_callback_self_connection_status(toxes[i], &handle_self_connection_status);
410 tox_callback_friend_connection_status(toxes[i], &handle_friend_connection_status);
411 tox_callback_conference_invite(toxes[i], &handle_conference_invite);
412 tox_callback_conference_connected(toxes[i], &handle_conference_connected);
413 }
414
415 ck_assert_msg(toxav_add_av_groupchat(toxes[0], audio_callback, &state[0]) != UINT32_MAX, "failed to create group");
416 printf("tox #%u: inviting its first friend\n", state[0].index);
417 ck_assert_msg(tox_conference_invite(toxes[0], 0, 0, nullptr) != 0, "failed to invite friend");
418 state[0].invited_next = true;
419
420
421 printf("waiting for invitations to be made\n");
422 uint32_t invited_count = 0;
423
424 do {
425 iterate_all_wait(NUM_AV_GROUP_TOX, toxes, state, ITERATION_INTERVAL);
426
427 invited_count = 0;
428
429 for (uint32_t i = 0; i < NUM_AV_GROUP_TOX; ++i) {
430 invited_count += state[i].invited_next;
431 }
432 } while (invited_count != NUM_AV_GROUP_TOX - 1);
433
434 uint64_t pregroup_clock = state[0].clock;
435 printf("waiting for all toxes to be in the group\n");
436 uint32_t fully_connected_count = 0;
437
438 do {
439 fully_connected_count = 0;
440 iterate_all_wait(NUM_AV_GROUP_TOX, toxes, state, ITERATION_INTERVAL);
441
442 for (uint32_t i = 0; i < NUM_AV_GROUP_TOX; ++i) {
443 Tox_Err_Conference_Peer_Query err;
444 uint32_t peer_count = tox_conference_peer_count(toxes[i], 0, &err);
445
446 if (err != TOX_ERR_CONFERENCE_PEER_QUERY_OK) {
447 peer_count = 0;
448 }
449
450 fully_connected_count += peer_count == NUM_AV_GROUP_TOX;
451 }
452 } while (fully_connected_count != NUM_AV_GROUP_TOX);
453
454 printf("group connected, took %d seconds\n", (int)((state[0].clock - pregroup_clock) / 1000));
455
456 run_conference_tests(toxes, state);
457
458 printf("test_many_group succeeded, took %d seconds\n", (int)(time(nullptr) - test_start_time));
459}
460
461int main(void)
462{
463 setvbuf(stdout, nullptr, _IONBF, 0);
464
465 run_auto_test(NUM_AV_GROUP_TOX, test_groupav, true);
466 return 0;
467}
diff --git a/auto_tests/conference_test.c b/auto_tests/conference_test.c
index 349c2905..5f08b823 100644
--- a/auto_tests/conference_test.c
+++ b/auto_tests/conference_test.c
@@ -8,11 +8,8 @@
8#include <stdlib.h> 8#include <stdlib.h>
9#include <string.h> 9#include <string.h>
10#include <time.h> 10#include <time.h>
11#include <stdint.h>
11 12
12#include "../testing/misc_tools.h"
13#include "../toxcore/crypto_core.h"
14#include "../toxcore/tox.h"
15#include "../toxcore/util.h"
16#include "check_compat.h" 13#include "check_compat.h"
17 14
18#define NUM_GROUP_TOX 16 15#define NUM_GROUP_TOX 16
@@ -91,7 +88,7 @@ static void handle_conference_connected(
91 state->invited_next = true; 88 state->invited_next = true;
92} 89}
93 90
94static uint16_t num_recv; 91static uint32_t num_recv;
95 92
96static void handle_conference_message( 93static void handle_conference_message(
97 Tox *tox, uint32_t groupnumber, uint32_t peernumber, Tox_Message_Type type, 94 Tox *tox, uint32_t groupnumber, uint32_t peernumber, Tox_Message_Type type,
@@ -102,15 +99,21 @@ static void handle_conference_message(
102 } 99 }
103} 100}
104 101
105static bool toxes_are_disconnected_from_group(uint32_t tox_count, Tox **toxes, int disconnected_count, 102static bool toxes_are_disconnected_from_group(uint32_t tox_count, Tox **toxes,
106 bool *disconnected) 103 bool *disconnected)
107{ 104{
105 uint32_t num_disconnected = 0;
106
107 for (uint32_t i = 0; i < tox_count; ++i) {
108 num_disconnected += disconnected[i];
109 }
110
108 for (uint32_t i = 0; i < tox_count; i++) { 111 for (uint32_t i = 0; i < tox_count; i++) {
109 if (disconnected[i]) { 112 if (disconnected[i]) {
110 continue; 113 continue;
111 } 114 }
112 115
113 if (tox_conference_peer_count(toxes[i], 0, nullptr) > tox_count - NUM_DISCONNECT) { 116 if (tox_conference_peer_count(toxes[i], 0, nullptr) > tox_count - num_disconnected) {
114 return false; 117 return false;
115 } 118 }
116 } 119 }
@@ -118,6 +121,36 @@ static bool toxes_are_disconnected_from_group(uint32_t tox_count, Tox **toxes, i
118 return true; 121 return true;
119} 122}
120 123
124static void disconnect_toxes(uint32_t tox_count, Tox **toxes, State *state,
125 const bool *disconnect, const bool *exclude)
126{
127 /* Fake a network outage for a set of peers D by iterating only the other
128 * peers D' until the connections time out according to D', then iterating
129 * only D until the connections time out according to D. */
130
131 VLA(bool, disconnect_now, tox_count);
132 bool invert = false;
133
134 do {
135 for (uint32_t i = 0; i < tox_count; ++i) {
136 disconnect_now[i] = exclude[i] || (invert ^ disconnect[i]);
137 }
138
139 do {
140 for (uint32_t i = 0; i < tox_count; ++i) {
141 if (!disconnect_now[i]) {
142 tox_iterate(toxes[i], &state[i]);
143 state[i].clock += 1000;
144 }
145 }
146
147 c_sleep(20);
148 } while (!toxes_are_disconnected_from_group(tox_count, toxes, disconnect_now));
149
150 invert = !invert;
151 } while (invert);
152}
153
121static bool all_connected_to_group(uint32_t tox_count, Tox **toxes) 154static bool all_connected_to_group(uint32_t tox_count, Tox **toxes)
122{ 155{
123 for (uint32_t i = 0; i < tox_count; i++) { 156 for (uint32_t i = 0; i < tox_count; i++) {
@@ -131,8 +164,8 @@ static bool all_connected_to_group(uint32_t tox_count, Tox **toxes)
131 164
132static bool names_propagated(uint32_t tox_count, Tox **toxes, State *state) 165static bool names_propagated(uint32_t tox_count, Tox **toxes, State *state)
133{ 166{
134 for (uint16_t i = 0; i < tox_count; ++i) { 167 for (uint32_t i = 0; i < tox_count; ++i) {
135 for (uint16_t j = 0; j < tox_count; ++j) { 168 for (uint32_t j = 0; j < tox_count; ++j) {
136 const size_t len = tox_conference_peer_get_name_size(toxes[i], 0, j, nullptr); 169 const size_t len = tox_conference_peer_get_name_size(toxes[i], 0, j, nullptr);
137 170
138 if (len != NAMELEN) { 171 if (len != NAMELEN) {
@@ -145,9 +178,10 @@ static bool names_propagated(uint32_t tox_count, Tox **toxes, State *state)
145} 178}
146 179
147 180
148/* returns a random index at which a list of booleans is false 181/**
182 * returns a random index at which a list of booleans is false
149 * (some such index is required to exist) 183 * (some such index is required to exist)
150 * */ 184 */
151static uint32_t random_false_index(bool *list, const uint32_t length) 185static uint32_t random_false_index(bool *list, const uint32_t length)
152{ 186{
153 uint32_t index; 187 uint32_t index;
@@ -171,7 +205,7 @@ static void run_conference_tests(Tox **toxes, State *state)
171 205
172 ck_assert(NUM_DISCONNECT < NUM_GROUP_TOX); 206 ck_assert(NUM_DISCONNECT < NUM_GROUP_TOX);
173 207
174 for (uint16_t i = 0; i < NUM_DISCONNECT; ++i) { 208 for (uint32_t i = 0; i < NUM_DISCONNECT; ++i) {
175 uint32_t disconnect = random_false_index(disconnected, NUM_GROUP_TOX); 209 uint32_t disconnect = random_false_index(disconnected, NUM_GROUP_TOX);
176 disconnected[disconnect] = true; 210 disconnected[disconnect] = true;
177 211
@@ -186,7 +220,7 @@ static void run_conference_tests(Tox **toxes, State *state)
186 uint8_t *save[NUM_GROUP_TOX]; 220 uint8_t *save[NUM_GROUP_TOX];
187 size_t save_size[NUM_GROUP_TOX]; 221 size_t save_size[NUM_GROUP_TOX];
188 222
189 for (uint16_t i = 0; i < NUM_GROUP_TOX; ++i) { 223 for (uint32_t i = 0; i < NUM_GROUP_TOX; ++i) {
190 if (restarting[i]) { 224 if (restarting[i]) {
191 save_size[i] = tox_get_savedata_size(toxes[i]); 225 save_size[i] = tox_get_savedata_size(toxes[i]);
192 ck_assert_msg(save_size[i] != 0, "save is invalid size %u", (unsigned)save_size[i]); 226 ck_assert_msg(save_size[i] != 0, "save is invalid size %u", (unsigned)save_size[i]);
@@ -197,18 +231,9 @@ static void run_conference_tests(Tox **toxes, State *state)
197 } 231 }
198 } 232 }
199 233
200 do { 234 disconnect_toxes(NUM_GROUP_TOX, toxes, state, disconnected, restarting);
201 for (uint16_t i = 0; i < NUM_GROUP_TOX; ++i) {
202 if (!disconnected[i]) {
203 tox_iterate(toxes[i], &state[i]);
204 state[i].clock += 1000;
205 }
206 }
207 235
208 c_sleep(20); 236 for (uint32_t i = 0; i < NUM_GROUP_TOX; ++i) {
209 } while (!toxes_are_disconnected_from_group(NUM_GROUP_TOX, toxes, NUM_DISCONNECT, disconnected));
210
211 for (uint16_t i = 0; i < NUM_GROUP_TOX; ++i) {
212 if (restarting[i]) { 237 if (restarting[i]) {
213 struct Tox_Options *const options = tox_options_new(nullptr); 238 struct Tox_Options *const options = tox_options_new(nullptr);
214 tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_TOX_SAVE); 239 tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_TOX_SAVE);
@@ -216,13 +241,15 @@ static void run_conference_tests(Tox **toxes, State *state)
216 toxes[i] = tox_new_log(options, nullptr, &state[i].index); 241 toxes[i] = tox_new_log(options, nullptr, &state[i].index);
217 tox_options_free(options); 242 tox_options_free(options);
218 free(save[i]); 243 free(save[i]);
244
245 set_mono_time_callback(toxes[i], &state[i]);
219 } 246 }
220 } 247 }
221 248
222 if (check_name_change_propagation) { 249 if (check_name_change_propagation) {
223 printf("changing names\n"); 250 printf("changing names\n");
224 251
225 for (uint16_t i = 0; i < NUM_GROUP_TOX; ++i) { 252 for (uint32_t i = 0; i < NUM_GROUP_TOX; ++i) {
226 char name[NAMELEN + 1]; 253 char name[NAMELEN + 1];
227 snprintf(name, NAMELEN + 1, NEW_NAME_FORMAT_STR, state[i].index); 254 snprintf(name, NAMELEN + 1, NEW_NAME_FORMAT_STR, state[i].index);
228 tox_self_set_name(toxes[i], (const uint8_t *)name, NAMELEN, nullptr); 255 tox_self_set_name(toxes[i], (const uint8_t *)name, NAMELEN, nullptr);
@@ -237,7 +264,7 @@ static void run_conference_tests(Tox **toxes, State *state)
237 264
238 printf("running conference tests\n"); 265 printf("running conference tests\n");
239 266
240 for (uint16_t i = 0; i < NUM_GROUP_TOX; ++i) { 267 for (uint32_t i = 0; i < NUM_GROUP_TOX; ++i) {
241 tox_callback_conference_message(toxes[i], &handle_conference_message); 268 tox_callback_conference_message(toxes[i], &handle_conference_message);
242 269
243 iterate_all_wait(NUM_GROUP_TOX, toxes, state, ITERATION_INTERVAL); 270 iterate_all_wait(NUM_GROUP_TOX, toxes, state, ITERATION_INTERVAL);
@@ -259,8 +286,8 @@ static void run_conference_tests(Tox **toxes, State *state)
259 ck_assert_msg(num_recv == NUM_GROUP_TOX, "failed to recv group messages"); 286 ck_assert_msg(num_recv == NUM_GROUP_TOX, "failed to recv group messages");
260 287
261 if (check_name_change_propagation) { 288 if (check_name_change_propagation) {
262 for (uint16_t i = 0; i < NUM_GROUP_TOX; ++i) { 289 for (uint32_t i = 0; i < NUM_GROUP_TOX; ++i) {
263 for (uint16_t j = 0; j < NUM_GROUP_TOX; ++j) { 290 for (uint32_t j = 0; j < NUM_GROUP_TOX; ++j) {
264 uint8_t name[NAMELEN]; 291 uint8_t name[NAMELEN];
265 tox_conference_peer_get_name(toxes[i], 0, j, name, nullptr); 292 tox_conference_peer_get_name(toxes[i], 0, j, name, nullptr);
266 /* Note the toxes will have been reordered */ 293 /* Note the toxes will have been reordered */
@@ -270,14 +297,14 @@ static void run_conference_tests(Tox **toxes, State *state)
270 } 297 }
271 } 298 }
272 299
273 for (uint16_t k = NUM_GROUP_TOX; k != 0 ; --k) { 300 for (uint32_t k = NUM_GROUP_TOX; k != 0 ; --k) {
274 tox_conference_delete(toxes[k - 1], 0, nullptr); 301 tox_conference_delete(toxes[k - 1], 0, nullptr);
275 302
276 for (uint8_t j = 0; j < 10 || j < NUM_GROUP_TOX; ++j) { 303 for (uint8_t j = 0; j < 10 || j < NUM_GROUP_TOX; ++j) {
277 iterate_all_wait(NUM_GROUP_TOX, toxes, state, ITERATION_INTERVAL); 304 iterate_all_wait(NUM_GROUP_TOX, toxes, state, ITERATION_INTERVAL);
278 } 305 }
279 306
280 for (uint16_t i = 0; i < k - 1; ++i) { 307 for (uint32_t i = 0; i < k - 1; ++i) {
281 uint32_t peer_count = tox_conference_peer_count(toxes[i], 0, nullptr); 308 uint32_t peer_count = tox_conference_peer_count(toxes[i], 0, nullptr);
282 ck_assert_msg(peer_count == (k - 1), "\n\tBad number of group peers (post check)." 309 ck_assert_msg(peer_count == (k - 1), "\n\tBad number of group peers (post check)."
283 "\n\t\t\tExpected: %u but tox_instance(%u) only has: %u\n\n", 310 "\n\t\t\tExpected: %u but tox_instance(%u) only has: %u\n\n",
@@ -290,7 +317,7 @@ static void test_many_group(Tox **toxes, State *state)
290{ 317{
291 const time_t test_start_time = time(nullptr); 318 const time_t test_start_time = time(nullptr);
292 319
293 for (uint16_t i = 0; i < NUM_GROUP_TOX; ++i) { 320 for (uint32_t i = 0; i < NUM_GROUP_TOX; ++i) {
294 tox_callback_self_connection_status(toxes[i], &handle_self_connection_status); 321 tox_callback_self_connection_status(toxes[i], &handle_self_connection_status);
295 tox_callback_friend_connection_status(toxes[i], &handle_friend_connection_status); 322 tox_callback_friend_connection_status(toxes[i], &handle_friend_connection_status);
296 tox_callback_conference_invite(toxes[i], &handle_conference_invite); 323 tox_callback_conference_invite(toxes[i], &handle_conference_invite);
@@ -310,21 +337,21 @@ static void test_many_group(Tox **toxes, State *state)
310 337
311 338
312 printf("waiting for invitations to be made\n"); 339 printf("waiting for invitations to be made\n");
313 uint16_t invited_count = 0; 340 uint32_t invited_count = 0;
314 341
315 do { 342 do {
316 iterate_all_wait(NUM_GROUP_TOX, toxes, state, ITERATION_INTERVAL); 343 iterate_all_wait(NUM_GROUP_TOX, toxes, state, ITERATION_INTERVAL);
317 344
318 invited_count = 0; 345 invited_count = 0;
319 346
320 for (uint16_t i = 0; i < NUM_GROUP_TOX; ++i) { 347 for (uint32_t i = 0; i < NUM_GROUP_TOX; ++i) {
321 invited_count += state[i].invited_next; 348 invited_count += state[i].invited_next;
322 } 349 }
323 } while (invited_count != NUM_GROUP_TOX - 1); 350 } while (invited_count != NUM_GROUP_TOX - 1);
324 351
325 uint64_t pregroup_clock = state[0].clock; 352 uint64_t pregroup_clock = state[0].clock;
326 printf("waiting for all toxes to be in the group\n"); 353 printf("waiting for all toxes to be in the group\n");
327 uint16_t fully_connected_count = 0; 354 uint32_t fully_connected_count = 0;
328 355
329 do { 356 do {
330 fully_connected_count = 0; 357 fully_connected_count = 0;
@@ -332,7 +359,7 @@ static void test_many_group(Tox **toxes, State *state)
332 359
333 iterate_all_wait(NUM_GROUP_TOX, toxes, state, ITERATION_INTERVAL); 360 iterate_all_wait(NUM_GROUP_TOX, toxes, state, ITERATION_INTERVAL);
334 361
335 for (uint16_t i = 0; i < NUM_GROUP_TOX; ++i) { 362 for (uint32_t i = 0; i < NUM_GROUP_TOX; ++i) {
336 Tox_Err_Conference_Peer_Query err; 363 Tox_Err_Conference_Peer_Query err;
337 uint32_t peer_count = tox_conference_peer_count(toxes[i], 0, &err); 364 uint32_t peer_count = tox_conference_peer_count(toxes[i], 0, &err);
338 365
@@ -353,7 +380,7 @@ static void test_many_group(Tox **toxes, State *state)
353 fflush(stdout); 380 fflush(stdout);
354 } while (fully_connected_count != NUM_GROUP_TOX); 381 } while (fully_connected_count != NUM_GROUP_TOX);
355 382
356 for (uint16_t i = 0; i < NUM_GROUP_TOX; ++i) { 383 for (uint32_t i = 0; i < NUM_GROUP_TOX; ++i) {
357 uint32_t peer_count = tox_conference_peer_count(toxes[i], 0, nullptr); 384 uint32_t peer_count = tox_conference_peer_count(toxes[i], 0, nullptr);
358 385
359 ck_assert_msg(peer_count == NUM_GROUP_TOX, "\n\tBad number of group peers (pre check)." 386 ck_assert_msg(peer_count == NUM_GROUP_TOX, "\n\tBad number of group peers (pre check)."
diff --git a/auto_tests/run_auto_test.h b/auto_tests/run_auto_test.h
index 4f2dc278..47d9dc4a 100644
--- a/auto_tests/run_auto_test.h
+++ b/auto_tests/run_auto_test.h
@@ -48,6 +48,15 @@ static uint64_t get_state_clock_callback(Mono_Time *mono_time, void *user_data)
48 return state->clock; 48 return state->clock;
49} 49}
50 50
51static void set_mono_time_callback(Tox *tox, State *state)
52{
53 // TODO(iphydf): Don't rely on toxcore internals.
54 Mono_Time *mono_time = ((Messenger *)tox)->mono_time;
55
56 state->clock = current_time_monotonic(mono_time);
57 mono_time_set_current_time_callback(mono_time, get_state_clock_callback, state);
58}
59
51static void run_auto_test(uint32_t tox_count, void test(Tox **toxes, State *state), bool chain) 60static void run_auto_test(uint32_t tox_count, void test(Tox **toxes, State *state), bool chain)
52{ 61{
53 printf("initialising %u toxes\n", tox_count); 62 printf("initialising %u toxes\n", tox_count);
@@ -59,11 +68,7 @@ static void run_auto_test(uint32_t tox_count, void test(Tox **toxes, State *stat
59 toxes[i] = tox_new_log(nullptr, nullptr, &state[i].index); 68 toxes[i] = tox_new_log(nullptr, nullptr, &state[i].index);
60 ck_assert_msg(toxes[i], "failed to create %u tox instances", i + 1); 69 ck_assert_msg(toxes[i], "failed to create %u tox instances", i + 1);
61 70
62 // TODO(iphydf): Don't rely on toxcore internals. 71 set_mono_time_callback(toxes[i], &state[i]);
63 Mono_Time *mono_time = (*(Messenger **)toxes[i])->mono_time;
64
65 state[i].clock = current_time_monotonic(mono_time);
66 mono_time_set_current_time_callback(mono_time, get_state_clock_callback, &state[i]);
67 } 72 }
68 73
69 if (chain) { 74 if (chain) {