diff --git a/.circleci/config.yml b/.circleci/config.yml index 5e8ad896..e0d4d2b1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -71,6 +71,7 @@ jobs: - run: *apt_install - checkout - run: infer --no-progress-bar -- cc + auto_tests/auto_test_support.c auto_tests/lossless_packet_test.c testing/misc_tools.c toxav/*.c diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ae55b463..77eeb29c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -106,6 +106,7 @@ jobs: -o send_message_test -Wall -Werror -bench -g + auto_tests/auto_test_support.c auto_tests/send_message_test.c testing/misc_tools.c toxav/*.c @@ -117,6 +118,7 @@ jobs: - name: Build amalgamation file with TCC run: other/make_single_file + auto_tests/auto_test_support.c auto_tests/send_message_test.c testing/misc_tools.c | tcc - @@ -141,6 +143,7 @@ jobs: -Wno-unknown-pragmas -Wno-unused-variable -fstruct-passing -fno-unprototyped -g + auto_tests/auto_test_support.c auto_tests/send_message_test.c testing/misc_tools.c toxav/*.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 5048be96..ffaa9cb4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -391,11 +391,18 @@ endif() option(AUTOTEST "Enable autotests (mainly for CI)" OFF) +if(AUTOTEST) + add_library(auto_test_support + auto_tests/auto_test_support.c + auto_tests/auto_test_support.h) + target_link_modules(auto_test_support toxcore misc_tools) +endif() + function(auto_test target) if(AUTOTEST AND NOT (MSVC AND ARGV1 STREQUAL "MSVC_DONT_BUILD")) add_executable(auto_${target}_test ${CPUFEATURES} auto_tests/${target}_test.c) - target_link_modules(auto_${target}_test toxcore misc_tools) + target_link_modules(auto_${target}_test toxcore misc_tools auto_test_support) if(NOT ARGV1 STREQUAL "DONT_RUN") add_test(NAME ${target} COMMAND ${CROSSCOMPILING_EMULATOR} auto_${target}_test) set_tests_properties(${target} PROPERTIES TIMEOUT "${TEST_TIMEOUT_SECONDS}") diff --git a/auto_tests/BUILD.bazel b/auto_tests/BUILD.bazel index dabea2d6..000b8ee9 100644 --- a/auto_tests/BUILD.bazel +++ b/auto_tests/BUILD.bazel @@ -9,9 +9,17 @@ cc_library( ) cc_library( - name = "run_auto_test", + name = "auto_test_support", testonly = True, - hdrs = ["run_auto_test.h"], + srcs = ["auto_test_support.c"], + hdrs = ["auto_test_support.h"], + deps = [ + ":check_compat", + "//c-toxcore/testing:misc_tools", + "//c-toxcore/toxcore:Messenger", + "//c-toxcore/toxcore:mono_time", + "//c-toxcore/toxcore", + ], ) flaky_tests = { @@ -33,7 +41,7 @@ flaky_tests = { ), deps = [ ":check_compat", - ":run_auto_test", + ":auto_test_support", "//c-toxcore/testing:misc_tools", "//c-toxcore/toxav", "//c-toxcore/toxcore", diff --git a/auto_tests/Makefile.inc b/auto_tests/Makefile.inc index 71cda96f..a9c814c0 100644 --- a/auto_tests/Makefile.inc +++ b/auto_tests/Makefile.inc @@ -1,5 +1,9 @@ if BUILD_TESTS +noinst_LTLIBRARIES += libauto_test_support.la +libauto_test_support_la_SOURCES = ../auto_tests/auto_test_support.c ../auto_tests/auto_test_support.h +libauto_test_support_la_LIBADD = libmisc_tools.la libtoxcore.la + TESTS = \ conference_double_invite_test \ conference_invite_merge_test \ @@ -51,6 +55,7 @@ AUTOTEST_LDADD = \ $(LIBSODIUM_LDFLAGS) \ $(NACL_LDFLAGS) \ libmisc_tools.la \ + libauto_test_support.la \ libtoxcore.la \ libtoxencryptsave.la \ $(LIBSODIUM_LIBS) \ @@ -239,4 +244,4 @@ endif EXTRA_DIST += \ $(top_srcdir)/auto_tests/data/save.tox \ $(top_srcdir)/auto_tests/check_compat.h \ - $(top_srcdir)/auto_tests/run_auto_test.h + $(top_srcdir)/auto_tests/auto_test_support.h diff --git a/auto_tests/auto_test_support.c b/auto_tests/auto_test_support.c new file mode 100644 index 00000000..1ea437cd --- /dev/null +++ b/auto_tests/auto_test_support.c @@ -0,0 +1,309 @@ +#include // calloc, free + +#include "check_compat.h" +#include "../testing/misc_tools.h" +#include "../toxcore/Messenger.h" +#include "../toxcore/mono_time.h" + +#include "auto_test_support.h" + +const Run_Auto_Options default_run_auto_options = { GRAPH_COMPLETE, nullptr }; + +// List of live bootstrap nodes. These nodes should have TCP server enabled. +static const struct BootstrapNodes { + const char *ip; + uint16_t port; + const uint8_t key[32]; +} BootstrapNodes[] = { +#ifndef USE_TEST_NETWORK + { + "tox.abilinski.com", 33445, + 0x10, 0xC0, 0x0E, 0xB2, 0x50, 0xC3, 0x23, 0x3E, + 0x34, 0x3E, 0x2A, 0xEB, 0xA0, 0x71, 0x15, 0xA5, + 0xC2, 0x89, 0x20, 0xE9, 0xC8, 0xD2, 0x94, 0x92, + 0xF6, 0xD0, 0x0B, 0x29, 0x04, 0x9E, 0xDC, 0x7E, + }, + { + "tox.initramfs.io", 33445, + 0x02, 0x80, 0x7C, 0xF4, 0xF8, 0xBB, 0x8F, 0xB3, + 0x90, 0xCC, 0x37, 0x94, 0xBD, 0xF1, 0xE8, 0x44, + 0x9E, 0x9A, 0x83, 0x92, 0xC5, 0xD3, 0xF2, 0x20, + 0x00, 0x19, 0xDA, 0x9F, 0x1E, 0x81, 0x2E, 0x46, + }, + { + "tox.plastiras.org", 33445, + 0x8E, 0x8B, 0x63, 0x29, 0x9B, 0x3D, 0x52, 0x0F, + 0xB3, 0x77, 0xFE, 0x51, 0x00, 0xE6, 0x5E, 0x33, + 0x22, 0xF7, 0xAE, 0x5B, 0x20, 0xA0, 0xAC, 0xED, + 0x29, 0x81, 0x76, 0x9F, 0xC5, 0xB4, 0x37, 0x25, + }, + { + "tox.novg.net", 33445, + 0xD5, 0x27, 0xE5, 0x84, 0x7F, 0x83, 0x30, 0xD6, + 0x28, 0xDA, 0xB1, 0x81, 0x4F, 0x0A, 0x42, 0x2F, + 0x6D, 0xC9, 0xD0, 0xA3, 0x00, 0xE6, 0xC3, 0x57, + 0x63, 0x4E, 0xE2, 0xDA, 0x88, 0xC3, 0x54, 0x63, + }, +#else + { + "172.93.52.70", 33445, + 0x79, 0xCA, 0xDA, 0x49, 0x74, 0xB0, 0x92, 0x6F, + 0x28, 0x6F, 0x02, 0x5C, 0xD5, 0xFF, 0xDF, 0x3E, + 0x65, 0x4A, 0x37, 0x58, 0xC5, 0x3E, 0x02, 0x73, + 0xEC, 0xFC, 0x4D, 0x12, 0xC2, 0x1D, 0xCA, 0x48, + }, +#endif // USE_TEST_NETWORK + { nullptr, 0, 0 }, +}; + +void bootstrap_tox_live_network(Tox *tox, bool enable_tcp) +{ + for (size_t j = 0; BootstrapNodes[j].ip != nullptr; ++j) { + const char *ip = BootstrapNodes[j].ip; + uint16_t port = BootstrapNodes[j].port; + const uint8_t *key = BootstrapNodes[j].key; + + Tox_Err_Bootstrap err; + tox_bootstrap(tox, ip, port, key, &err); + + if (err != TOX_ERR_BOOTSTRAP_OK) { + fprintf(stderr, "Failed to bootstrap node %zu (%s): error %d\n", j, ip, err); + } + + if (enable_tcp) { + tox_add_tcp_relay(tox, ip, port, key, &err); + + if (err != TOX_ERR_BOOTSTRAP_OK) { + fprintf(stderr, "Failed to add TCP relay %zu (%s): error %d\n", j, ip, err); + } + } + } +} + +bool all_connected(uint32_t tox_count, AutoTox *autotoxes) +{ + for (uint32_t i = 0; i < tox_count; ++i) { + if (tox_self_get_connection_status(autotoxes[i].tox) == TOX_CONNECTION_NONE) { + return false; + } + } + + return true; +} + +bool all_friends_connected(uint32_t tox_count, AutoTox *autotoxes) +{ + for (uint32_t i = 0; i < tox_count; ++i) { + const size_t friend_count = tox_self_get_friend_list_size(autotoxes[i].tox); + + for (size_t j = 0; j < friend_count; ++j) { + if (tox_friend_get_connection_status(autotoxes[i].tox, j, nullptr) == TOX_CONNECTION_NONE) { + return false; + } + } + } + + return true; +} + +void iterate_all_wait(uint32_t tox_count, AutoTox *autotoxes, uint32_t wait) +{ + for (uint32_t i = 0; i < tox_count; ++i) { + if (autotoxes[i].alive) { + tox_iterate(autotoxes[i].tox, &autotoxes[i]); + autotoxes[i].clock += wait; + } + } + + /* Also actually sleep a little, to allow for local network processing */ + c_sleep(5); +} + +static uint64_t get_state_clock_callback(Mono_Time *mono_time, void *user_data) +{ + const uint64_t *clock = (const uint64_t *)user_data; + return *clock; +} + +void set_mono_time_callback(AutoTox *autotox) +{ + // TODO(iphydf): Don't rely on toxcore internals. + Mono_Time *mono_time = ((Messenger *)autotox->tox)->mono_time; + + autotox->clock = current_time_monotonic(mono_time); + mono_time_set_current_time_callback(mono_time, get_state_clock_callback, &autotox->clock); +} + +void save_autotox(AutoTox *autotox) +{ + ck_assert(autotox != nullptr); + + fprintf(stderr, "Saving #%u\n", autotox->index); + + free(autotox->save_state); + autotox->save_state = nullptr; + + autotox->save_size = tox_get_savedata_size(autotox->tox); + ck_assert_msg(autotox->save_size > 0, "save is invalid size %u", (unsigned)autotox->save_size); + autotox->save_state = (uint8_t *)malloc(autotox->save_size); + ck_assert_msg(autotox->save_state != nullptr, "malloc failed"); + tox_get_savedata(autotox->tox, autotox->save_state); +} + +void kill_autotox(AutoTox *autotox) +{ + ck_assert(autotox != nullptr); + ck_assert(autotox->alive); + fprintf(stderr, "Killing #%u\n", autotox->index); + autotox->alive = false; + tox_kill(autotox->tox); +} + +void reload(AutoTox *autotox) +{ + ck_assert(autotox != nullptr); + + if (autotox->alive) { + kill_autotox(autotox); + } + + fprintf(stderr, "Reloading #%u\n", autotox->index); + ck_assert(autotox->save_state != nullptr); + + struct Tox_Options *const options = tox_options_new(nullptr); + ck_assert(options != nullptr); + tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_TOX_SAVE); + tox_options_set_savedata_data(options, autotox->save_state, autotox->save_size); + autotox->tox = tox_new_log(options, nullptr, &autotox->index); + ck_assert(autotox->tox != nullptr); + tox_options_free(options); + + set_mono_time_callback(autotox); + autotox->alive = true; +} + +static void initialise_autotox(struct Tox_Options *options, AutoTox *autotox, uint32_t index, uint32_t state_size, + const Run_Auto_Options *autotest_opts) +{ + autotox->index = index; + autotox->tox = tox_new_log(options, nullptr, &autotox->index); + ck_assert_msg(autotox->tox != nullptr, "failed to create tox instance #%u", index); + + set_mono_time_callback(autotox); + + autotox->alive = true; + autotox->save_state = nullptr; + + if (state_size > 0) { + autotox->state = calloc(1, state_size); + ck_assert(autotox->state != nullptr); + ck_assert_msg(autotox->state != nullptr, "failed to allocate state"); + } else { + autotox->state = nullptr; + } + + if (autotest_opts->init_autotox != nullptr) { + autotest_opts->init_autotox(autotox, index); + } +} + +static void autotox_add_friend(AutoTox *autotoxes, uint32_t adding, uint32_t added) +{ + uint8_t public_key[TOX_PUBLIC_KEY_SIZE]; + tox_self_get_public_key(autotoxes[added].tox, public_key); + Tox_Err_Friend_Add err; + tox_friend_add_norequest(autotoxes[adding].tox, public_key, &err); + ck_assert(err == TOX_ERR_FRIEND_ADD_OK); +} + +static void initialise_friend_graph(Graph_Type graph, uint32_t num_toxes, AutoTox *autotoxes) +{ + if (graph == GRAPH_LINEAR) { + printf("toxes #%u-#%u each add adjacent toxes as friends\n", 0, num_toxes - 1); + + for (uint32_t i = 0; i < num_toxes; ++i) { + for (uint32_t j = i - 1; j != i + 3; j += 2) { + if (j < num_toxes) { + autotox_add_friend(autotoxes, i, j); + } + } + } + } else if (graph == GRAPH_COMPLETE) { + printf("toxes #%u-#%u add each other as friends\n", 0, num_toxes - 1); + + for (uint32_t i = 0; i < num_toxes; ++i) { + for (uint32_t j = 0; j < num_toxes; ++j) { + if (i != j) { + autotox_add_friend(autotoxes, i, j); + } + } + } + } else { + ck_abort_msg("Unknown graph type"); + } +} + +static void bootstrap_autotoxes(struct Tox_Options *options, uint32_t tox_count, const Run_Auto_Options *autotest_opts, + AutoTox *autotoxes) +{ + const bool udp_enabled = options != nullptr ? tox_options_get_udp_enabled(options) : true; + + if (udp_enabled) { + printf("bootstrapping all toxes off tox 0\n"); + uint8_t dht_key[TOX_PUBLIC_KEY_SIZE]; + tox_self_get_dht_id(autotoxes[0].tox, dht_key); + const uint16_t dht_port = tox_self_get_udp_port(autotoxes[0].tox, nullptr); + + for (uint32_t i = 1; i < tox_count; ++i) { + Tox_Err_Bootstrap err; + tox_bootstrap(autotoxes[i].tox, "localhost", dht_port, dht_key, &err); + ck_assert(err == TOX_ERR_BOOTSTRAP_OK); + } + } else { + printf("bootstrapping all toxes to tcp relays\n"); + + for (uint32_t i = 0; i < tox_count; ++i) { + bootstrap_tox_live_network(autotoxes[i].tox, true); + } + } +} + +void run_auto_test(struct Tox_Options *options, uint32_t tox_count, void test(AutoTox *autotoxes), + uint32_t state_size, const Run_Auto_Options *autotest_opts) +{ + printf("initialising %u toxes\n", tox_count); + + AutoTox *autotoxes = (AutoTox *)calloc(tox_count, sizeof(AutoTox)); + + ck_assert(autotoxes != nullptr); + + for (uint32_t i = 0; i < tox_count; ++i) { + initialise_autotox(options, &autotoxes[i], i, state_size, autotest_opts); + } + + initialise_friend_graph(autotest_opts->graph, tox_count, autotoxes); + + bootstrap_autotoxes(options, tox_count, autotest_opts, autotoxes); + + do { + iterate_all_wait(tox_count, autotoxes, ITERATION_INTERVAL); + } while (!all_connected(tox_count, autotoxes)); + + printf("toxes are online\n"); + + do { + iterate_all_wait(tox_count, autotoxes, ITERATION_INTERVAL); + } while (!all_friends_connected(tox_count, autotoxes)); + + printf("tox clients connected\n"); + + test(autotoxes); + + for (uint32_t i = 0; i < tox_count; ++i) { + tox_kill(autotoxes[i].tox); + free(autotoxes[i].state); + free(autotoxes[i].save_state); + } + + free(autotoxes); +} diff --git a/auto_tests/auto_test_support.h b/auto_tests/auto_test_support.h new file mode 100644 index 00000000..1c49cd77 --- /dev/null +++ b/auto_tests/auto_test_support.h @@ -0,0 +1,53 @@ +#ifndef RUN_AUTO_TEST_H +#define RUN_AUTO_TEST_H + +#include // calloc, free + +#include "check_compat.h" +#include "../testing/misc_tools.h" +#include "../toxcore/Messenger.h" +#include "../toxcore/mono_time.h" + +typedef struct AutoTox { + Tox *tox; + + uint32_t index; + uint64_t clock; + + size_t save_size; + uint8_t *save_state; + bool alive; + + void *state; +} AutoTox; + +bool all_connected(uint32_t tox_count, AutoTox *toxes); + +bool all_friends_connected(uint32_t tox_count, AutoTox *toxes); + +void iterate_all_wait(uint32_t tox_count, AutoTox *toxes, uint32_t wait); + +void save_autotox(AutoTox *autotox); +void kill_autotox(AutoTox *autotox); +void reload(AutoTox *autotox); + +void set_mono_time_callback(AutoTox *tox); + +typedef enum Graph_Type { + GRAPH_COMPLETE = 0, + GRAPH_LINEAR +} Graph_Type; + +typedef struct Run_Auto_Options { + Graph_Type graph; + void (*init_autotox)(AutoTox *autotox, uint32_t n); +} Run_Auto_Options; + +extern const Run_Auto_Options default_run_auto_options; + +void run_auto_test(struct Tox_Options *options, uint32_t tox_count, void test(AutoTox *autotoxes), + uint32_t state_size, const Run_Auto_Options *autotest_opts); + +void bootstrap_tox_live_network(Tox *tox, bool enable_tcp); + +#endif diff --git a/auto_tests/bootstrap_test.c b/auto_tests/bootstrap_test.c index c5c30c2d..b9b1965e 100644 --- a/auto_tests/bootstrap_test.c +++ b/auto_tests/bootstrap_test.c @@ -3,12 +3,7 @@ #include "../testing/misc_tools.h" #include "check_compat.h" -typedef struct State { - uint32_t index; - uint64_t clock; -} State; - -#include "run_auto_test.h" +#include "auto_test_support.h" int main(void) { @@ -16,7 +11,7 @@ int main(void) Tox *tox_udp = tox_new_log(nullptr, nullptr, nullptr); - bootstrap_toxes_live_network(&tox_udp, 1, false); + bootstrap_tox_live_network(tox_udp, false); printf("Waiting for connection"); @@ -35,7 +30,5 @@ int main(void) tox_kill(tox_udp); - (void)run_auto_test; - return 0; } diff --git a/auto_tests/conference_av_test.c b/auto_tests/conference_av_test.c index b9a69aa2..7ee25ab0 100644 --- a/auto_tests/conference_av_test.c +++ b/auto_tests/conference_av_test.c @@ -13,51 +13,49 @@ #define NUM_AV_DISCONNECT (NUM_AV_GROUP_TOX / 2) #define NUM_AV_DISABLE (NUM_AV_GROUP_TOX / 2) -typedef struct State { - uint32_t index; - uint64_t clock; +#include "auto_test_support.h" +typedef struct State { bool invited_next; uint32_t received_audio_peers[NUM_AV_GROUP_TOX]; uint32_t received_audio_num; } State; -#include "run_auto_test.h" - static void handle_self_connection_status( Tox *tox, Tox_Connection connection_status, void *user_data) { - const State *state = (State *)user_data; + const AutoTox *autotox = (AutoTox *)user_data; if (connection_status != TOX_CONNECTION_NONE) { - printf("tox #%u: is now connected\n", state->index); + printf("tox #%u: is now connected\n", autotox->index); } else { - printf("tox #%u: is now disconnected\n", state->index); + printf("tox #%u: is now disconnected\n", autotox->index); } } static void handle_friend_connection_status( Tox *tox, uint32_t friendnumber, Tox_Connection connection_status, void *user_data) { - const State *state = (State *)user_data; + const AutoTox *autotox = (AutoTox *)user_data; if (connection_status != TOX_CONNECTION_NONE) { - printf("tox #%u: is now connected to friend %u\n", state->index, friendnumber); + printf("tox #%u: is now connected to friend %u\n", autotox->index, friendnumber); } else { - printf("tox #%u: is now disconnected from friend %u\n", state->index, friendnumber); + printf("tox #%u: is now disconnected from friend %u\n", autotox->index, friendnumber); } } static void audio_callback(void *tox, uint32_t groupnumber, uint32_t peernumber, const int16_t *pcm, unsigned int samples, uint8_t channels, uint32_t - sample_rate, void *userdata) + sample_rate, void *user_data) { if (samples == 0) { return; } - State *state = (State *)userdata; + const AutoTox *autotox = (AutoTox *)user_data; + State *state = (State *)autotox->state; for (uint32_t i = 0; i < state->received_audio_num; ++i) { if (state->received_audio_peers[i] == peernumber) { @@ -75,17 +73,18 @@ static void handle_conference_invite( Tox *tox, uint32_t friendnumber, Tox_Conference_Type type, const uint8_t *data, size_t length, void *user_data) { - const State *state = (State *)user_data; - ck_assert_msg(type == TOX_CONFERENCE_TYPE_AV, "tox #%u: wrong conference type: %d", state->index, type); + const AutoTox *autotox = (AutoTox *)user_data; + ck_assert_msg(type == TOX_CONFERENCE_TYPE_AV, "tox #%u: wrong conference type: %d", autotox->index, type); ck_assert_msg(toxav_join_av_groupchat(tox, friendnumber, data, length, audio_callback, user_data) == 0, - "tox #%u: failed to join group", state->index); + "tox #%u: failed to join group", autotox->index); } static void handle_conference_connected( Tox *tox, uint32_t conference_number, void *user_data) { - State *state = (State *)user_data; + const AutoTox *autotox = (AutoTox *)user_data; + State *state = (State *)autotox->state; if (state->invited_next || tox_self_get_friend_list_size(tox) <= 1) { return; @@ -93,12 +92,13 @@ static void handle_conference_connected( Tox_Err_Conference_Invite err; tox_conference_invite(tox, 1, 0, &err); - ck_assert_msg(err == TOX_ERR_CONFERENCE_INVITE_OK, "tox #%u failed to invite next friend: err = %d", state->index, err); - printf("tox #%u: invited next friend\n", state->index); + ck_assert_msg(err == TOX_ERR_CONFERENCE_INVITE_OK, "tox #%u failed to invite next friend: err = %d", autotox->index, + err); + printf("tox #%u: invited next friend\n", autotox->index); state->invited_next = true; } -static bool toxes_are_disconnected_from_group(uint32_t tox_count, Tox **toxes, +static bool toxes_are_disconnected_from_group(uint32_t tox_count, AutoTox *autotoxes, bool *disconnected) { uint32_t num_disconnected = 0; @@ -112,7 +112,7 @@ static bool toxes_are_disconnected_from_group(uint32_t tox_count, Tox **toxes, continue; } - if (tox_conference_peer_count(toxes[i], 0, nullptr) > tox_count - num_disconnected) { + if (tox_conference_peer_count(autotoxes[i].tox, 0, nullptr) > tox_count - num_disconnected) { return false; } } @@ -120,7 +120,7 @@ static bool toxes_are_disconnected_from_group(uint32_t tox_count, Tox **toxes, return true; } -static void disconnect_toxes(uint32_t tox_count, Tox **toxes, State *state, +static void disconnect_toxes(uint32_t tox_count, AutoTox *autotoxes, const bool *disconnect, const bool *exclude) { /* Fake a network outage for a set of peers D by iterating only the other @@ -138,22 +138,22 @@ static void disconnect_toxes(uint32_t tox_count, Tox **toxes, State *state, do { for (uint32_t i = 0; i < tox_count; ++i) { if (!disconnect_now[i]) { - tox_iterate(toxes[i], &state[i]); - state[i].clock += 1000; + tox_iterate(autotoxes[i].tox, &autotoxes[i]); + autotoxes[i].clock += 1000; } } c_sleep(20); - } while (!toxes_are_disconnected_from_group(tox_count, toxes, disconnect_now)); + } while (!toxes_are_disconnected_from_group(tox_count, autotoxes, disconnect_now)); invert = !invert; } while (invert); } -static bool all_connected_to_group(uint32_t tox_count, Tox **toxes) +static bool all_connected_to_group(uint32_t tox_count, AutoTox *autotoxes) { for (uint32_t i = 0; i < tox_count; ++i) { - if (tox_conference_peer_count(toxes[i], 0, nullptr) < tox_count) { + if (tox_conference_peer_count(autotoxes[i].tox, 0, nullptr) < tox_count) { return false; } } @@ -176,7 +176,7 @@ static uint32_t random_false_index(bool *list, const uint32_t length) return index; } -static bool all_got_audio(State *state, const bool *disabled) +static bool all_got_audio(AutoTox *autotoxes, const bool *disabled) { uint32_t num_disabled = 0; @@ -185,7 +185,9 @@ static bool all_got_audio(State *state, const bool *disabled) } for (uint32_t i = 0; i < NUM_AV_GROUP_TOX; ++i) { - if (disabled[i] ^ (state[i].received_audio_num + State *state = (State *)autotoxes[i].state; + + if (disabled[i] ^ (state->received_audio_num != NUM_AV_GROUP_TOX - num_disabled - 1)) { return false; } @@ -194,10 +196,10 @@ static bool all_got_audio(State *state, const bool *disabled) return true; } -static void reset_received_audio(Tox **toxes, State *state) +static void reset_received_audio(AutoTox *autotoxes) { for (uint32_t j = 0; j < NUM_AV_GROUP_TOX; ++j) { - state[j].received_audio_num = 0; + ((State *)autotoxes[j].state)->received_audio_num = 0; } } @@ -209,7 +211,7 @@ static void reset_received_audio(Tox **toxes, State *state) * buffers fill up. */ #define GROUP_AV_AUDIO_ITERATIONS (8 + NUM_AV_GROUP_TOX) -static bool test_audio(Tox **toxes, State *state, const bool *disabled, bool quiet) +static bool test_audio(AutoTox *autotoxes, const bool *disabled, bool quiet) { if (!quiet) { printf("testing sending and receiving audio\n"); @@ -217,7 +219,7 @@ static bool test_audio(Tox **toxes, State *state, const bool *disabled, bool qui const int16_t PCM[GROUP_AV_TEST_SAMPLES] = {0}; - reset_received_audio(toxes, state); + reset_received_audio(autotoxes); for (uint32_t n = 0; n < GROUP_AV_AUDIO_ITERATIONS; ++n) { for (uint32_t i = 0; i < NUM_AV_GROUP_TOX; ++i) { @@ -225,18 +227,18 @@ static bool test_audio(Tox **toxes, State *state, const bool *disabled, bool qui continue; } - if (toxav_group_send_audio(toxes[i], 0, PCM, GROUP_AV_TEST_SAMPLES, 1, 48000) != 0) { + if (toxav_group_send_audio(autotoxes[i].tox, 0, PCM, GROUP_AV_TEST_SAMPLES, 1, 48000) != 0) { if (!quiet) { - ck_abort_msg("#%u failed to send audio", state[i].index); + ck_abort_msg("#%u failed to send audio", autotoxes[i].index); } return false; } } - iterate_all_wait(NUM_AV_GROUP_TOX, toxes, state, ITERATION_INTERVAL); + iterate_all_wait(NUM_AV_GROUP_TOX, autotoxes, ITERATION_INTERVAL); - if (all_got_audio(state, disabled)) { + if (all_got_audio(autotoxes, disabled)) { return true; } } @@ -248,32 +250,32 @@ static bool test_audio(Tox **toxes, State *state, const bool *disabled, bool qui return false; } -static void test_eventual_audio(Tox **toxes, State *state, const bool *disabled, uint64_t timeout) +static void test_eventual_audio(AutoTox *autotoxes, const bool *disabled, uint64_t timeout) { - uint64_t start = state[0].clock; + uint64_t start = autotoxes[0].clock; - while (state[0].clock < start + timeout) { - if (test_audio(toxes, state, disabled, true) - && test_audio(toxes, state, disabled, true)) { - printf("audio test successful after %d seconds\n", (int)((state[0].clock - start) / 1000)); + while (autotoxes[0].clock < start + timeout) { + if (test_audio(autotoxes, disabled, true) + && test_audio(autotoxes, disabled, true)) { + printf("audio test successful after %d seconds\n", (int)((autotoxes[0].clock - start) / 1000)); return; } } printf("audio seems not to be getting through: testing again with errors.\n"); - test_audio(toxes, state, disabled, false); + test_audio(autotoxes, disabled, false); } -static void do_audio(Tox **toxes, State *state, uint32_t iterations) +static void do_audio(AutoTox *autotoxes, uint32_t iterations) { const int16_t PCM[GROUP_AV_TEST_SAMPLES] = {0}; printf("running audio for %u iterations\n", iterations); for (uint32_t f = 0; f < iterations; ++f) { for (uint32_t i = 0; i < NUM_AV_GROUP_TOX; ++i) { - ck_assert_msg(toxav_group_send_audio(toxes[i], 0, PCM, GROUP_AV_TEST_SAMPLES, 1, 48000) == 0, - "#%u failed to send audio", state[i].index); - iterate_all_wait(NUM_AV_GROUP_TOX, toxes, state, ITERATION_INTERVAL); + ck_assert_msg(toxav_group_send_audio(autotoxes[i].tox, 0, PCM, GROUP_AV_TEST_SAMPLES, 1, 48000) == 0, + "#%u failed to send audio", autotoxes[i].index); + iterate_all_wait(NUM_AV_GROUP_TOX, autotoxes, ITERATION_INTERVAL); } } } @@ -283,15 +285,15 @@ static void do_audio(Tox **toxes, State *state, uint32_t iterations) #define JITTER_SETTLE_TIME (GROUP_JBUF_DEAD_SECONDS*1000 + NUM_AV_GROUP_TOX*ITERATION_INTERVAL*(GROUP_AV_AUDIO_ITERATIONS+1)) -static void run_conference_tests(Tox **toxes, State *state) +static void run_conference_tests(AutoTox *autotoxes) { bool disabled[NUM_AV_GROUP_TOX] = {0}; - test_audio(toxes, state, disabled, false); + test_audio(autotoxes, disabled, false); /* have everyone send audio for a bit so we can test that the audio * sequnums dropping to 0 on restart isn't a problem */ - do_audio(toxes, state, 20); + do_audio(autotoxes, 20); printf("letting random toxes timeout\n"); bool disconnected[NUM_AV_GROUP_TOX] = {0}; @@ -305,55 +307,41 @@ static void run_conference_tests(Tox **toxes, State *state) if (i < NUM_AV_DISCONNECT / 2) { restarting[disconnect] = true; - printf("Restarting #%u\n", state[disconnect].index); + printf("Restarting #%u\n", autotoxes[disconnect].index); } else { - printf("Disconnecting #%u\n", state[disconnect].index); + printf("Disconnecting #%u\n", autotoxes[disconnect].index); } } - uint8_t *save[NUM_AV_GROUP_TOX]; - size_t save_size[NUM_AV_GROUP_TOX]; - for (uint32_t i = 0; i < NUM_AV_GROUP_TOX; ++i) { if (restarting[i]) { - save_size[i] = tox_get_savedata_size(toxes[i]); - ck_assert_msg(save_size[i] != 0, "save is invalid size %u", (unsigned)save_size[i]); - save[i] = (uint8_t *)malloc(save_size[i]); - ck_assert_msg(save[i] != nullptr, "malloc failed"); - tox_get_savedata(toxes[i], save[i]); - tox_kill(toxes[i]); + save_autotox(&autotoxes[i]); + kill_autotox(&autotoxes[i]); } } - disconnect_toxes(NUM_AV_GROUP_TOX, toxes, state, disconnected, restarting); + disconnect_toxes(NUM_AV_GROUP_TOX, autotoxes, disconnected, restarting); for (uint32_t i = 0; i < NUM_AV_GROUP_TOX; ++i) { if (restarting[i]) { - struct Tox_Options *const options = tox_options_new(nullptr); - tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_TOX_SAVE); - tox_options_set_savedata_data(options, save[i], save_size[i]); - toxes[i] = tox_new_log(options, nullptr, &state[i].index); - tox_options_free(options); - free(save[i]); - - set_mono_time_callback(toxes[i], &state[i]); + reload(&autotoxes[i]); } } printf("reconnecting toxes\n"); do { - iterate_all_wait(NUM_AV_GROUP_TOX, toxes, state, ITERATION_INTERVAL); - } while (!all_connected_to_group(NUM_AV_GROUP_TOX, toxes)); + iterate_all_wait(NUM_AV_GROUP_TOX, autotoxes, ITERATION_INTERVAL); + } while (!all_connected_to_group(NUM_AV_GROUP_TOX, autotoxes)); for (uint32_t i = 0; i < NUM_AV_GROUP_TOX; ++i) { if (restarting[i]) { - ck_assert_msg(!toxav_groupchat_av_enabled(toxes[i], 0), - "#%u restarted but av enabled", state[i].index); - ck_assert_msg(toxav_groupchat_enable_av(toxes[i], 0, audio_callback, &state[i]) == 0, - "#%u failed to re-enable av", state[i].index); - ck_assert_msg(toxav_groupchat_av_enabled(toxes[i], 0), - "#%u av not enabled even after enabling", state[i].index); + ck_assert_msg(!toxav_groupchat_av_enabled(autotoxes[i].tox, 0), + "#%u restarted but av enabled", autotoxes[i].index); + ck_assert_msg(toxav_groupchat_enable_av(autotoxes[i].tox, 0, audio_callback, &autotoxes[i]) == 0, + "#%u failed to re-enable av", autotoxes[i].index); + ck_assert_msg(toxav_groupchat_av_enabled(autotoxes[i].tox, 0), + "#%u av not enabled even after enabling", autotoxes[i].index); } } @@ -363,7 +351,7 @@ static void run_conference_tests(Tox **toxes, State *state) * connected enough for lossy messages to get through * (all_connected_to_group() only checks lossless connectivity, which is a * looser condition). */ - test_eventual_audio(toxes, state, disabled, JITTER_SETTLE_TIME + NUM_AV_GROUP_TOX * 1000); + test_eventual_audio(autotoxes, disabled, JITTER_SETTLE_TIME + NUM_AV_GROUP_TOX * 1000); printf("testing disabling av\n"); @@ -372,18 +360,18 @@ static void run_conference_tests(Tox **toxes, State *state) for (uint32_t i = 0; i < NUM_AV_DISABLE; ++i) { uint32_t disable = random_false_index(disabled, NUM_AV_GROUP_TOX); disabled[disable] = true; - printf("Disabling #%u\n", state[disable].index); - ck_assert_msg(toxav_groupchat_enable_av(toxes[disable], 0, audio_callback, &state[disable]) != 0, - "#%u could enable already enabled av!", state[i].index); - ck_assert_msg(toxav_groupchat_disable_av(toxes[disable], 0) == 0, - "#%u failed to disable av", state[i].index); + printf("Disabling #%u\n", autotoxes[disable].index); + ck_assert_msg(toxav_groupchat_enable_av(autotoxes[disable].tox, 0, audio_callback, &autotoxes[disable]) != 0, + "#%u could enable already enabled av!", autotoxes[i].index); + ck_assert_msg(toxav_groupchat_disable_av(autotoxes[disable].tox, 0) == 0, + "#%u failed to disable av", autotoxes[i].index); } // Run test without error to clear out messages from now-disabled peers. - test_audio(toxes, state, disabled, true); + test_audio(autotoxes, disabled, true); printf("testing audio with some peers having disabled their av\n"); - test_audio(toxes, state, disabled, false); + test_audio(autotoxes, disabled, false); for (uint32_t i = 0; i < NUM_AV_DISABLE; ++i) { if (!disabled[i]) { @@ -391,59 +379,60 @@ static void run_conference_tests(Tox **toxes, State *state) } disabled[i] = false; - ck_assert_msg(toxav_groupchat_disable_av(toxes[i], 0) != 0, - "#%u could disable already disabled av!", state[i].index); - ck_assert_msg(!toxav_groupchat_av_enabled(toxes[i], 0), - "#%u av enabled after disabling", state[i].index); - ck_assert_msg(toxav_groupchat_enable_av(toxes[i], 0, audio_callback, &state[i]) == 0, - "#%u failed to re-enable av", state[i].index); + ck_assert_msg(toxav_groupchat_disable_av(autotoxes[i].tox, 0) != 0, + "#%u could disable already disabled av!", autotoxes[i].index); + ck_assert_msg(!toxav_groupchat_av_enabled(autotoxes[i].tox, 0), + "#%u av enabled after disabling", autotoxes[i].index); + ck_assert_msg(toxav_groupchat_enable_av(autotoxes[i].tox, 0, audio_callback, &autotoxes[i]) == 0, + "#%u failed to re-enable av", autotoxes[i].index); } printf("testing audio after re-enabling all av\n"); - test_eventual_audio(toxes, state, disabled, JITTER_SETTLE_TIME); + test_eventual_audio(autotoxes, disabled, JITTER_SETTLE_TIME); } -static void test_groupav(Tox **toxes, State *state) +static void test_groupav(AutoTox *autotoxes) { const time_t test_start_time = time(nullptr); for (uint32_t i = 0; i < NUM_AV_GROUP_TOX; ++i) { - tox_callback_self_connection_status(toxes[i], &handle_self_connection_status); - tox_callback_friend_connection_status(toxes[i], &handle_friend_connection_status); - tox_callback_conference_invite(toxes[i], &handle_conference_invite); - tox_callback_conference_connected(toxes[i], &handle_conference_connected); + tox_callback_self_connection_status(autotoxes[i].tox, &handle_self_connection_status); + tox_callback_friend_connection_status(autotoxes[i].tox, &handle_friend_connection_status); + tox_callback_conference_invite(autotoxes[i].tox, &handle_conference_invite); + tox_callback_conference_connected(autotoxes[i].tox, &handle_conference_connected); } - ck_assert_msg(toxav_add_av_groupchat(toxes[0], audio_callback, &state[0]) != UINT32_MAX, "failed to create group"); - printf("tox #%u: inviting its first friend\n", state[0].index); - ck_assert_msg(tox_conference_invite(toxes[0], 0, 0, nullptr) != 0, "failed to invite friend"); - state[0].invited_next = true; + ck_assert_msg(toxav_add_av_groupchat(autotoxes[0].tox, audio_callback, &autotoxes[0]) != UINT32_MAX, + "failed to create group"); + printf("tox #%u: inviting its first friend\n", autotoxes[0].index); + ck_assert_msg(tox_conference_invite(autotoxes[0].tox, 0, 0, nullptr) != 0, "failed to invite friend"); + ((State *)autotoxes[0].state)->invited_next = true; printf("waiting for invitations to be made\n"); uint32_t invited_count = 0; do { - iterate_all_wait(NUM_AV_GROUP_TOX, toxes, state, ITERATION_INTERVAL); + iterate_all_wait(NUM_AV_GROUP_TOX, autotoxes, ITERATION_INTERVAL); invited_count = 0; for (uint32_t i = 0; i < NUM_AV_GROUP_TOX; ++i) { - invited_count += state[i].invited_next; + invited_count += ((State *)autotoxes[i].state)->invited_next; } } while (invited_count != NUM_AV_GROUP_TOX - 1); - uint64_t pregroup_clock = state[0].clock; + uint64_t pregroup_clock = autotoxes[0].clock; printf("waiting for all toxes to be in the group\n"); uint32_t fully_connected_count = 0; do { fully_connected_count = 0; - iterate_all_wait(NUM_AV_GROUP_TOX, toxes, state, ITERATION_INTERVAL); + iterate_all_wait(NUM_AV_GROUP_TOX, autotoxes, ITERATION_INTERVAL); for (uint32_t i = 0; i < NUM_AV_GROUP_TOX; ++i) { Tox_Err_Conference_Peer_Query err; - uint32_t peer_count = tox_conference_peer_count(toxes[i], 0, &err); + uint32_t peer_count = tox_conference_peer_count(autotoxes[i].tox, 0, &err); if (err != TOX_ERR_CONFERENCE_PEER_QUERY_OK) { peer_count = 0; @@ -453,9 +442,9 @@ static void test_groupav(Tox **toxes, State *state) } } while (fully_connected_count != NUM_AV_GROUP_TOX); - printf("group connected, took %d seconds\n", (int)((state[0].clock - pregroup_clock) / 1000)); + printf("group connected, took %d seconds\n", (int)((autotoxes[0].clock - pregroup_clock) / 1000)); - run_conference_tests(toxes, state); + run_conference_tests(autotoxes); printf("test_many_group succeeded, took %d seconds\n", (int)(time(nullptr) - test_start_time)); } @@ -464,6 +453,10 @@ int main(void) { setvbuf(stdout, nullptr, _IONBF, 0); - run_auto_test(nullptr, NUM_AV_GROUP_TOX, test_groupav, true); + Run_Auto_Options options = default_run_auto_options; + options.graph = GRAPH_LINEAR; + + run_auto_test(nullptr, NUM_AV_GROUP_TOX, test_groupav, sizeof(State), &options); + return 0; } diff --git a/auto_tests/conference_double_invite_test.c b/auto_tests/conference_double_invite_test.c index 6d8c1aa3..48283101 100644 --- a/auto_tests/conference_double_invite_test.c +++ b/auto_tests/conference_double_invite_test.c @@ -2,9 +2,6 @@ #include typedef struct State { - uint32_t index; - uint64_t clock; - bool self_online; bool friend_online; @@ -12,17 +9,18 @@ typedef struct State { uint32_t conference; } State; -#include "run_auto_test.h" +#include "auto_test_support.h" static void handle_conference_invite( Tox *tox, uint32_t friend_number, Tox_Conference_Type type, const uint8_t *cookie, size_t length, void *user_data) { - State *state = (State *)user_data; + const AutoTox *autotox = (AutoTox *)user_data; + State *state = (State *)autotox->state; fprintf(stderr, "handle_conference_invite(#%u, %u, %d, uint8_t[%u], _)\n", - state->index, friend_number, type, (unsigned)length); - fprintf(stderr, "tox%u joining conference\n", state->index); + autotox->index, friend_number, type, (unsigned)length); + fprintf(stderr, "tox%u joining conference\n", autotox->index); ck_assert_msg(!state->joined, "invitation callback generated for already joined conference"); @@ -31,31 +29,35 @@ static void handle_conference_invite( state->conference = tox_conference_join(tox, friend_number, cookie, length, &err); ck_assert_msg(err == TOX_ERR_CONFERENCE_JOIN_OK, "attempting to join the conference returned with an error: %d", err); - fprintf(stderr, "tox%u joined conference %u\n", state->index, state->conference); + fprintf(stderr, "tox%u joined conference %u\n", autotox->index, state->conference); state->joined = true; } } -static void conference_double_invite_test(Tox **toxes, State *state) +static void conference_double_invite_test(AutoTox *autotoxes) { // Conference callbacks. - tox_callback_conference_invite(toxes[0], handle_conference_invite); - tox_callback_conference_invite(toxes[1], handle_conference_invite); + tox_callback_conference_invite(autotoxes[0].tox, handle_conference_invite); + tox_callback_conference_invite(autotoxes[1].tox, handle_conference_invite); + + State *state[2]; + state[0] = (State *)autotoxes[0].state; + state[1] = (State *)autotoxes[1].state; { // Create new conference, tox0 is the founder. Tox_Err_Conference_New err; - state[0].conference = tox_conference_new(toxes[0], &err); - state[0].joined = true; + state[0]->conference = tox_conference_new(autotoxes[0].tox, &err); + state[0]->joined = true; ck_assert_msg(err == TOX_ERR_CONFERENCE_NEW_OK, "attempting to create a new conference returned with an error: %d", err); - fprintf(stderr, "Created conference: index=%u\n", state[0].conference); + fprintf(stderr, "Created conference: index=%u\n", state[0]->conference); } { // Invite friend. Tox_Err_Conference_Invite err; - tox_conference_invite(toxes[0], 0, state[0].conference, &err); + tox_conference_invite(autotoxes[0].tox, 0, state[0]->conference, &err); ck_assert_msg(err == TOX_ERR_CONFERENCE_INVITE_OK, "attempting to invite a friend returned with an error: %d", err); fprintf(stderr, "tox0 invited tox1\n"); @@ -64,21 +66,25 @@ static void conference_double_invite_test(Tox **toxes, State *state) fprintf(stderr, "Waiting for invitation to arrive\n"); do { - iterate_all_wait(2, toxes, state, ITERATION_INTERVAL); - } while (!state[0].joined || !state[1].joined); + iterate_all_wait(2, autotoxes, ITERATION_INTERVAL); + } while (!state[0]->joined || !state[1]->joined); fprintf(stderr, "Invitations accepted\n"); fprintf(stderr, "Sending second invitation; should be ignored\n"); - tox_conference_invite(toxes[0], 0, state[0].conference, nullptr); + tox_conference_invite(autotoxes[0].tox, 0, state[0]->conference, nullptr); - iterate_all_wait(2, toxes, state, ITERATION_INTERVAL); + iterate_all_wait(2, autotoxes, ITERATION_INTERVAL); } int main(void) { setvbuf(stdout, nullptr, _IONBF, 0); - run_auto_test(nullptr, 2, conference_double_invite_test, false); + Run_Auto_Options options = default_run_auto_options; + options.graph = GRAPH_LINEAR; + + run_auto_test(nullptr, 2, conference_double_invite_test, sizeof(State), &options); + return 0; } diff --git a/auto_tests/conference_invite_merge_test.c b/auto_tests/conference_invite_merge_test.c index c44f1322..d2e6700c 100644 --- a/auto_tests/conference_invite_merge_test.c +++ b/auto_tests/conference_invite_merge_test.c @@ -3,133 +3,72 @@ #include typedef struct State { - uint32_t index; - uint64_t clock; - - size_t save_size; - uint8_t *save_state; - bool alive; - bool connected; uint32_t conference; } State; #define NUM_INVITE_MERGE_TOX 5 -#include "run_auto_test.h" +#include "auto_test_support.h" static void handle_conference_invite( Tox *tox, uint32_t friend_number, Tox_Conference_Type type, const uint8_t *cookie, size_t length, void *user_data) { - State *state = (State *)user_data; + const AutoTox *autotox = (AutoTox *)user_data; + State *state = (State *)autotox->state; if (friend_number != -1) { Tox_Err_Conference_Join err; state->conference = tox_conference_join(tox, friend_number, cookie, length, &err); ck_assert_msg(err == TOX_ERR_CONFERENCE_JOIN_OK, "attempting to join the conference returned with an error: %d", err); - fprintf(stderr, "#%u accepted invite to conference %u\n", state->index, state->conference); + fprintf(stderr, "#%u accepted invite to conference %u\n", autotox->index, state->conference); } } static void handle_conference_connected( Tox *tox, uint32_t conference_number, void *user_data) { - State *state = (State *)user_data; - fprintf(stderr, "#%u connected to conference %u\n", state->index, state->conference); + const AutoTox *autotox = (AutoTox *)user_data; + State *state = (State *)autotox->state; + + fprintf(stderr, "#%u connected to conference %u\n", autotox->index, state->conference); state->connected = true; } -static void iterate_alive(Tox **toxes, State *state) -{ - for (uint32_t i = 0; i < NUM_INVITE_MERGE_TOX; i++) { - if (!state[i].alive) { - continue; - } - - tox_iterate(toxes[i], &state[i]); - state[i].clock += ITERATION_INTERVAL; - } - - c_sleep(20); -} - -static void save(Tox **toxes, State *state, uint32_t n) -{ - fprintf(stderr, "Saving #%u\n", state[n].index); - - if (state[n].save_state != nullptr) { - free(state[n].save_state); - } - - state[n].save_size = tox_get_savedata_size(toxes[n]); - state[n].save_state = (uint8_t *)malloc(state[n].save_size); - ck_assert_msg(state[n].save_state != nullptr, "malloc failed"); - tox_get_savedata(toxes[n], state[n].save_state); -} - -static void kill(Tox **toxes, State *state, uint32_t n) -{ - fprintf(stderr, "Killing #%u\n", state[n].index); - state[n].alive = false; - tox_kill(toxes[n]); -} - -static void reload(Tox **toxes, State *state, uint32_t n) -{ - if (state[n].alive) { - state[n].alive = false; - tox_kill(toxes[n]); - } - - fprintf(stderr, "Reloading #%u\n", state[n].index); - ck_assert(state[n].save_state != nullptr); - - struct Tox_Options *const options = tox_options_new(nullptr); - ck_assert(options != nullptr); - tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_TOX_SAVE); - tox_options_set_savedata_data(options, state[n].save_state, state[n].save_size); - toxes[n] = tox_new_log(options, nullptr, &state[n].index); - ck_assert(toxes[n] != nullptr); - tox_options_free(options); - - set_mono_time_callback(toxes[n], &state[n]); - state[n].alive = true; -} - -static void wait_connected(Tox **toxes, State *state, uint32_t n, uint32_t friendnumber) +static void wait_connected(AutoTox *autotoxes, AutoTox *autotox, uint32_t friendnumber) { do { - iterate_alive(toxes, state); - } while (tox_friend_get_connection_status(toxes[n], friendnumber, nullptr) == TOX_CONNECTION_NONE); + iterate_all_wait(NUM_INVITE_MERGE_TOX, autotoxes, ITERATION_INTERVAL); + } while (tox_friend_get_connection_status(autotox->tox, friendnumber, nullptr) == TOX_CONNECTION_NONE); } -static void do_invite(Tox **toxes, State *state, uint32_t inviter, uint32_t invitee, uint32_t friendnum) +static void do_invite(AutoTox *autotoxes, AutoTox *inviter, AutoTox *invitee, uint32_t friendnum) { - fprintf(stderr, "#%u inviting #%u\n", state[inviter].index, state[invitee].index); + fprintf(stderr, "#%u inviting #%u\n", inviter->index, invitee->index); Tox_Err_Conference_Invite err; - tox_conference_invite(toxes[inviter], friendnum, state[inviter].conference, &err); + tox_conference_invite(inviter->tox, friendnum, ((State *)inviter->state)->conference, &err); ck_assert_msg(err == TOX_ERR_CONFERENCE_INVITE_OK, - "#%u attempting to invite #%u (friendnumber %u) returned with an error: %d", state[inviter].index, state[invitee].index, + "#%u attempting to invite #%u (friendnumber %u) returned with an error: %d", inviter->index, invitee->index, friendnum, err); do { - iterate_alive(toxes, state); - } while (!state[invitee].connected); + iterate_all_wait(NUM_INVITE_MERGE_TOX, autotoxes, ITERATION_INTERVAL); + } while (!((State *)invitee->state)->connected); } -static bool group_complete(Tox **toxes, State *state) +static bool group_complete(AutoTox *autotoxes) { int c = -1, size = 0; for (int i = 0; i < NUM_INVITE_MERGE_TOX; i++) { - if (!state[i].alive) { + if (!autotoxes[i].alive) { continue; } - const int ct = tox_conference_peer_count(toxes[i], state[i].conference, nullptr); + const int ct = tox_conference_peer_count(autotoxes[i].tox, ((State *)autotoxes[i].state)->conference, nullptr); if (c == -1) { c = ct; @@ -143,100 +82,98 @@ static bool group_complete(Tox **toxes, State *state) return (c == size); } -static void wait_group_complete(Tox **toxes, State *state) +static void wait_group_complete(AutoTox *autotoxes) { do { - iterate_alive(toxes, state); - } while (!group_complete(toxes, state)); + iterate_all_wait(NUM_INVITE_MERGE_TOX, autotoxes, ITERATION_INTERVAL); + } while (!group_complete(autotoxes)); } -static void conference_invite_merge_test(Tox **toxes, State *state) +static void conference_invite_merge_test(AutoTox *autotoxes) { // Test that an explicit invite between peers in different connected // components will cause a split group to merge for (int i = 0; i < NUM_INVITE_MERGE_TOX; i++) { - tox_callback_conference_invite(toxes[i], handle_conference_invite); - tox_callback_conference_connected(toxes[i], &handle_conference_connected); - state[i].alive = true; - state[i].save_state = nullptr; + tox_callback_conference_invite(autotoxes[i].tox, &handle_conference_invite); + tox_callback_conference_connected(autotoxes[i].tox, &handle_conference_connected); } + State *state2 = (State *)autotoxes[2].state; + { // Create new conference, tox 2 is the founder. Tox_Err_Conference_New err; - state[2].conference = tox_conference_new(toxes[2], &err); - state[2].connected = true; + state2->conference = tox_conference_new(autotoxes[2].tox, &err); + state2->connected = true; ck_assert_msg(err == TOX_ERR_CONFERENCE_NEW_OK, "attempting to create a new conference returned with an error: %d", err); - fprintf(stderr, "Created conference: index=%u\n", state[2].conference); + fprintf(stderr, "Created conference: index=%u\n", state2->conference); } - save(toxes, state, 2); + save_autotox(&autotoxes[2]); - do_invite(toxes, state, 2, 1, 0); - do_invite(toxes, state, 1, 0, 0); + do_invite(autotoxes, &autotoxes[2], &autotoxes[1], 0); + do_invite(autotoxes, &autotoxes[1], &autotoxes[0], 0); - save(toxes, state, 1); - kill(toxes, state, 1); + save_autotox(&autotoxes[1]); + kill_autotox(&autotoxes[1]); do { - iterate_alive(toxes, state); - } while (tox_conference_peer_count(toxes[2], state[2].conference, nullptr) != 1); + iterate_all_wait(NUM_INVITE_MERGE_TOX, autotoxes, ITERATION_INTERVAL); + } while (tox_conference_peer_count(autotoxes[2].tox, state2->conference, nullptr) != 1); - do_invite(toxes, state, 2, 3, 1); - do_invite(toxes, state, 3, 4, 1); + do_invite(autotoxes, &autotoxes[2], &autotoxes[3], 1); + do_invite(autotoxes, &autotoxes[3], &autotoxes[4], 1); - kill(toxes, state, 2); + kill_autotox(&autotoxes[2]); - reload(toxes, state, 1); + reload(&autotoxes[1]); uint8_t public_key[TOX_PUBLIC_KEY_SIZE]; - tox_self_get_public_key(toxes[1], public_key); - tox_friend_add_norequest(toxes[3], public_key, nullptr); - tox_self_get_public_key(toxes[3], public_key); - tox_friend_add_norequest(toxes[1], public_key, nullptr); - wait_connected(toxes, state, 1, 2); + tox_self_get_public_key(autotoxes[1].tox, public_key); + tox_friend_add_norequest(autotoxes[3].tox, public_key, nullptr); + tox_self_get_public_key(autotoxes[3].tox, public_key); + tox_friend_add_norequest(autotoxes[1].tox, public_key, nullptr); + wait_connected(autotoxes, &autotoxes[1], 2); - do_invite(toxes, state, 1, 3, 2); + do_invite(autotoxes, &autotoxes[1], &autotoxes[3], 2); fprintf(stderr, "Waiting for group to merge\n"); - wait_group_complete(toxes, state); + wait_group_complete(autotoxes); fprintf(stderr, "Group merged\n"); - reload(toxes, state, 2); - wait_connected(toxes, state, 2, 0); - do_invite(toxes, state, 2, 1, 0); + reload(&autotoxes[2]); + wait_connected(autotoxes, &autotoxes[2], 0); + do_invite(autotoxes, &autotoxes[2], &autotoxes[1], 0); fprintf(stderr, "Waiting for #2 to rejoin\n"); - wait_group_complete(toxes, state); + wait_group_complete(autotoxes); - kill(toxes, state, 2); - wait_group_complete(toxes, state); - reload(toxes, state, 2); - wait_connected(toxes, state, 2, 0); - wait_connected(toxes, state, 1, 1); + kill_autotox(&autotoxes[2]); + wait_group_complete(autotoxes); + reload(&autotoxes[2]); + wait_connected(autotoxes, &autotoxes[2], 0); + wait_connected(autotoxes, &autotoxes[1], 1); - do_invite(toxes, state, 1, 2, 1); + do_invite(autotoxes, &autotoxes[1], &autotoxes[2], 1); fprintf(stderr, "Waiting for #2 to rejoin\n"); - wait_group_complete(toxes, state); - - for (int i = 0; i < NUM_INVITE_MERGE_TOX; i++) { - if (state[i].save_state != nullptr) { - free(state[i].save_state); - } - } + wait_group_complete(autotoxes); } int main(void) { setvbuf(stdout, nullptr, _IONBF, 0); - run_auto_test(nullptr, NUM_INVITE_MERGE_TOX, conference_invite_merge_test, true); + Run_Auto_Options options = default_run_auto_options; + options.graph = GRAPH_LINEAR; + + run_auto_test(nullptr, NUM_INVITE_MERGE_TOX, conference_invite_merge_test, sizeof(State), &options); + return 0; } diff --git a/auto_tests/conference_peer_nick_test.c b/auto_tests/conference_peer_nick_test.c index 3f3399b1..3813027e 100644 --- a/auto_tests/conference_peer_nick_test.c +++ b/auto_tests/conference_peer_nick_test.c @@ -2,9 +2,6 @@ #include typedef struct State { - uint32_t index; - uint64_t clock; - bool self_online; bool friend_online; bool friend_in_group; @@ -13,38 +10,40 @@ typedef struct State { uint32_t conference; } State; -#include "run_auto_test.h" +#include "auto_test_support.h" static void handle_conference_invite( Tox *tox, uint32_t friend_number, Tox_Conference_Type type, const uint8_t *cookie, size_t length, void *user_data) { - State *state = (State *)user_data; + const AutoTox *autotox = (AutoTox *)user_data; + State *state = (State *)autotox->state; fprintf(stderr, "handle_conference_invite(#%u, %u, %d, uint8_t[%u], _)\n", - state->index, friend_number, type, (unsigned)length); - fprintf(stderr, "tox%u joining conference\n", state->index); + autotox->index, friend_number, type, (unsigned)length); + fprintf(stderr, "tox%u joining conference\n", autotox->index); Tox_Err_Conference_Join err; state->conference = tox_conference_join(tox, friend_number, cookie, length, &err); ck_assert_msg(err == TOX_ERR_CONFERENCE_JOIN_OK, "attempting to join the conference returned with an error: %d", err); - fprintf(stderr, "tox%u joined conference %u\n", state->index, state->conference); + fprintf(stderr, "tox%u joined conference %u\n", autotox->index, state->conference); state->joined = true; } static void handle_peer_list_changed(Tox *tox, uint32_t conference_number, void *user_data) { - State *state = (State *)user_data; + const AutoTox *autotox = (AutoTox *)user_data; + State *state = (State *)autotox->state; fprintf(stderr, "handle_peer_list_changed(#%u, %u, _)\n", - state->index, conference_number); + autotox->index, conference_number); Tox_Err_Conference_Peer_Query err; uint32_t const count = tox_conference_peer_count(tox, conference_number, &err); ck_assert_msg(err == TOX_ERR_CONFERENCE_PEER_QUERY_OK, "failed to get conference peer count: err = %d", err); - printf("tox%u has %u peers\n", state->index, count); + printf("tox%u has %u peers\n", autotox->index, count); state->friend_in_group = count == 2; } @@ -73,32 +72,36 @@ static void rebuild_peer_list(Tox *tox) } } -static void conference_peer_nick_test(Tox **toxes, State *state) +static void conference_peer_nick_test(AutoTox *autotoxes) { // Conference callbacks. - tox_callback_conference_invite(toxes[0], handle_conference_invite); - tox_callback_conference_invite(toxes[1], handle_conference_invite); - tox_callback_conference_peer_list_changed(toxes[0], handle_peer_list_changed); - tox_callback_conference_peer_list_changed(toxes[1], handle_peer_list_changed); + tox_callback_conference_invite(autotoxes[0].tox, handle_conference_invite); + tox_callback_conference_invite(autotoxes[1].tox, handle_conference_invite); + tox_callback_conference_peer_list_changed(autotoxes[0].tox, handle_peer_list_changed); + tox_callback_conference_peer_list_changed(autotoxes[1].tox, handle_peer_list_changed); // Set the names of the toxes. - tox_self_set_name(toxes[0], (const uint8_t *)"test-tox-0", 10, nullptr); - tox_self_set_name(toxes[1], (const uint8_t *)"test-tox-1", 10, nullptr); + tox_self_set_name(autotoxes[0].tox, (const uint8_t *)"test-tox-0", 10, nullptr); + tox_self_set_name(autotoxes[1].tox, (const uint8_t *)"test-tox-1", 10, nullptr); + + State *state[2]; + state[0] = (State *)autotoxes[0].state; + state[1] = (State *)autotoxes[1].state; { // Create new conference, tox0 is the founder. Tox_Err_Conference_New err; - state[0].conference = tox_conference_new(toxes[0], &err); - state[0].joined = true; + state[0]->conference = tox_conference_new(autotoxes[0].tox, &err); + state[0]->joined = true; ck_assert_msg(err == TOX_ERR_CONFERENCE_NEW_OK, "attempting to create a new conference returned with an error: %d", err); - fprintf(stderr, "Created conference: index=%u\n", state[0].conference); + fprintf(stderr, "Created conference: index=%u\n", state[0]->conference); } { // Invite friend. Tox_Err_Conference_Invite err; - tox_conference_invite(toxes[0], 0, state[0].conference, &err); + tox_conference_invite(autotoxes[0].tox, 0, state[0]->conference, &err); ck_assert_msg(err == TOX_ERR_CONFERENCE_INVITE_OK, "attempting to invite a friend returned with an error: %d", err); fprintf(stderr, "tox0 invited tox1\n"); @@ -107,17 +110,17 @@ static void conference_peer_nick_test(Tox **toxes, State *state) fprintf(stderr, "Waiting for invitation to arrive and peers to be in the group\n"); do { - iterate_all_wait(2, toxes, state, ITERATION_INTERVAL); - } while (!state[0].joined || !state[1].joined || !state[0].friend_in_group || !state[1].friend_in_group); + iterate_all_wait(2, autotoxes, ITERATION_INTERVAL); + } while (!state[0]->joined || !state[1]->joined || !state[0]->friend_in_group || !state[1]->friend_in_group); fprintf(stderr, "Running tox0, but not tox1, waiting for tox1 to drop out\n"); do { - iterate_all_wait(1, toxes, state, 1000); + iterate_all_wait(1, autotoxes, 1000); // Rebuild peer list after every iteration. - rebuild_peer_list(toxes[0]); - } while (state[0].friend_in_group); + rebuild_peer_list(autotoxes[0].tox); + } while (state[0]->friend_in_group); fprintf(stderr, "Invitations accepted\n"); } @@ -126,6 +129,9 @@ int main(void) { setvbuf(stdout, nullptr, _IONBF, 0); - run_auto_test(nullptr, 2, conference_peer_nick_test, false); + Run_Auto_Options options = default_run_auto_options; + options.graph = GRAPH_LINEAR; + run_auto_test(nullptr, 2, conference_peer_nick_test, sizeof(State), &options); + return 0; } diff --git a/auto_tests/conference_test.c b/auto_tests/conference_test.c index cce9ad70..f2e9f385 100644 --- a/auto_tests/conference_test.c +++ b/auto_tests/conference_test.c @@ -19,35 +19,32 @@ #define NEW_NAME_FORMAT_STR "New #%4u" typedef struct State { - uint32_t index; - uint64_t clock; - bool invited_next; } State; -#include "run_auto_test.h" +#include "auto_test_support.h" static void handle_self_connection_status( Tox *tox, Tox_Connection connection_status, void *user_data) { - const State *state = (State *)user_data; + const AutoTox *autotox = (AutoTox *)user_data; if (connection_status != TOX_CONNECTION_NONE) { - printf("tox #%u: is now connected\n", state->index); + printf("tox #%u: is now connected\n", autotox->index); } else { - printf("tox #%u: is now disconnected\n", state->index); + printf("tox #%u: is now disconnected\n", autotox->index); } } static void handle_friend_connection_status( Tox *tox, uint32_t friendnumber, Tox_Connection connection_status, void *user_data) { - const State *state = (State *)user_data; + const AutoTox *autotox = (AutoTox *)user_data; if (connection_status != TOX_CONNECTION_NONE) { - printf("tox #%u: is now connected to friend %u\n", state->index, friendnumber); + printf("tox #%u: is now connected to friend %u\n", autotox->index, friendnumber); } else { - printf("tox #%u: is now disconnected from friend %u\n", state->index, friendnumber); + printf("tox #%u: is now disconnected from friend %u\n", autotox->index, friendnumber); } } @@ -55,25 +52,26 @@ static void handle_conference_invite( Tox *tox, uint32_t friendnumber, Tox_Conference_Type type, const uint8_t *data, size_t length, void *user_data) { - const State *state = (State *)user_data; - ck_assert_msg(type == TOX_CONFERENCE_TYPE_TEXT, "tox #%u: wrong conference type: %d", state->index, type); + const AutoTox *autotox = (AutoTox *)user_data; + ck_assert_msg(type == TOX_CONFERENCE_TYPE_TEXT, "tox #%u: wrong conference type: %d", autotox->index, type); Tox_Err_Conference_Join err; uint32_t g_num = tox_conference_join(tox, friendnumber, data, length, &err); - ck_assert_msg(err == TOX_ERR_CONFERENCE_JOIN_OK, "tox #%u: error joining group: %d", state->index, err); - ck_assert_msg(g_num == 0, "tox #%u: group number was not 0", state->index); + ck_assert_msg(err == TOX_ERR_CONFERENCE_JOIN_OK, "tox #%u: error joining group: %d", autotox->index, err); + ck_assert_msg(g_num == 0, "tox #%u: group number was not 0", autotox->index); // Try joining again. We should only be allowed to join once. tox_conference_join(tox, friendnumber, data, length, &err); ck_assert_msg(err != TOX_ERR_CONFERENCE_JOIN_OK, - "tox #%u: joining groupchat twice should be impossible.", state->index); + "tox #%u: joining groupchat twice should be impossible.", autotox->index); } static void handle_conference_connected( Tox *tox, uint32_t conference_number, void *user_data) { - State *state = (State *)user_data; + const AutoTox *autotox = (AutoTox *)user_data; + State *state = (State *)autotox->state; if (state->invited_next || tox_self_get_friend_list_size(tox) <= 1) { return; @@ -81,8 +79,9 @@ static void handle_conference_connected( Tox_Err_Conference_Invite err; tox_conference_invite(tox, 1, 0, &err); - ck_assert_msg(err == TOX_ERR_CONFERENCE_INVITE_OK, "tox #%u failed to invite next friend: err = %d", state->index, err); - printf("tox #%u: invited next friend\n", state->index); + ck_assert_msg(err == TOX_ERR_CONFERENCE_INVITE_OK, "tox #%u failed to invite next friend: err = %d", autotox->index, + err); + printf("tox #%u: invited next friend\n", autotox->index); state->invited_next = true; } @@ -97,7 +96,7 @@ static void handle_conference_message( } } -static bool toxes_are_disconnected_from_group(uint32_t tox_count, Tox **toxes, +static bool toxes_are_disconnected_from_group(uint32_t tox_count, AutoTox *autotoxes, bool *disconnected) { uint32_t num_disconnected = 0; @@ -111,7 +110,7 @@ static bool toxes_are_disconnected_from_group(uint32_t tox_count, Tox **toxes, continue; } - if (tox_conference_peer_count(toxes[i], 0, nullptr) > tox_count - num_disconnected) { + if (tox_conference_peer_count(autotoxes[i].tox, 0, nullptr) > tox_count - num_disconnected) { return false; } } @@ -119,7 +118,7 @@ static bool toxes_are_disconnected_from_group(uint32_t tox_count, Tox **toxes, return true; } -static void disconnect_toxes(uint32_t tox_count, Tox **toxes, State *state, +static void disconnect_toxes(uint32_t tox_count, AutoTox *autotoxes, const bool *disconnect, const bool *exclude) { /* Fake a network outage for a set of peers D by iterating only the other @@ -137,22 +136,22 @@ static void disconnect_toxes(uint32_t tox_count, Tox **toxes, State *state, do { for (uint32_t i = 0; i < tox_count; ++i) { if (!disconnect_now[i]) { - tox_iterate(toxes[i], &state[i]); - state[i].clock += 1000; + tox_iterate(autotoxes[i].tox, &autotoxes[i]); + autotoxes[i].clock += 1000; } } c_sleep(20); - } while (!toxes_are_disconnected_from_group(tox_count, toxes, disconnect_now)); + } while (!toxes_are_disconnected_from_group(tox_count, autotoxes, disconnect_now)); invert = !invert; } while (invert); } -static bool all_connected_to_group(uint32_t tox_count, Tox **toxes) +static bool all_connected_to_group(uint32_t tox_count, AutoTox *autotoxes) { for (uint32_t i = 0; i < tox_count; i++) { - if (tox_conference_peer_count(toxes[i], 0, nullptr) < tox_count) { + if (tox_conference_peer_count(autotoxes[i].tox, 0, nullptr) < tox_count) { return false; } } @@ -160,11 +159,11 @@ static bool all_connected_to_group(uint32_t tox_count, Tox **toxes) return true; } -static bool names_propagated(uint32_t tox_count, Tox **toxes, State *state) +static bool names_propagated(uint32_t tox_count, AutoTox *autotoxes) { for (uint32_t i = 0; i < tox_count; ++i) { for (uint32_t j = 0; j < tox_count; ++j) { - const size_t len = tox_conference_peer_get_name_size(toxes[i], 0, j, nullptr); + const size_t len = tox_conference_peer_get_name_size(autotoxes[i].tox, 0, j, nullptr); if (len != NAMELEN) { return false; @@ -191,7 +190,7 @@ static uint32_t random_false_index(bool *list, const uint32_t length) return index; } -static void run_conference_tests(Tox **toxes, State *state) +static void run_conference_tests(AutoTox *autotoxes) { /* disabling name change propagation check for now, as it occasionally * fails due to disconnections too short to trigger freezing */ @@ -204,9 +203,9 @@ static void run_conference_tests(Tox **toxes, State *state) for (uint16_t i = 0; i < NUM_GROUP_TOX; ++i) { Tox_Err_Conference_Set_Max_Offline err; - tox_conference_set_max_offline(toxes[i], 0, max_frozen, &err); + tox_conference_set_max_offline(autotoxes[i].tox, 0, max_frozen, &err); ck_assert_msg(err == TOX_ERR_CONFERENCE_SET_MAX_OFFLINE_OK, - "tox #%u failed to set max offline: err = %d", state[i].index, err); + "tox #%u failed to set max offline: err = %d", autotoxes[i].index, err); } printf("letting random toxes timeout\n"); @@ -221,9 +220,9 @@ static void run_conference_tests(Tox **toxes, State *state) if (i < NUM_DISCONNECT / 2) { restarting[disconnect] = true; - printf("Restarting #%u\n", state[disconnect].index); + printf("Restarting #%u\n", autotoxes[disconnect].index); } else { - printf("Disconnecting #%u\n", state[disconnect].index); + printf("Disconnecting #%u\n", autotoxes[disconnect].index); } } @@ -232,16 +231,16 @@ static void run_conference_tests(Tox **toxes, State *state) for (uint32_t i = 0; i < NUM_GROUP_TOX; ++i) { if (restarting[i]) { - save_size[i] = tox_get_savedata_size(toxes[i]); + save_size[i] = tox_get_savedata_size(autotoxes[i].tox); ck_assert_msg(save_size[i] != 0, "save is invalid size %u", (unsigned)save_size[i]); save[i] = (uint8_t *)malloc(save_size[i]); ck_assert_msg(save[i] != nullptr, "malloc failed"); - tox_get_savedata(toxes[i], save[i]); - tox_kill(toxes[i]); + tox_get_savedata(autotoxes[i].tox, save[i]); + tox_kill(autotoxes[i].tox); } } - disconnect_toxes(NUM_GROUP_TOX, toxes, state, disconnected, restarting); + disconnect_toxes(NUM_GROUP_TOX, autotoxes, disconnected, restarting); for (uint32_t i = 0; i < NUM_GROUP_TOX; ++i) { if (restarting[i]) { @@ -249,13 +248,13 @@ static void run_conference_tests(Tox **toxes, State *state) ck_assert(options != nullptr); tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_TOX_SAVE); tox_options_set_savedata_data(options, save[i], save_size[i]); - toxes[i] = tox_new_log(options, nullptr, &state[i].index); - ck_assert(toxes[i] != nullptr); + autotoxes[i].tox = tox_new_log(options, nullptr, &autotoxes[i].index); + ck_assert(autotoxes[i].tox != nullptr); tox_options_free(options); free(save[i]); - set_mono_time_callback(toxes[i], &state[i]); - tox_conference_set_max_offline(toxes[i], 0, max_frozen, nullptr); + set_mono_time_callback(&autotoxes[i]); + tox_conference_set_max_offline(autotoxes[i].tox, 0, max_frozen, nullptr); } } @@ -264,43 +263,43 @@ static void run_conference_tests(Tox **toxes, State *state) for (uint32_t i = 0; i < NUM_GROUP_TOX; ++i) { char name[NAMELEN + 1]; - snprintf(name, NAMELEN + 1, NEW_NAME_FORMAT_STR, state[i].index); - tox_self_set_name(toxes[i], (const uint8_t *)name, NAMELEN, nullptr); + snprintf(name, NAMELEN + 1, NEW_NAME_FORMAT_STR, autotoxes[i].index); + tox_self_set_name(autotoxes[i].tox, (const uint8_t *)name, NAMELEN, nullptr); } } for (uint16_t i = 0; i < NUM_GROUP_TOX; ++i) { - const uint32_t num_frozen = tox_conference_offline_peer_count(toxes[i], 0, nullptr); + const uint32_t num_frozen = tox_conference_offline_peer_count(autotoxes[i].tox, 0, nullptr); ck_assert_msg(num_frozen <= max_frozen, "tox #%u has too many offline peers: %u\n", - state[i].index, num_frozen); + autotoxes[i].index, num_frozen); } printf("reconnecting toxes\n"); do { - iterate_all_wait(NUM_GROUP_TOX, toxes, state, ITERATION_INTERVAL); - } while (!all_connected_to_group(NUM_GROUP_TOX, toxes)); + iterate_all_wait(NUM_GROUP_TOX, autotoxes, ITERATION_INTERVAL); + } while (!all_connected_to_group(NUM_GROUP_TOX, autotoxes)); printf("running conference tests\n"); for (uint32_t i = 0; i < NUM_GROUP_TOX; ++i) { - tox_callback_conference_message(toxes[i], &handle_conference_message); + tox_callback_conference_message(autotoxes[i].tox, &handle_conference_message); - iterate_all_wait(NUM_GROUP_TOX, toxes, state, ITERATION_INTERVAL); + iterate_all_wait(NUM_GROUP_TOX, autotoxes, ITERATION_INTERVAL); } Tox_Err_Conference_Send_Message err; ck_assert_msg( tox_conference_send_message( - toxes[random_u32() % NUM_GROUP_TOX], 0, TOX_MESSAGE_TYPE_NORMAL, (const uint8_t *)GROUP_MESSAGE, + autotoxes[random_u32() % NUM_GROUP_TOX].tox, 0, TOX_MESSAGE_TYPE_NORMAL, (const uint8_t *)GROUP_MESSAGE, sizeof(GROUP_MESSAGE) - 1, &err) != 0, "failed to send group message"); ck_assert_msg( err == TOX_ERR_CONFERENCE_SEND_MESSAGE_OK, "failed to send group message"); num_recv = 0; for (uint8_t j = 0; j < NUM_GROUP_TOX * 2; ++j) { - iterate_all_wait(NUM_GROUP_TOX, toxes, state, ITERATION_INTERVAL); + iterate_all_wait(NUM_GROUP_TOX, autotoxes, ITERATION_INTERVAL); } ck_assert_msg(num_recv == NUM_GROUP_TOX, "failed to recv group messages"); @@ -309,23 +308,23 @@ static void run_conference_tests(Tox **toxes, State *state) for (uint32_t i = 0; i < NUM_GROUP_TOX; ++i) { for (uint32_t j = 0; j < NUM_GROUP_TOX; ++j) { uint8_t name[NAMELEN]; - tox_conference_peer_get_name(toxes[i], 0, j, name, nullptr); + tox_conference_peer_get_name(autotoxes[i].tox, 0, j, name, nullptr); /* Note the toxes will have been reordered */ ck_assert_msg(memcmp(name, "New", 3) == 0, - "name of #%u according to #%u not updated", state[j].index, state[i].index); + "name of #%u according to #%u not updated", autotoxes[j].index, autotoxes[i].index); } } } for (uint32_t k = NUM_GROUP_TOX; k != 0 ; --k) { - tox_conference_delete(toxes[k - 1], 0, nullptr); + tox_conference_delete(autotoxes[k - 1].tox, 0, nullptr); for (uint8_t j = 0; j < 10 || j < NUM_GROUP_TOX; ++j) { - iterate_all_wait(NUM_GROUP_TOX, toxes, state, ITERATION_INTERVAL); + iterate_all_wait(NUM_GROUP_TOX, autotoxes, ITERATION_INTERVAL); } for (uint32_t i = 0; i < k - 1; ++i) { - uint32_t peer_count = tox_conference_peer_count(toxes[i], 0, nullptr); + uint32_t peer_count = tox_conference_peer_count(autotoxes[i].tox, 0, nullptr); ck_assert_msg(peer_count == (k - 1), "\n\tBad number of group peers (post check)." "\n\t\t\tExpected: %u but tox_instance(%u) only has: %u\n\n", k - 1, i, (unsigned)peer_count); @@ -333,26 +332,27 @@ static void run_conference_tests(Tox **toxes, State *state) } } -static void test_many_group(Tox **toxes, State *state) +static void test_many_group(AutoTox *autotoxes) { const time_t test_start_time = time(nullptr); for (uint32_t i = 0; i < NUM_GROUP_TOX; ++i) { - tox_callback_self_connection_status(toxes[i], &handle_self_connection_status); - tox_callback_friend_connection_status(toxes[i], &handle_friend_connection_status); - tox_callback_conference_invite(toxes[i], &handle_conference_invite); - tox_callback_conference_connected(toxes[i], &handle_conference_connected); + tox_callback_self_connection_status(autotoxes[i].tox, &handle_self_connection_status); + tox_callback_friend_connection_status(autotoxes[i].tox, &handle_friend_connection_status); + tox_callback_conference_invite(autotoxes[i].tox, &handle_conference_invite); + tox_callback_conference_connected(autotoxes[i].tox, &handle_conference_connected); char name[NAMELEN + 1]; - snprintf(name, NAMELEN + 1, NAME_FORMAT_STR, state[i].index); - tox_self_set_name(toxes[i], (const uint8_t *)name, NAMELEN, nullptr); + snprintf(name, NAMELEN + 1, NAME_FORMAT_STR, autotoxes[i].index); + tox_self_set_name(autotoxes[i].tox, (const uint8_t *)name, NAMELEN, nullptr); } - ck_assert_msg(tox_conference_new(toxes[0], nullptr) != UINT32_MAX, "failed to create group"); - printf("tox #%u: inviting its first friend\n", state[0].index); - ck_assert_msg(tox_conference_invite(toxes[0], 0, 0, nullptr) != 0, "failed to invite friend"); - state[0].invited_next = true; - ck_assert_msg(tox_conference_set_title(toxes[0], 0, (const uint8_t *)"Gentoo", sizeof("Gentoo") - 1, nullptr) != 0, + ck_assert_msg(tox_conference_new(autotoxes[0].tox, nullptr) != UINT32_MAX, "failed to create group"); + printf("tox #%u: inviting its first friend\n", autotoxes[0].index); + ck_assert_msg(tox_conference_invite(autotoxes[0].tox, 0, 0, nullptr) != 0, "failed to invite friend"); + ((State *)autotoxes[0].state)->invited_next = true; + ck_assert_msg(tox_conference_set_title(autotoxes[0].tox, 0, (const uint8_t *)"Gentoo", sizeof("Gentoo") - 1, + nullptr) != 0, "failed to set group title"); @@ -360,16 +360,16 @@ static void test_many_group(Tox **toxes, State *state) uint32_t invited_count = 0; do { - iterate_all_wait(NUM_GROUP_TOX, toxes, state, ITERATION_INTERVAL); + iterate_all_wait(NUM_GROUP_TOX, autotoxes, ITERATION_INTERVAL); invited_count = 0; for (uint32_t i = 0; i < NUM_GROUP_TOX; ++i) { - invited_count += state[i].invited_next; + invited_count += ((State *)autotoxes[i].state)->invited_next; } } while (invited_count != NUM_GROUP_TOX - 1); - uint64_t pregroup_clock = state[0].clock; + uint64_t pregroup_clock = autotoxes[0].clock; printf("waiting for all toxes to be in the group\n"); uint32_t fully_connected_count = 0; @@ -377,11 +377,11 @@ static void test_many_group(Tox **toxes, State *state) fully_connected_count = 0; printf("current peer counts: ["); - iterate_all_wait(NUM_GROUP_TOX, toxes, state, ITERATION_INTERVAL); + iterate_all_wait(NUM_GROUP_TOX, autotoxes, ITERATION_INTERVAL); for (uint32_t i = 0; i < NUM_GROUP_TOX; ++i) { Tox_Err_Conference_Peer_Query err; - uint32_t peer_count = tox_conference_peer_count(toxes[i], 0, &err); + uint32_t peer_count = tox_conference_peer_count(autotoxes[i].tox, 0, &err); if (err != TOX_ERR_CONFERENCE_PEER_QUERY_OK) { peer_count = 0; @@ -401,28 +401,28 @@ static void test_many_group(Tox **toxes, State *state) } while (fully_connected_count != NUM_GROUP_TOX); for (uint32_t i = 0; i < NUM_GROUP_TOX; ++i) { - uint32_t peer_count = tox_conference_peer_count(toxes[i], 0, nullptr); + uint32_t peer_count = tox_conference_peer_count(autotoxes[i].tox, 0, nullptr); ck_assert_msg(peer_count == NUM_GROUP_TOX, "\n\tBad number of group peers (pre check)." "\n\t\t\tExpected: %d but tox_instance(%u) only has: %u\n\n", NUM_GROUP_TOX, i, (unsigned)peer_count); uint8_t title[2048]; - size_t ret = tox_conference_get_title_size(toxes[i], 0, nullptr); + size_t ret = tox_conference_get_title_size(autotoxes[i].tox, 0, nullptr); ck_assert_msg(ret == sizeof("Gentoo") - 1, "Wrong title length"); - tox_conference_get_title(toxes[i], 0, title, nullptr); + tox_conference_get_title(autotoxes[i].tox, 0, title, nullptr); ck_assert_msg(memcmp("Gentoo", title, ret) == 0, "Wrong title"); } printf("waiting for names to propagate\n"); do { - iterate_all_wait(NUM_GROUP_TOX, toxes, state, ITERATION_INTERVAL); - } while (!names_propagated(NUM_GROUP_TOX, toxes, state)); + iterate_all_wait(NUM_GROUP_TOX, autotoxes, ITERATION_INTERVAL); + } while (!names_propagated(NUM_GROUP_TOX, autotoxes)); - printf("group connected, took %d seconds\n", (int)((state[0].clock - pregroup_clock) / 1000)); + printf("group connected, took %d seconds\n", (int)((autotoxes[0].clock - pregroup_clock) / 1000)); - run_conference_tests(toxes, state); + run_conference_tests(autotoxes); printf("test_many_group succeeded, took %d seconds\n", (int)(time(nullptr) - test_start_time)); } @@ -431,6 +431,9 @@ int main(void) { setvbuf(stdout, nullptr, _IONBF, 0); - run_auto_test(nullptr, NUM_GROUP_TOX, test_many_group, true); + Run_Auto_Options options = default_run_auto_options; + options.graph = GRAPH_LINEAR; + + run_auto_test(nullptr, NUM_GROUP_TOX, test_many_group, sizeof(State), &options); return 0; } diff --git a/auto_tests/friend_connection_test.c b/auto_tests/friend_connection_test.c index 21c25b93..297af53a 100644 --- a/auto_tests/friend_connection_test.c +++ b/auto_tests/friend_connection_test.c @@ -7,14 +7,9 @@ #include -typedef struct State { - uint32_t index; - uint64_t clock; -} State; +#include "auto_test_support.h" -#include "run_auto_test.h" - -static void friend_connection_test(Tox **toxes, State *state) +static void friend_connection_test(AutoTox *toxes) { // Nothing to do here. When copying this test, add test-specific code here. } @@ -23,6 +18,9 @@ int main(void) { setvbuf(stdout, nullptr, _IONBF, 0); - run_auto_test(nullptr, 2, friend_connection_test, false); + Run_Auto_Options options = default_run_auto_options; + options.graph = GRAPH_LINEAR; + run_auto_test(nullptr, 2, friend_connection_test, 0, &options); + return 0; } diff --git a/auto_tests/lossless_packet_test.c b/auto_tests/lossless_packet_test.c index da0f6447..be751590 100644 --- a/auto_tests/lossless_packet_test.c +++ b/auto_tests/lossless_packet_test.c @@ -13,20 +13,18 @@ #include "check_compat.h" typedef struct State { - uint32_t index; - uint64_t clock; - bool custom_packet_received; } State; -#include "run_auto_test.h" +#include "auto_test_support.h" #define LOSSLESS_PACKET_FILLER 160 static void handle_lossless_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length, void *user_data) { - State *state = (State *)user_data; + const AutoTox *autotox = (AutoTox *)user_data; + State *state = (State *)autotox->state; uint8_t cmp_packet[TOX_MAX_CUSTOM_PACKET_SIZE]; memset(cmp_packet, LOSSLESS_PACKET_FILLER, sizeof(cmp_packet)); @@ -36,27 +34,31 @@ static void handle_lossless_packet(Tox *tox, uint32_t friend_number, const uint8 } } -static void test_lossless_packet(Tox **toxes, State *state) +static void test_lossless_packet(AutoTox *autotoxes) { - tox_callback_friend_lossless_packet(toxes[1], &handle_lossless_packet); + tox_callback_friend_lossless_packet(autotoxes[1].tox, &handle_lossless_packet); uint8_t packet[TOX_MAX_CUSTOM_PACKET_SIZE + 1]; memset(packet, LOSSLESS_PACKET_FILLER, sizeof(packet)); - bool ret = tox_friend_send_lossless_packet(toxes[0], 0, packet, sizeof(packet), nullptr); + bool ret = tox_friend_send_lossless_packet(autotoxes[0].tox, 0, packet, sizeof(packet), nullptr); ck_assert_msg(ret == false, "should not be able to send custom packets this big %i", ret); - ret = tox_friend_send_lossless_packet(toxes[0], 0, packet, TOX_MAX_CUSTOM_PACKET_SIZE, nullptr); + ret = tox_friend_send_lossless_packet(autotoxes[0].tox, 0, packet, TOX_MAX_CUSTOM_PACKET_SIZE, nullptr); ck_assert_msg(ret == true, "tox_friend_send_lossless_packet fail %i", ret); do { - iterate_all_wait(2, toxes, state, ITERATION_INTERVAL); - } while (!state[1].custom_packet_received); + iterate_all_wait(2, autotoxes, ITERATION_INTERVAL); + } while (!((State *)autotoxes[1].state)->custom_packet_received); } int main(void) { setvbuf(stdout, nullptr, _IONBF, 0); - run_auto_test(nullptr, 2, test_lossless_packet, false); + Run_Auto_Options options = default_run_auto_options; + options.graph = GRAPH_LINEAR; + + run_auto_test(nullptr, 2, test_lossless_packet, sizeof(State), &options); + return 0; } diff --git a/auto_tests/lossy_packet_test.c b/auto_tests/lossy_packet_test.c index 0dcd50a4..c9eddfbd 100644 --- a/auto_tests/lossy_packet_test.c +++ b/auto_tests/lossy_packet_test.c @@ -11,13 +11,10 @@ #include "check_compat.h" typedef struct State { - uint32_t index; - uint64_t clock; - bool custom_packet_received; } State; -#include "run_auto_test.h" +#include "auto_test_support.h" #define LOSSY_PACKET_FILLER 200 @@ -27,32 +24,37 @@ static void handle_lossy_packet(Tox *tox, uint32_t friend_number, const uint8_t memset(cmp_packet, LOSSY_PACKET_FILLER, sizeof(cmp_packet)); if (length == TOX_MAX_CUSTOM_PACKET_SIZE && memcmp(data, cmp_packet, sizeof(cmp_packet)) == 0) { - State *state = (State *)user_data; + const AutoTox *autotox = (AutoTox *)user_data; + State *state = (State *)autotox->state; state->custom_packet_received = true; } } -static void test_lossy_packet(Tox **toxes, State *state) +static void test_lossy_packet(AutoTox *autotoxes) { - tox_callback_friend_lossy_packet(toxes[1], &handle_lossy_packet); + tox_callback_friend_lossy_packet(autotoxes[1].tox, &handle_lossy_packet); uint8_t packet[TOX_MAX_CUSTOM_PACKET_SIZE + 1]; memset(packet, LOSSY_PACKET_FILLER, sizeof(packet)); - bool ret = tox_friend_send_lossy_packet(toxes[0], 0, packet, sizeof(packet), nullptr); + bool ret = tox_friend_send_lossy_packet(autotoxes[0].tox, 0, packet, sizeof(packet), nullptr); ck_assert_msg(ret == false, "should not be able to send custom packets this big %i", ret); - ret = tox_friend_send_lossy_packet(toxes[0], 0, packet, TOX_MAX_CUSTOM_PACKET_SIZE, nullptr); + ret = tox_friend_send_lossy_packet(autotoxes[0].tox, 0, packet, TOX_MAX_CUSTOM_PACKET_SIZE, nullptr); ck_assert_msg(ret == true, "tox_friend_send_lossy_packet fail %i", ret); do { - iterate_all_wait(2, toxes, state, ITERATION_INTERVAL); - } while (!state[1].custom_packet_received); + iterate_all_wait(2, autotoxes, ITERATION_INTERVAL); + } while (!((State *)autotoxes[1].state)->custom_packet_received); } int main(void) { setvbuf(stdout, nullptr, _IONBF, 0); - run_auto_test(nullptr, 2, test_lossy_packet, false); + Run_Auto_Options options = default_run_auto_options; + options.graph = GRAPH_LINEAR; + + run_auto_test(nullptr, 2, test_lossy_packet, sizeof(State), &options); + return 0; } diff --git a/auto_tests/overflow_recvq_test.c b/auto_tests/overflow_recvq_test.c index 0ab54f24..48a13b96 100644 --- a/auto_tests/overflow_recvq_test.c +++ b/auto_tests/overflow_recvq_test.c @@ -4,26 +4,24 @@ #include typedef struct State { - uint32_t index; - uint64_t clock; - uint32_t recv_count; } State; -#include "run_auto_test.h" +#include "auto_test_support.h" #define NUM_MSGS 40000 static void handle_friend_message(Tox *tox, uint32_t friend_number, Tox_Message_Type type, const uint8_t *message, size_t length, void *user_data) { - State *state = (State *)user_data; + const AutoTox *autotox = (AutoTox *)user_data; + State *state = (State *)autotox->state; state->recv_count++; } -static void net_crypto_overflow_test(Tox **toxes, State *state) +static void net_crypto_overflow_test(AutoTox *autotoxes) { - tox_callback_friend_message(toxes[0], handle_friend_message); + tox_callback_friend_message(autotoxes[0].tox, handle_friend_message); printf("sending many messages to tox0\n"); @@ -33,7 +31,7 @@ static void net_crypto_overflow_test(Tox **toxes, State *state) snprintf((char *)message, sizeof(message), "%u-%u", tox_index, i); Tox_Err_Friend_Send_Message err; - tox_friend_send_message(toxes[tox_index], 0, TOX_MESSAGE_TYPE_NORMAL, message, sizeof message, &err); + tox_friend_send_message(autotoxes[tox_index].tox, 0, TOX_MESSAGE_TYPE_NORMAL, message, sizeof message, &err); if (err == TOX_ERR_FRIEND_SEND_MESSAGE_SENDQ) { printf("tox%u sent %u messages to friend 0\n", tox_index, i); @@ -48,16 +46,19 @@ static void net_crypto_overflow_test(Tox **toxes, State *state) // TODO(iphydf): Wait until all messages have arrived. Currently, not all // messages arrive, so this test would always fail. for (uint32_t i = 0; i < 200; i++) { - iterate_all_wait(3, toxes, state, ITERATION_INTERVAL); + iterate_all_wait(3, autotoxes, ITERATION_INTERVAL); } - printf("tox%u received %u messages\n", state[0].index, state[0].recv_count); + printf("tox%u received %u messages\n", autotoxes[0].index, ((State *)autotoxes[0].state)->recv_count); } int main(void) { setvbuf(stdout, nullptr, _IONBF, 0); - run_auto_test(nullptr, 3, net_crypto_overflow_test, false); + Run_Auto_Options options = default_run_auto_options; + options.graph = GRAPH_LINEAR; + run_auto_test(nullptr, 3, net_crypto_overflow_test, sizeof(State), &options); + return 0; } diff --git a/auto_tests/overflow_sendq_test.c b/auto_tests/overflow_sendq_test.c index b96c6664..1c03fe6b 100644 --- a/auto_tests/overflow_sendq_test.c +++ b/auto_tests/overflow_sendq_test.c @@ -3,23 +3,18 @@ #include -typedef struct State { - uint32_t index; - uint64_t clock; -} State; - -#include "run_auto_test.h" +#include "auto_test_support.h" #define NUM_MSGS 40000 -static void net_crypto_overflow_test(Tox **toxes, State *state) +static void net_crypto_overflow_test(AutoTox *autotoxes) { const uint8_t message[] = {0}; bool errored = false; for (uint32_t i = 0; i < NUM_MSGS; i++) { Tox_Err_Friend_Send_Message err; - tox_friend_send_message(toxes[0], 0, TOX_MESSAGE_TYPE_NORMAL, message, sizeof message, &err); + tox_friend_send_message(autotoxes[0].tox, 0, TOX_MESSAGE_TYPE_NORMAL, message, sizeof message, &err); if (err != TOX_ERR_FRIEND_SEND_MESSAGE_OK) { errored = true; @@ -43,6 +38,9 @@ int main(void) { setvbuf(stdout, nullptr, _IONBF, 0); - run_auto_test(nullptr, 2, net_crypto_overflow_test, false); + Run_Auto_Options options = default_run_auto_options; + options.graph = GRAPH_LINEAR; + run_auto_test(nullptr, 2, net_crypto_overflow_test, 0, &options); + return 0; } diff --git a/auto_tests/reconnect_test.c b/auto_tests/reconnect_test.c index f995b835..5af48e0c 100644 --- a/auto_tests/reconnect_test.c +++ b/auto_tests/reconnect_test.c @@ -18,20 +18,15 @@ #define TOX_COUNT 2 #define RECONNECT_TIME_MAX (FRIEND_CONNECTION_TIMEOUT + 3) -typedef struct State { - uint32_t index; - uint64_t clock; -} State; +#include "auto_test_support.h" -#include "run_auto_test.h" - -static uint32_t tox_connected_count(uint32_t tox_count, Tox **toxes, State *state, uint32_t index) +static uint32_t tox_connected_count(uint32_t tox_count, AutoTox *autotoxes, uint32_t index) { - const size_t friend_count = tox_self_get_friend_list_size(toxes[index]); + const size_t friend_count = tox_self_get_friend_list_size(autotoxes[index].tox); uint32_t connected_count = 0; for (size_t j = 0; j < friend_count; j++) { - if (tox_friend_get_connection_status(toxes[index], j, nullptr) != TOX_CONNECTION_NONE) { + if (tox_friend_get_connection_status(autotoxes[index].tox, j, nullptr) != TOX_CONNECTION_NONE) { ++connected_count; } } @@ -39,14 +34,14 @@ static uint32_t tox_connected_count(uint32_t tox_count, Tox **toxes, State *stat return connected_count; } -static bool all_disconnected_from(uint32_t tox_count, Tox **toxes, State *state, uint32_t index) +static bool all_disconnected_from(uint32_t tox_count, AutoTox *autotoxes, uint32_t index) { for (uint32_t i = 0; i < tox_count; i++) { if (i == index) { continue; } - if (tox_connected_count(tox_count, toxes, state, i) >= tox_count - 1) { + if (tox_connected_count(tox_count, autotoxes, i) >= tox_count - 1) { return false; } } @@ -54,39 +49,39 @@ static bool all_disconnected_from(uint32_t tox_count, Tox **toxes, State *state, return true; } -static void test_reconnect(Tox **toxes, State *state) +static void test_reconnect(AutoTox *autotoxes) { const time_t test_start_time = time(nullptr); printf("letting connections settle\n"); do { - iterate_all_wait(TOX_COUNT, toxes, state, ITERATION_INTERVAL); + iterate_all_wait(TOX_COUNT, autotoxes, ITERATION_INTERVAL); } while (time(nullptr) - test_start_time < 2); uint16_t disconnect = random_u16() % TOX_COUNT; - printf("disconnecting #%u\n", state[disconnect].index); + printf("disconnecting #%u\n", autotoxes[disconnect].index); do { for (uint16_t i = 0; i < TOX_COUNT; ++i) { if (i != disconnect) { - tox_iterate(toxes[i], &state[i]); - state[i].clock += 1000; + tox_iterate(autotoxes[i].tox, &autotoxes[i]); + autotoxes[i].clock += 1000; } } c_sleep(20); - } while (!all_disconnected_from(TOX_COUNT, toxes, state, disconnect)); + } while (!all_disconnected_from(TOX_COUNT, autotoxes, disconnect)); - const uint64_t reconnect_start_time = state[0].clock; + const uint64_t reconnect_start_time = autotoxes[0].clock; printf("reconnecting\n"); do { - iterate_all_wait(TOX_COUNT, toxes, state, ITERATION_INTERVAL); - } while (!all_friends_connected(TOX_COUNT, toxes)); + iterate_all_wait(TOX_COUNT, autotoxes, ITERATION_INTERVAL); + } while (!all_friends_connected(TOX_COUNT, autotoxes)); - const uint64_t reconnect_time = state[0].clock - reconnect_start_time; + const uint64_t reconnect_time = autotoxes[0].clock - reconnect_start_time; ck_assert_msg(reconnect_time <= RECONNECT_TIME_MAX * 1000, "reconnection took %d seconds; expected at most %d seconds", (int)(reconnect_time / 1000), RECONNECT_TIME_MAX); @@ -97,6 +92,9 @@ int main(void) { setvbuf(stdout, nullptr, _IONBF, 0); - run_auto_test(nullptr, TOX_COUNT, test_reconnect, false); + Run_Auto_Options options = default_run_auto_options; + options.graph = GRAPH_LINEAR; + run_auto_test(nullptr, TOX_COUNT, test_reconnect, 0, &options); + return 0; } diff --git a/auto_tests/run_auto_test.h b/auto_tests/run_auto_test.h deleted file mode 100644 index 3d0afc95..00000000 --- a/auto_tests/run_auto_test.h +++ /dev/null @@ -1,232 +0,0 @@ -#include // calloc, free -#include "check_compat.h" -#include "../testing/misc_tools.h" -#include "../toxcore/Messenger.h" -#include "../toxcore/mono_time.h" - -// List of live bootstrap nodes. These nodes should have TCP server enabled. -static const struct BootstrapNodes { - const char *ip; - uint16_t port; - const uint8_t key[32]; -} BootstrapNodes[] = { -#ifndef USE_TEST_NETWORK - { - "tox.abilinski.com", 33445, - 0x10, 0xC0, 0x0E, 0xB2, 0x50, 0xC3, 0x23, 0x3E, - 0x34, 0x3E, 0x2A, 0xEB, 0xA0, 0x71, 0x15, 0xA5, - 0xC2, 0x89, 0x20, 0xE9, 0xC8, 0xD2, 0x94, 0x92, - 0xF6, 0xD0, 0x0B, 0x29, 0x04, 0x9E, 0xDC, 0x7E, - }, - { - "tox.initramfs.io", 33445, - 0x02, 0x80, 0x7C, 0xF4, 0xF8, 0xBB, 0x8F, 0xB3, - 0x90, 0xCC, 0x37, 0x94, 0xBD, 0xF1, 0xE8, 0x44, - 0x9E, 0x9A, 0x83, 0x92, 0xC5, 0xD3, 0xF2, 0x20, - 0x00, 0x19, 0xDA, 0x9F, 0x1E, 0x81, 0x2E, 0x46, - }, - { - "tox.plastiras.org", 33445, - 0x8E, 0x8B, 0x63, 0x29, 0x9B, 0x3D, 0x52, 0x0F, - 0xB3, 0x77, 0xFE, 0x51, 0x00, 0xE6, 0x5E, 0x33, - 0x22, 0xF7, 0xAE, 0x5B, 0x20, 0xA0, 0xAC, 0xED, - 0x29, 0x81, 0x76, 0x9F, 0xC5, 0xB4, 0x37, 0x25, - }, - { - "tox.novg.net", 33445, - 0xD5, 0x27, 0xE5, 0x84, 0x7F, 0x83, 0x30, 0xD6, - 0x28, 0xDA, 0xB1, 0x81, 0x4F, 0x0A, 0x42, 0x2F, - 0x6D, 0xC9, 0xD0, 0xA3, 0x00, 0xE6, 0xC3, 0x57, - 0x63, 0x4E, 0xE2, 0xDA, 0x88, 0xC3, 0x54, 0x63, - }, -#else - { - "172.93.52.70", 33445, - 0x79, 0xCA, 0xDA, 0x49, 0x74, 0xB0, 0x92, 0x6F, - 0x28, 0x6F, 0x02, 0x5C, 0xD5, 0xFF, 0xDF, 0x3E, - 0x65, 0x4A, 0x37, 0x58, 0xC5, 0x3E, 0x02, 0x73, - 0xEC, 0xFC, 0x4D, 0x12, 0xC2, 0x1D, 0xCA, 0x48, - }, -#endif // USE_TEST_NETWORK - { nullptr, 0, 0 }, -}; - -static void bootstrap_toxes_live_network(Tox **toxes, uint32_t tox_count, bool enable_tcp) -{ - for (size_t i = 0; i < tox_count; ++i) { - for (size_t j = 0; BootstrapNodes[j].ip != nullptr; ++j) { - const char *ip = BootstrapNodes[j].ip; - uint16_t port = BootstrapNodes[j].port; - const uint8_t *key = BootstrapNodes[j].key; - - Tox_Err_Bootstrap err; - tox_bootstrap(toxes[i], ip, port, key, &err); - - if (err != TOX_ERR_BOOTSTRAP_OK) { - fprintf(stderr, "Failed to bootstrap node %zu (%s): error %d\n", j, ip, err); - } - - if (enable_tcp) { - tox_add_tcp_relay(toxes[i], ip, port, key, &err); - - if (err != TOX_ERR_BOOTSTRAP_OK) { - fprintf(stderr, "Failed to add TCP relay %zu (%s): error %d\n", j, ip, err); - } - } - } - } -} - -static bool all_connected(uint32_t tox_count, Tox **toxes) -{ - for (uint32_t i = 0; i < tox_count; i++) { - if (tox_self_get_connection_status(toxes[i]) == TOX_CONNECTION_NONE) { - return false; - } - } - - return true; -} - -static bool all_friends_connected(uint32_t tox_count, Tox **toxes) -{ - for (uint32_t i = 0; i < tox_count; i++) { - const size_t friend_count = tox_self_get_friend_list_size(toxes[i]); - - for (size_t j = 0; j < friend_count; j++) { - if (tox_friend_get_connection_status(toxes[i], j, nullptr) == TOX_CONNECTION_NONE) { - return false; - } - } - } - - return true; -} - -static void iterate_all_wait(uint32_t tox_count, Tox **toxes, State *state, uint32_t wait) -{ - for (uint32_t i = 0; i < tox_count; i++) { - tox_iterate(toxes[i], &state[i]); - state[i].clock += wait; - } - - /* Also actually sleep a little, to allow for local network processing */ - c_sleep(5); -} - -static uint64_t get_state_clock_callback(Mono_Time *mono_time, void *user_data) -{ - const State *state = (const State *)user_data; - return state->clock; -} - -static void set_mono_time_callback(Tox *tox, State *state) -{ - // TODO(iphydf): Don't rely on toxcore internals. - Mono_Time *mono_time = ((Messenger *)tox)->mono_time; - - state->clock = current_time_monotonic(mono_time); - mono_time_set_current_time_callback(mono_time, get_state_clock_callback, state); -} - -static void add_friend(uint32_t i, uint32_t j, Tox **toxes) -{ - uint8_t public_key[TOX_PUBLIC_KEY_SIZE]; - tox_self_get_public_key(toxes[j], public_key); - Tox_Err_Friend_Add err; - tox_friend_add_norequest(toxes[i], public_key, &err); - ck_assert(err == TOX_ERR_FRIEND_ADD_OK); -} - -static void build_friend_graph(uint32_t tox_count, bool chain, Tox **toxes) -{ - if (chain) { - printf("each tox adds adjacent toxes as friends\n"); - - for (uint32_t i = 0; i < tox_count; i++) { - for (uint32_t j = i - 1; j != i + 3; j += 2) { - if (j >= tox_count) { - continue; - } - - add_friend(i, j, toxes); - } - } - } else { - printf("toxes all add each other as friends\n"); - - for (uint32_t i = 0; i < tox_count; i++) { - for (uint32_t j = 0; j < tox_count; j++) { - if (i != j) { - add_friend(i, j, toxes); - } - } - } - } -} - -static void wait_friend_connections(uint32_t tox_count, Tox **toxes, State *state) -{ - do { - iterate_all_wait(tox_count, toxes, state, ITERATION_INTERVAL); - } while (!all_connected(tox_count, toxes)); - - printf("toxes are online\n"); - - do { - iterate_all_wait(tox_count, toxes, state, ITERATION_INTERVAL); - } while (!all_friends_connected(tox_count, toxes)); - - printf("tox clients connected\n"); -} - -static void run_auto_test(struct Tox_Options *options, uint32_t tox_count, void test(Tox **toxes, State *state), - bool chain) -{ - printf("initialising %u toxes\n", tox_count); - Tox **toxes = (Tox **)calloc(tox_count, sizeof(Tox *)); - State *state = (State *)calloc(tox_count, sizeof(State)); - - ck_assert(toxes != nullptr); - ck_assert(state != nullptr); - - for (uint32_t i = 0; i < tox_count; i++) { - state[i].index = i; - toxes[i] = tox_new_log(options, nullptr, &state[i].index); - ck_assert_msg(toxes[i], "failed to create %u tox instances", i + 1); - - set_mono_time_callback(toxes[i], &state[i]); - } - - build_friend_graph(tox_count, chain, toxes); - - const bool udp_enabled = options != nullptr ? tox_options_get_udp_enabled(options) : true; - Tox_Err_Bootstrap err; - - if (udp_enabled) { - printf("bootstrapping all toxes off toxes[0]\n"); - - uint8_t dht_key[TOX_PUBLIC_KEY_SIZE]; - tox_self_get_dht_id(toxes[0], dht_key); - const uint16_t dht_port = tox_self_get_udp_port(toxes[0], nullptr); - - for (uint32_t i = 1; i < tox_count; i++) { - tox_bootstrap(toxes[i], "localhost", dht_port, dht_key, &err); - ck_assert(err == TOX_ERR_BOOTSTRAP_OK); - } - } else { - printf("bootstrapping all toxes to tcp relays\n"); - bootstrap_toxes_live_network(toxes, tox_count, true); - } - - wait_friend_connections(tox_count, toxes, state); - - test(toxes, state); - - for (uint32_t i = 0; i < tox_count; i++) { - tox_kill(toxes[i]); - } - - free(state); - free(toxes); -} diff --git a/auto_tests/send_message_test.c b/auto_tests/send_message_test.c index 4cacda56..15e68630 100644 --- a/auto_tests/send_message_test.c +++ b/auto_tests/send_message_test.c @@ -6,21 +6,19 @@ #include typedef struct State { - uint32_t index; - uint64_t clock; - bool message_received; } State; -#include "run_auto_test.h" +#include "auto_test_support.h" #define MESSAGE_FILLER 'G' static void message_callback( Tox *m, uint32_t friendnumber, Tox_Message_Type type, - const uint8_t *string, size_t length, void *userdata) + const uint8_t *string, size_t length, void *user_data) { - State *state = (State *)userdata; + const AutoTox *autotox = (AutoTox *)user_data; + State *state = (State *)autotox->state; if (type != TOX_MESSAGE_TYPE_NORMAL) { ck_abort_msg("Bad type"); @@ -34,29 +32,32 @@ static void message_callback( } } -static void send_message_test(Tox **toxes, State *state) +static void send_message_test(AutoTox *autotoxes) { - tox_callback_friend_message(toxes[1], &message_callback); + tox_callback_friend_message(autotoxes[1].tox, &message_callback); uint8_t msgs[TOX_MAX_MESSAGE_LENGTH + 1]; memset(msgs, MESSAGE_FILLER, sizeof(msgs)); Tox_Err_Friend_Send_Message errm; - tox_friend_send_message(toxes[0], 0, TOX_MESSAGE_TYPE_NORMAL, msgs, TOX_MAX_MESSAGE_LENGTH + 1, &errm); + tox_friend_send_message(autotoxes[0].tox, 0, TOX_MESSAGE_TYPE_NORMAL, msgs, TOX_MAX_MESSAGE_LENGTH + 1, &errm); ck_assert_msg(errm == TOX_ERR_FRIEND_SEND_MESSAGE_TOO_LONG, "TOX_MAX_MESSAGE_LENGTH is too small? error=%d", errm); - tox_friend_send_message(toxes[0], 0, TOX_MESSAGE_TYPE_NORMAL, msgs, TOX_MAX_MESSAGE_LENGTH, &errm); + tox_friend_send_message(autotoxes[0].tox, 0, TOX_MESSAGE_TYPE_NORMAL, msgs, TOX_MAX_MESSAGE_LENGTH, &errm); ck_assert_msg(errm == TOX_ERR_FRIEND_SEND_MESSAGE_OK, "TOX_MAX_MESSAGE_LENGTH is too big? error=%d", errm); do { - iterate_all_wait(2, toxes, state, ITERATION_INTERVAL); - } while (!state[1].message_received); + iterate_all_wait(2, autotoxes, ITERATION_INTERVAL); + } while (!((State *)autotoxes[1].state)->message_received); } int main(void) { setvbuf(stdout, nullptr, _IONBF, 0); - run_auto_test(nullptr, 2, send_message_test, false); + Run_Auto_Options options = default_run_auto_options; + options.graph = GRAPH_LINEAR; + run_auto_test(nullptr, 2, send_message_test, sizeof(State), &options); + return 0; } diff --git a/auto_tests/tcp_relay_test.c b/auto_tests/tcp_relay_test.c index 8bcd6abe..b098f5ca 100644 --- a/auto_tests/tcp_relay_test.c +++ b/auto_tests/tcp_relay_test.c @@ -3,12 +3,7 @@ #include "../testing/misc_tools.h" #include "check_compat.h" -typedef struct State { - uint32_t index; - uint64_t clock; -} State; - -#include "run_auto_test.h" +#include "auto_test_support.h" int main(void) { @@ -19,7 +14,7 @@ int main(void) Tox *tox_tcp = tox_new_log(opts, nullptr, nullptr); tox_options_free(opts); - bootstrap_toxes_live_network(&tox_tcp, 1, true); + bootstrap_tox_live_network(tox_tcp, true); printf("Waiting for connection"); @@ -38,7 +33,5 @@ int main(void) tox_kill(tox_tcp); - (void)run_auto_test; - return 0; } diff --git a/auto_tests/typing_test.c b/auto_tests/typing_test.c index 5ea1299b..eb439832 100644 --- a/auto_tests/typing_test.c +++ b/auto_tests/typing_test.c @@ -12,40 +12,39 @@ #include "check_compat.h" typedef struct State { - uint32_t index; - uint64_t clock; bool friend_is_typing; } State; -#include "run_auto_test.h" +#include "auto_test_support.h" -static void typing_callback(Tox *m, uint32_t friendnumber, bool typing, void *userdata) +static void typing_callback(Tox *m, uint32_t friendnumber, bool typing, void *user_data) { - State *state = (State *)userdata; + const AutoTox *autotox = (AutoTox *)user_data; + State *state = (State *)autotox->state; state->friend_is_typing = typing; } -static void test_typing(Tox **toxes, State *state) +static void test_typing(AutoTox *autotoxes) { time_t cur_time = time(nullptr); - tox_callback_friend_typing(toxes[1], &typing_callback); - tox_self_set_typing(toxes[0], 0, true, nullptr); + tox_callback_friend_typing(autotoxes[1].tox, &typing_callback); + tox_self_set_typing(autotoxes[0].tox, 0, true, nullptr); do { - iterate_all_wait(2, toxes, state, 200); - } while (!state[1].friend_is_typing); + iterate_all_wait(2, autotoxes, 200); + } while (!((State *)autotoxes[1].state)->friend_is_typing); - ck_assert_msg(tox_friend_get_typing(toxes[1], 0, nullptr) == 1, + ck_assert_msg(tox_friend_get_typing(autotoxes[1].tox, 0, nullptr) == 1, "tox_friend_get_typing should have returned true, but it didn't"); - tox_self_set_typing(toxes[0], 0, false, nullptr); + tox_self_set_typing(autotoxes[0].tox, 0, false, nullptr); do { - iterate_all_wait(2, toxes, state, 200); - } while (state[1].friend_is_typing); + iterate_all_wait(2, autotoxes, 200); + } while (((State *)autotoxes[1].state)->friend_is_typing); Tox_Err_Friend_Query err_t; - ck_assert_msg(tox_friend_get_typing(toxes[1], 0, &err_t) == 0, + ck_assert_msg(tox_friend_get_typing(autotoxes[1].tox, 0, &err_t) == 0, "tox_friend_get_typing should have returned false, but it didn't"); ck_assert_msg(err_t == TOX_ERR_FRIEND_QUERY_OK, "tox_friend_get_typing call did not return correct error"); @@ -55,6 +54,10 @@ static void test_typing(Tox **toxes, State *state) int main(void) { setvbuf(stdout, nullptr, _IONBF, 0); - run_auto_test(nullptr, 2, test_typing, false); + + Run_Auto_Options options = default_run_auto_options; + options.graph = GRAPH_LINEAR; + run_auto_test(nullptr, 2, test_typing, sizeof(State), &options); + return 0; }