|
|
|
@ -15,6 +15,7 @@ |
|
|
|
#include "../src/routing_layer/topo_node_sqlite.h" |
|
|
|
#include "../src/routing_layer/topo_node_sqlite.h" |
|
|
|
#include "../src/routing_layer/route_crypto.h" |
|
|
|
#include "../src/routing_layer/route_crypto.h" |
|
|
|
#include "../src/transport_layer/etcp.h" |
|
|
|
#include "../src/transport_layer/etcp.h" |
|
|
|
|
|
|
|
#include "../src/transport_layer/etcp_keepalive.h" |
|
|
|
#include "../src/transport_layer/node_conn_direct.h" |
|
|
|
#include "../src/transport_layer/node_conn_direct.h" |
|
|
|
#include "../src/utun_instance.h" |
|
|
|
#include "../src/utun_instance.h" |
|
|
|
#include "../lib/debug_config.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"); |
|
|
|
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) { |
|
|
|
int main(int argc, char **argv) { |
|
|
|
debug_config_init(); debug_set_level(DEBUG_LEVEL_ERROR); |
|
|
|
debug_config_init(); debug_set_level(DEBUG_LEVEL_ERROR); |
|
|
|
debug_set_category_level(DEBUG_CATEGORY_STREAM, DEBUG_LEVEL_DEBUG); |
|
|
|
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[0], nodes[i]->node_id, "710001", NULL, NULL) == 0); |
|
|
|
CHECK(member_sync_start(nodes[i], nodes[0]->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(); |
|
|
|
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 < 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]); } |
|
|
|
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(); |
|
|
|
uasync_destroy(ua, 1); test_clock_finish(); |
|
|
|
@ -1697,9 +1748,10 @@ int main(int argc, char **argv) { |
|
|
|
u_report_unfreed_blocks(); |
|
|
|
u_report_unfreed_blocks(); |
|
|
|
} |
|
|
|
} |
|
|
|
CHECK(u_get_allocated_count() == allocations); |
|
|
|
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; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
test_sources_after_wake(); |
|
|
|
test_profile_atomicity(); |
|
|
|
test_profile_atomicity(); |
|
|
|
stream_set_event_callback(nodes[0], on_stream, NULL); stream_set_event_callback(nodes[1], on_stream, NULL); |
|
|
|
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; |
|
|
|
struct STREAM_HANDLE *publisher = NULL, *publisher2 = NULL, *other_group = NULL, *mobile = NULL, *desktop = NULL; |
|
|
|
|