Browse Source

tests: accelerate JOIN waits and verify timeout boundaries

master
evgeny 3 days ago
parent
commit
414d40c00c
  1. 3
      tests/Makefile.am
  2. 50
      tests/test_chat_join.c

3
tests/Makefile.am

@ -550,9 +550,10 @@ test_chat_sync_stress_SOURCES = test_chat_sync_stress.c
test_chat_sync_stress_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/lib
test_chat_sync_stress_LDADD = $(LIBUTUN) $(CRYPTO_LIBS) $(COMMON_LIBS)
test_chat_join_SOURCES = test_chat_join.c
test_chat_join_SOURCES = test_chat_join.c $(test_clock_sources)
test_chat_join_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/chat -I$(top_srcdir)/src/routing_layer -I$(top_srcdir)/src/transport_layer -I$(top_srcdir)/lib
test_chat_join_LDADD = $(LIBUTUN) $(CRYPTO_LIBS) $(COMMON_LIBS)
test_chat_join_LDFLAGS = $(test_clock_ldflags)
test_chat_join_e2e_SOURCES = test_chat_join_e2e.c
test_chat_join_e2e_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/chat -I$(top_srcdir)/src/routing_layer -I$(top_srcdir)/src/transport_layer -I$(top_srcdir)/lib

50
tests/test_chat_join.c

