|
|
|
|
@ -604,6 +604,44 @@ static int test_ack_receive(void) {
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Реальные ACK проходят проверку эпохи/диапазона; длины payload не равны размерам криптограмм. */ |
|
|
|
|
static int test_delivery_stats(void) { |
|
|
|
|
TEST("delivery stats: payload bytes, duplicate ACK, cancellation and isolated services"); |
|
|
|
|
struct UASYNC* ua; struct UTUN_INSTANCE inst; etcp_recv_fn recv_cb; |
|
|
|
|
SETUP(); |
|
|
|
|
establish(recv_cb, &inst, TEST_REMOTE_NODE, TEST_SVC_ID, TEST_REMOTE_NODE); |
|
|
|
|
struct ETCP_ROUTER_CONN *c = etcp_router_conn_get(&inst, TOPO_GROUP_UTUN, TEST_REMOTE_NODE, TEST_SVC_ID); |
|
|
|
|
TESTASSERT(c); |
|
|
|
|
for (unsigned i = 0; i < 3; i++) { |
|
|
|
|
struct ROUTER_INFLIGHT *inf = u_calloc(1, sizeof(*inf)); TESTASSERT(inf); |
|
|
|
|
inf->seq = i; inf->ll.size = 4; inf->ll.len = 100 + i * 10; inf->send_count = 3; |
|
|
|
|
inf->dgram_len = inf->ll.len + 128; |
|
|
|
|
inf->dgram = u_calloc(1, inf->dgram_len); TESTASSERT(inf->dgram); |
|
|
|
|
TESTASSERT(queue_data_put_with_index(c->inflight_q, &inf->ll) == 0); |
|
|
|
|
} |
|
|
|
|
c->tx_seq = c->tx_sent = 3; |
|
|
|
|
struct ETCP_ROUTER_TX_STATS stats; |
|
|
|
|
TESTASSERT(etcp_router_tx_stats(&inst, TOPO_GROUP_UTUN, TEST_REMOTE_NODE, TEST_SVC_ID, get_time_us(), &stats) == 0); |
|
|
|
|
TESTASSERT(stats.inflight_bytes == 330 && stats.inflight_packets == 3 && stats.acked_bytes == 0); |
|
|
|
|
inject(recv_cb, &inst, TEST_REMOTE_NODE, TEST_SVC_ID, 2, NULL, 0, 1, 0); |
|
|
|
|
inject(recv_cb, &inst, TEST_REMOTE_NODE, TEST_SVC_ID, 2, NULL, 0, 1, 0); |
|
|
|
|
TESTASSERT(etcp_router_tx_stats(&inst, TOPO_GROUP_UTUN, TEST_REMOTE_NODE, TEST_SVC_ID, get_time_us(), &stats) == 0); |
|
|
|
|
TESTASSERT(stats.inflight_bytes == 120 && stats.acked_bytes == 210 && stats.acked_packets == 2); |
|
|
|
|
TESTASSERT(stats.inflight_packets == 1 && !stats.window.valid); |
|
|
|
|
uint64_t old_epoch = stats.local_epoch; |
|
|
|
|
struct ETCP_ROUTER_CONN *other = etcp_router_conn_get(&inst, TOPO_GROUP_UTUN, TEST_REMOTE_NODE, TEST_SVC_ID2); |
|
|
|
|
TESTASSERT(other); |
|
|
|
|
uint8_t body[23] = {0}; |
|
|
|
|
TESTASSERT(etcp_router_conn_send(other, body, sizeof(body), 0) == 0); |
|
|
|
|
TESTASSERT(etcp_router_tx_stats(&inst, TOPO_GROUP_UTUN, TEST_REMOTE_NODE, TEST_SVC_ID2, get_time_us(), &stats) == 0); |
|
|
|
|
TESTASSERT(stats.queued_bytes == sizeof(body) && stats.queued_packets == 1 && !stats.acked_bytes); |
|
|
|
|
etcp_router_conn_restart(&inst, TOPO_GROUP_UTUN, TEST_REMOTE_NODE, TEST_SVC_ID); |
|
|
|
|
TESTASSERT(etcp_router_tx_stats(&inst, TOPO_GROUP_UTUN, TEST_REMOTE_NODE, TEST_SVC_ID, get_time_us(), &stats) == 0); |
|
|
|
|
TESTASSERT(stats.local_epoch != old_epoch && !stats.acked_bytes && !stats.inflight_bytes && !stats.window.valid); |
|
|
|
|
TESTASSERT(etcp_router_tx_stats(&inst, TOPO_GROUP_UTUN, TEST_REMOTE_NODE2, TEST_SVC_ID, get_time_us(), &stats) == 1); |
|
|
|
|
TEARDOWN(); PASS(); return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int test_ack_timer(void) { |
|
|
|
|
TEST("ACK timer scheduled on data receive"); |
|
|
|
|
struct UASYNC* ua; struct UTUN_INSTANCE inst; etcp_recv_fn recv_cb; |
|
|
|
|
@ -1343,6 +1381,7 @@ int main(void) {
|
|
|
|
|
test_circular_wrap(); |
|
|
|
|
test_data_integrity(); |
|
|
|
|
test_ack_receive(); |
|
|
|
|
test_delivery_stats(); |
|
|
|
|
test_ack_timer(); |
|
|
|
|
test_send_q(); |
|
|
|
|
test_loopback(); |
|
|
|
|
|