Verify ETCP registry identity and failure ownership invariants

This commit is contained in:
evgeny committed 2026-10-24 00:01:02 +02:00
1 parent 032f8e83b2
commit 74b63cc315
1 file changed
+28
+28
View File
@@ -307,6 +307,33 @@ static void neighbor_close_case(struct UTUN_INSTANCE *inst) {
puts("PASS nested close: current and neighbor links, no cached next pointer");
}
static void registry_index_cases(struct UTUN_INSTANCE *inst) {
struct ETCP_CONN *first = etcp_connection_create(inst, "first indexed"); CHECK(first);
struct ETCP_CONN *second = etcp_connection_create(inst, "second indexed"); CHECK(second);
struct ll_entry *entry = first->conn_queue_entry, *other = second->conn_queue_entry;
first->peer_node_id = second->peer_node_id = 1;
size_t allocated = u_get_allocated_count();
CHECK(etcp_conn_index_peer(first) == 0 && first->conn_queue_entry == entry);
CHECK(first->state == 0 && instance_find_conn(inst, 1) == first && inst->connections->count == 2);
CHECK(etcp_conn_index_peer(first) == 0 && u_get_allocated_count() == allocated);
CHECK(etcp_conn_index_peer(second) < 0 && second->conn_queue_entry == other);
CHECK(((struct conn_queue_entry*)other->data)->peer_node_id == 0 && instance_find_conn(inst, 1) == first);
etcp_conn_queue_set_ready(first); etcp_conn_queue_set_ready(first);
CHECK(first->state == 1 && first->conn_queue_entry == entry && u_get_allocated_count() == allocated);
second->peer_node_id = 2;
CHECK(etcp_conn_index_peer(second) == 0 && second->conn_queue_entry == other && instance_find_conn(inst, 2) == second);
/* Отказ put освобождает entry: close не должен повторно трогать эту память. */
queue_set_size_limit(inst->connections, 1);
second->peer_node_id = 3;
CHECK(etcp_conn_index_peer(second) < 0 && !second->conn_queue_entry && inst->connections->count == 1);
CHECK(!instance_find_conn(inst, 2) && !instance_find_conn(inst, 3) && instance_find_conn(inst, 1) == first);
queue_set_size_limit(inst->connections, -1);
etcp_connection_close(second); etcp_connection_close(first);
uasync_drain_immediate(inst->ua); uasync_poll(inst->ua, 0);
CHECK(!inst->connections->count);
puts("PASS peer registry: stable entry, idempotent ready, duplicate rejection, failed put cleanup");
}
int main(void) {
debug_config_init(); debug_set_level(DEBUG_LEVEL_WARN);
const char* log = getenv("LIFECYCLE_TEST_LOG");
@@ -340,6 +367,7 @@ int main(void) {
}
ncd_cases(&inst); ncd_late_up_case(&inst); recovery_cases(&inst); neighbor_close_case(&inst);
constructor_close_cases(&inst); link_constructor_close_cases(&inst); subscription_cases(&inst);
registry_index_cases(&inst);
queue_free(inst.connections); uasync_poll(inst.ua,0);
CHECK(inst.ua->timer_alloc_count == inst.ua->timer_free_count);
uasync_destroy(inst.ua,0); CHECK(u_get_allocated_count() == baseline);