|
|
|
|
@ -115,7 +115,7 @@ static void check_reconnect(void) {
|
|
|
|
|
teardown(); DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "PASS multiple links, reconnect cancellation and fresh DOWN deadline"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Локальный handle не препятствует удалению; release внутри DOWN сохраняет таймаут. */ |
|
|
|
|
/* Локальные handles защищают DOWN; release последнего учитывает уже прошедший срок. */ |
|
|
|
|
static void check_owner(int release) { |
|
|
|
|
setup(); struct ETCP_CONN* conn = ready_conn(0); struct NODE_CONN_DIRECT* handle = NULL; |
|
|
|
|
CHECK(node_conn_direct_open(&inst, 42, owner_cb, NULL, &handle, NULL) == NCD_REUSED); |
|
|
|
|
@ -123,11 +123,32 @@ static void check_owner(int release) {
|
|
|
|
|
conn->links->link_status = 0; etcp_on_link_down(conn, conn->links); |
|
|
|
|
CHECK(down == 1 && !deleted && conn->down_timer && !conn->close_requested); |
|
|
|
|
test_clock_run_for(inst.ua, ETCP_DOWN_TIMEOUT_TB + 10000); |
|
|
|
|
CHECK(deleted == 1 && closed == (release ? 0 : 1) && !inst.connections->count); |
|
|
|
|
if (!release) node_conn_direct_close(handle); |
|
|
|
|
if (!release) { |
|
|
|
|
CHECK(!deleted && !closed && !conn->down_timer && conn->down_deadline_tb && inst.connections->count == 1); |
|
|
|
|
CHECK(node_conn_direct_handle_count(conn) == 1); |
|
|
|
|
struct NODE_CONN_DIRECT* second = NULL; |
|
|
|
|
CHECK(node_conn_direct_open(&inst, 42, owner_cb, NULL, &second, NULL) == NCD_REUSED); |
|
|
|
|
CHECK(node_conn_direct_handle_count(conn) == 2); |
|
|
|
|
node_conn_direct_close(handle); CHECK(node_conn_direct_handle_count(conn) == 1 && !conn->close_requested); |
|
|
|
|
node_conn_direct_close(second); test_clock_run_for(inst.ua, 10); |
|
|
|
|
} |
|
|
|
|
CHECK(deleted == 1 && !closed && !inst.connections->count); |
|
|
|
|
teardown(); DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "PASS DOWN timeout with local owner release_on_down=%d", release); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Закрытие handle до deadline не начинает новые 30 секунд ожидания. */ |
|
|
|
|
static void check_release_before_deadline(void) { |
|
|
|
|
setup(); struct ETCP_CONN* conn = ready_conn(0); struct NODE_CONN_DIRECT* handle = NULL; |
|
|
|
|
CHECK(node_conn_direct_open(&inst, 42, NULL, NULL, &handle, NULL) == NCD_REUSED); |
|
|
|
|
conn->links->link_status = 0; etcp_on_link_down(conn, conn->links); |
|
|
|
|
uint64_t deadline = conn->down_deadline_tb; |
|
|
|
|
test_clock_run_for(inst.ua, 100000); node_conn_direct_close(handle); |
|
|
|
|
CHECK(!deleted && node_conn_direct_handle_count(conn) == 0 && conn->down_deadline_tb == deadline); |
|
|
|
|
test_clock_run_for(inst.ua, 100000); CHECK(!deleted); |
|
|
|
|
test_clock_run_for(inst.ua, 110000); CHECK(deleted == 1 && !inst.connections->count); |
|
|
|
|
teardown(); DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "PASS last handle release preserves original DOWN deadline"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* RX продлевает watchdog, затем молчание даёт DOWN и ещё 30 секунд до DELETE. */ |
|
|
|
|
static void check_silent_peer(int tcp) { |
|
|
|
|
setup(); struct ETCP_CONN* conn = ready_conn(tcp); struct ETCP_LINK* link = conn->links; |
|
|
|
|
@ -214,6 +235,7 @@ int main(void) {
|
|
|
|
|
check_reconnect(); CHECK(u_get_allocated_count() == baseline); |
|
|
|
|
check_owner(0); CHECK(u_get_allocated_count() == baseline); |
|
|
|
|
check_owner(1); CHECK(u_get_allocated_count() == baseline); |
|
|
|
|
check_release_before_deadline(); CHECK(u_get_allocated_count() == baseline); |
|
|
|
|
check_silent_peer(0); CHECK(u_get_allocated_count() == baseline); |
|
|
|
|
check_silent_peer(1); CHECK(u_get_allocated_count() == baseline); |
|
|
|
|
check_sleep(); CHECK(u_get_allocated_count() == baseline); |
|
|
|
|
|