Test stream announcements after foreground wake and packet reordering
This commit is contained in:
1 parent
919c3d76fe
commit
fc526d16c0
3 files changed
+89
-3
No files matched your search
@@ -284,6 +284,22 @@ static void check_peer_wake_new_link(int tcp, int active_window) {
|
||||
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "PASS peer wake via new link tcp=%d active_window=%d: phase cancelled, TX preserved", tcp, active_window);
|
||||
}
|
||||
|
||||
/* Потеря первого normal и запоздалый SLEEP исправляются следующим normal без ожидания конца сна. */
|
||||
static void check_peer_wake_reordered(void) {
|
||||
setup(); struct ETCP_CONN* conn = ready_conn(0); struct ETCP_LINK* link = conn->links;
|
||||
receive_keepalive(link, KA_FLAG_SLEEP, 0);
|
||||
test_clock_run_for(inst.ua, 2000); // первый normal потерян в сети
|
||||
CHECK(conn->peer_sleep_phase && conn->peer_phase_timer);
|
||||
receive_keepalive(link, 0, 0);
|
||||
CHECK(!conn->peer_sleep_phase && !conn->peer_phase_timer && link->keepalive_timer);
|
||||
receive_keepalive(link, KA_FLAG_SLEEP, 0); // старый анонс пришёл после пробуждения
|
||||
CHECK(conn->peer_sleep_phase && conn->peer_phase_timer);
|
||||
test_clock_run_for(inst.ua, 2000);
|
||||
receive_keepalive(link, 0, 0);
|
||||
CHECK(!conn->peer_sleep_phase && !conn->peer_phase_timer && link->keepalive_timer);
|
||||
teardown(); DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "PASS normal keepalive restores awake state after loss and reordered sleep");
|
||||
}
|
||||
|
||||
/* Мягкое закрытие работает без NCD entry; KEEP_ALIVE сохраняет транспорт дольше прежних 5 секунд. */
|
||||
static void check_graceful(void) {
|
||||
setup(); struct ETCP_CONN* conn = ready_conn(0);
|
||||
@@ -320,6 +336,7 @@ int main(void) {
|
||||
for (int tcp = 0; tcp <= 1; tcp++) for (int active = 0; active <= 1; active++) {
|
||||
check_peer_wake_new_link(tcp, active); CHECK(u_get_allocated_count() == baseline);
|
||||
}
|
||||
check_peer_wake_reordered(); CHECK(u_get_allocated_count() == baseline);
|
||||
check_remote_down(); CHECK(u_get_allocated_count() == baseline);
|
||||
check_graceful(); CHECK(u_get_allocated_count() == baseline);
|
||||
test_clock_finish(); return 0;
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "../src/routing_layer/topo_node_sqlite.h"
|
||||
#include "../src/routing_layer/route_crypto.h"
|
||||
#include "../src/transport_layer/etcp.h"
|
||||
#include "../src/transport_layer/etcp_keepalive.h"
|
||||
#include "../src/transport_layer/node_conn_direct.h"
|
||||
#include "../src/utun_instance.h"
|
||||
#include "../lib/debug_config.h"
|
||||
@@ -1620,6 +1621,55 @@ static void test_partial_bootstrap_and_end(void) {
|
||||
DEBUG_INFO(DEBUG_CATEGORY_STREAM, "[PASS] completed receive releases upstream while retaining reader and shared transport");
|
||||
}
|
||||
|
||||
/* Объявление источника ждёт спящего пира; foreground возобновляет настоящий Merkle-обмен. */
|
||||
static void test_sources_after_wake(void) {
|
||||
debug_level_t level = g_debug_config.category_levels[DEBUG_CATEGORY_KEEPALIVE];
|
||||
debug_set_category_level(DEBUG_CATEGORY_KEEPALIVE, DEBUG_LEVEL_INFO);
|
||||
CHECK(utun_set_client_activity(nodes[2], 1) == 0);
|
||||
/* Каналы стенда внесены напрямую в БД после init; ждём первого обновления кеша chat_sync (5 с). */
|
||||
test_clock_run_for(ua, 51000);
|
||||
CHECK(utun_set_client_activity(nodes[2], 0) == 0);
|
||||
struct ETCP_CONN *conn = instance_find_conn(nodes[0], nodes[2]->node_id); CHECK(conn && conn->links_up);
|
||||
uint64_t deadline = get_time_tb() + 10000;
|
||||
while (!conn->peer_sleep_phase && get_time_tb() < deadline) test_clock_poll(ua, 100);
|
||||
CHECK(conn->peer_sleep_phase);
|
||||
/* Linux-стенд без Android duty-cycle: задаём полученный от мобильного пира тайминг 120 с. */
|
||||
struct ETCP_LINK *link = conn->links;
|
||||
while (link && (!link->initialized || !link->ka_peer_sleeping)) link = link->next;
|
||||
CHECK(link);
|
||||
struct ETCP_DGRAM *pkt = memory_pool_alloc(nodes[0]->pkt_pool); CHECK(pkt);
|
||||
memset(pkt, 0, sizeof(*pkt) + 8); pkt->link = link; pkt->data_len = 8;
|
||||
pkt->data[0] = ETCP_KEEPALIVE; pkt->data[1] = KA_FLAG_SLEEP;
|
||||
pkt->data[2] = 0x30; pkt->data[3] = 0x75; // period=30000 мс
|
||||
pkt->data[6] = 0xb0; pkt->data[7] = 4; // sleep=1200 * 0.1 с
|
||||
CHECK(etcp_keepalive_on_recv(pkt) == 1 && conn->peer_phase_timer);
|
||||
struct STREAM_HANDLE *publisher = NULL;
|
||||
CHECK(stream_publish_open(nodes[1], GROUP1, NULL, &publisher) == STREAM_OK);
|
||||
struct stream_info info; CHECK(stream_get_info(publisher, &info) == STREAM_OK);
|
||||
test_clock_run_for(ua, 5000);
|
||||
struct stream_member_state state;
|
||||
CHECK(stream_member_load(nodes[2], GROUP1, nodes[1]->node_id, &state, NULL) == STREAM_OK && !state.published);
|
||||
CHECK(conn->peer_sleep_phase && conn->peer_phase_timer);
|
||||
uint64_t started = get_time_tb();
|
||||
CHECK(utun_set_client_activity(nodes[2], 1) == 0);
|
||||
wait_state(2, 1, GROUP1, info.descriptor.source_epoch, 0);
|
||||
CHECK(!conn->peer_sleep_phase && !conn->peer_phase_timer && get_time_tb() - started < 30000);
|
||||
char *catalog = NULL, id[64];
|
||||
CHECK(stream_sources_json(nodes[2], GROUP1, &catalog) == STREAM_OK);
|
||||
snprintf(id, sizeof(id), "\"id\":\"%llu\"", (unsigned long long)nodes[1]->node_id);
|
||||
CHECK(strstr(catalog, id)); u_free(catalog);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_STREAM, "[PASS] source catalogue after foreground: elapsed_ms=%llu, cancelled sleep=120000ms",
|
||||
(unsigned long long)((get_time_tb() - started) / 10));
|
||||
stream_close(publisher);
|
||||
deadline = get_time_tb() + 150000;
|
||||
do {
|
||||
test_clock_poll(ua, 100);
|
||||
CHECK(stream_member_load(nodes[2], GROUP1, nodes[1]->node_id, &state, NULL) == STREAM_OK);
|
||||
} while (state.published && get_time_tb() < deadline);
|
||||
CHECK(!state.published);
|
||||
debug_set_category_level(DEBUG_CATEGORY_KEEPALIVE, level);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
debug_config_init(); debug_set_level(DEBUG_LEVEL_ERROR);
|
||||
debug_set_category_level(DEBUG_CATEGORY_STREAM, DEBUG_LEVEL_DEBUG);
|
||||
@@ -1685,9 +1735,10 @@ int main(int argc, char **argv) {
|
||||
CHECK(member_sync_start(nodes[0], nodes[i]->node_id, "710001", NULL, NULL) == 0);
|
||||
CHECK(member_sync_start(nodes[i], nodes[0]->node_id, "710001", NULL, NULL) == 0);
|
||||
}
|
||||
if (argc == 2 && (!strcmp(argv[1], "--relay-only") || !strcmp(argv[1], "--lifecycle-only"))) {
|
||||
if (argc == 2 && (!strcmp(argv[1], "--relay-only") || !strcmp(argv[1], "--lifecycle-only") || !strcmp(argv[1], "--wake-only"))) {
|
||||
if (!strcmp(argv[1], "--relay-only")) test_supernode_relay();
|
||||
else test_partial_bootstrap_and_end();
|
||||
else if (!strcmp(argv[1], "--lifecycle-only")) test_partial_bootstrap_and_end();
|
||||
else test_sources_after_wake();
|
||||
for (unsigned i = 0; i < 3; i++) topo_group_peer_close(connections[i]);
|
||||
for (unsigned i = 0; i < 4; i++) { stream_set_event_callback(nodes[i], NULL, NULL); utun_instance_destroy(nodes[i]); }
|
||||
uasync_destroy(ua, 1); test_clock_finish();
|
||||
@@ -1697,9 +1748,10 @@ int main(int argc, char **argv) {
|
||||
u_report_unfreed_blocks();
|
||||
}
|
||||
CHECK(u_get_allocated_count() == allocations);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_STREAM, "[PASS] isolated supernode relay checks complete, no tracked allocations remain");
|
||||
DEBUG_INFO(DEBUG_CATEGORY_STREAM, "[PASS] isolated stream checks complete, no tracked allocations remain");
|
||||
return 0;
|
||||
}
|
||||
test_sources_after_wake();
|
||||
test_profile_atomicity();
|
||||
stream_set_event_callback(nodes[0], on_stream, NULL); stream_set_event_callback(nodes[1], on_stream, NULL);
|
||||
struct STREAM_HANDLE *publisher = NULL, *publisher2 = NULL, *other_group = NULL, *mobile = NULL, *desktop = NULL;
|
||||
|
||||
Reference in new issue
Block a user