@ -27,6 +27,7 @@
#include "../lib/debug_config.h"
#include "../lib/mem.h"
#include "test_utils.h"
#include "test_clock.h"
#include <sqlite3.h>
#define OPENSSL_API_COMPAT 0x10100000L
@ -343,7 +344,8 @@ static void destroy_instances(int n) {
static int wait_connected(int n) {
if (n <= 1) return 1;
int need = n * (n - 1);
for (int a = 0; a < 2000; a++) {
uint64_t deadline = get_time_tb() + 20000;
while (get_time_tb() < deadline) {
int ok = 0;
for (int i = 0; i < n; i++) {
struct ll_entry* e = g_inst[i]->connections->head;
@ -358,13 +360,15 @@ static int wait_connected(int n) {
}
}
if (ok >= need) return 1;
uasync_poll(g_ua, POLL_MS);
test_clock_poll(g_ua, POLL_MS);
}
DEBUG_ERROR(DEBUG_CATEGORY_DEBUG, "JOIN test: connection timeout nodes=%d required_links=%d budget_ms=2000", n, need);
return 0;
}
static int wait_chat_bgp(int n) {
for (int a = 0; a < 8000; a++) {
uint64_t deadline = get_time_tb() + 80000;
while (get_time_tb() < deadline) {
int ok = 1;
for (int i = 0; i < n && ok; i++) {
struct TOPO_GROUP* g = topo_groups_find(g_inst[i]->topo_groups, g_group_id);
@ -376,8 +380,10 @@ static int wait_chat_bgp(int n) {
}
}
if (ok) return 1;
uasync_poll(g_ua, POLL_MS);
test_clock_poll(g_ua, POLL_MS);
}
DEBUG_ERROR(DEBUG_CATEGORY_DEBUG, "JOIN test: group routes timeout nodes=%d group=%llu budget_ms=8000",
n, (unsigned long long)g_group_id);
return 0;
}
@ -488,23 +494,37 @@ static void t_validate_pubkey(void) {
}
}
struct registration_result { int calls, result; };
struct registration_result { int calls, result; uint64_t fired_tb; };
static void registered(void* arg, int result) {
struct registration_result* r = arg;
r->calls++; r->result = result;
r->calls++; r->result = result; r->fired_tb = get_time_tb();
}
static void poll_ms(int ms) {
uint64_t until = get_time_tb() + (uint64_t)ms * 10;
while (get_time_tb() < until) uasync_poll(g_ua, POLL_MS);
test_clock_run_for(g_ua, ms * 10);
}
static int wait_registered(struct registration_result* r) {
uint64_t until = get_time_tb() + JOIN_REGISTER_TIMEOUT_TB + 10000;
while (!r->calls && get_time_tb() < until) uasync_poll(g_ua, POLL_MS);
while (!r->calls && get_time_tb() < until) test_clock_poll(g_ua, POLL_MS);
return r->calls == 1 && r->result == CHAT_JOIN_OK;
}
/* Убеждаемся, что регистрация жива до срока; затем настоящий таймер выдаёт ровно один TIMEOUT. */
static int wait_registration_timeout(struct registration_result* r, uint64_t started) {
uint64_t before = started + JOIN_REGISTER_TIMEOUT_TB - 1000, now = get_time_tb();
if (now < before) test_clock_run_for(g_ua, (int)(before - now));
int pending = !r->calls && g_inst[0]->join_registrations != NULL;
wait_registered(r);
int ok = pending && r->calls == 1 && r->result == CHAT_JOIN_TIMEOUT && r->fired_tb + 10 >= started + JOIN_REGISTER_TIMEOUT_TB;
if (!ok) DEBUG_ERROR(DEBUG_CATEGORY_DEBUG, "JOIN timeout failed: pending=%d calls=%d result=%d fired_tb=%llu started_tb=%llu budget_tb=%d",
pending, r->calls, r->result, (unsigned long long)r->fired_tb,
(unsigned long long)started, JOIN_REGISTER_TIMEOUT_TB);
else DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "JOIN timeout: pending before deadline; one TIMEOUT elapsed_tb=%llu budget_tb=%d",
(unsigned long long)(r->fired_tb - started), JOIN_REGISTER_TIMEOUT_TB);
return ok;
}
static etcp_recv_fn original_join_recv;
static struct ll_entry* held_ack;
static struct ETCP_CONN* held_conn;
@ -573,11 +593,12 @@ static void t_registration_edges(void) {
TEST("registration: missing ACK times out once, late ACK ignored"); {
struct registration_result r = {0};
uint64_t key = JOIN_KEY + 12;
uint64_t started = get_time_tb();
struct chat_join_registration* req = chat_join_register_key(g_inst[0], g_group_id, g_nid[1], key, registered, &r);
wait_registered(&r);
int timed_out = wait_registration_timeout(&r, started);
int had_ack = held_ack != NULL;
release_ack(); poll_ms(20);
if (req && had_ack && r.calls == 1 && r.result == CHAT_JOIN_TIMEOUT && !g_inst[0]->join_registrations
if (req && had_ack && timed_out && r.calls == 1 && r.result == CHAT_JOIN_TIMEOUT && !g_inst[0]->join_registrations
&& !chat_join_lookup_inviter(g_inst[0], g_group_id, key)) OK(); else FAIL();
if (!r.calls && req) chat_join_cancel_registration(req);
}
@ -637,11 +658,12 @@ static void t_registration_edges(void) {
}
TEST("registration: connection node shutdown times out without success"); {
struct registration_result r = {0};
uint64_t started = get_time_tb();
struct chat_join_registration* req = chat_join_register_key(g_inst[0], g_group_id, g_nid[1], JOIN_KEY + 27, registered, &r);
chat_join_destroy(g_inst[1]); member_sync_destroy(g_inst[1]);
g_inst[1]->running = 0; utun_instance_destroy(g_inst[1]); g_inst[1] = NULL;
wait_registered(&r);
if (req && r.calls == 1 && r.result == CHAT_JOIN_TIMEOUT && !g_inst[0]->join_registrations
int timed_out = wait_registration_timeout(&r, started);
if (req && timed_out && r.calls == 1 && r.result == CHAT_JOIN_TIMEOUT && !g_inst[0]->join_registrations
&& !chat_join_lookup_inviter(g_inst[0], g_group_id, JOIN_KEY + 27)) OK(); else FAIL();
if (!r.calls && req) chat_join_cancel_registration(req);
}
@ -704,6 +726,7 @@ static void t_integration(void) {
int main(void) {
debug_config_init(); debug_set_level(DEBUG_LEVEL_ERROR);
test_clock_init(1000);
if (getenv("UTUN_TEST_DEBUG")) {
debug_set_category_level_by_name("chat_sync", "info");
debug_set_category_level_by_name("member_sync", "info");
@ -748,5 +771,6 @@ int main(void) {
uasync_destroy(g_ua, 0); g_ua = NULL;
}
t_rmdir(g_tdir);
test_clock_finish();
return G_FAILED > 0 ? 1 : 0;
}

Loading…
Cancel
Save