#include #include #include "internal/ping/tracker.h" static struct timespec make_ts(long sec, long nsec) { struct timespec ts; ts.tv_sec = sec; ts.tv_nsec = nsec; return (ts); } Test(ping_tracker, init) { struct ping_tracker t; ping_tracker_init(&t); cr_assert_eq(ping_tracker_sent(&t), (size_t)0); cr_assert_eq(ping_tracker_recv(&t), (size_t)0); cr_assert_eq(ping_tracker_lost(&t), (size_t)0); } Test(ping_tracker, basic_send_recv) { struct ping_tracker t; struct timespec ts_send; struct timespec ts_recv; int64_t rtt; ping_tracker_init(&t); ts_send = make_ts(1, 0); ts_recv = make_ts(1, 10000000); /* 10 ms later */ ping_tracker_record_send(&t, 1, &ts_send); rtt = ping_tracker_record_recv(&t, 1, &ts_recv); cr_assert_eq(rtt, (int64_t)10000000, "Expected RTT of 10ms in ns"); cr_assert_eq(ping_tracker_sent(&t), (size_t)1); cr_assert_eq(ping_tracker_recv(&t), (size_t)1); cr_assert_eq(ping_tracker_lost(&t), (size_t)0); } Test(ping_tracker, double_recv_ignored) { struct ping_tracker t; struct timespec ts_send; struct timespec ts_recv; int64_t rtt; ping_tracker_init(&t); ts_send = make_ts(0, 0); ts_recv = make_ts(0, 5000000); ping_tracker_record_send(&t, 5, &ts_send); rtt = ping_tracker_record_recv(&t, 5, &ts_recv); cr_assert(rtt >= 0, "First recv should succeed"); rtt = ping_tracker_record_recv(&t, 5, &ts_recv); cr_assert_eq(rtt, (int64_t)-1, "Duplicate recv should return -1"); cr_assert_eq(ping_tracker_recv(&t), (size_t)1); } Test(ping_tracker, unknown_seq_returns_minus_one) { struct ping_tracker t; struct timespec ts; int64_t rtt; ping_tracker_init(&t); ts = make_ts(0, 0); rtt = ping_tracker_record_recv(&t, 42, &ts); cr_assert_eq(rtt, (int64_t)-1); } Test(ping_tracker, wraparound_seq) { struct ping_tracker t; struct timespec ts_send; struct timespec ts_recv; int64_t rtt; ping_tracker_init(&t); ts_send = make_ts(0, 0); ts_recv = make_ts(0, 1000000); /* seq 128 maps to slot 0 */ ping_tracker_record_send(&t, 128, &ts_send); rtt = ping_tracker_record_recv(&t, 128, &ts_recv); cr_assert_eq(rtt, (int64_t)1000000); } Test(ping_tracker, lost_count) { struct ping_tracker t; struct timespec ts; ping_tracker_init(&t); ts = make_ts(0, 0); ping_tracker_record_send(&t, 1, &ts); ping_tracker_record_send(&t, 2, &ts); ping_tracker_record_send(&t, 3, &ts); ping_tracker_record_recv(&t, 2, &ts); cr_assert_eq(ping_tracker_sent(&t), (size_t)3); cr_assert_eq(ping_tracker_recv(&t), (size_t)1); cr_assert_eq(ping_tracker_lost(&t), (size_t)2); } Test(ping_tracker, sent_count_increments) { struct ping_tracker t; struct timespec ts; ping_tracker_init(&t); ts = make_ts(0, 0); ping_tracker_record_send(&t, 1, &ts); ping_tracker_record_send(&t, 2, &ts); ping_tracker_record_send(&t, 3, &ts); cr_assert_eq(ping_tracker_sent(&t), (size_t)3); } Test(ping_tracker, recv_rtt_positive) { struct ping_tracker t; struct timespec ts_send; struct timespec ts_recv; int64_t rtt; ping_tracker_init(&t); ts_send = make_ts(1, 0); ts_recv = make_ts(1, 10000000); /* 10 ms later */ ping_tracker_record_send(&t, 7, &ts_send); rtt = ping_tracker_record_recv(&t, 7, &ts_recv); cr_assert(rtt > 0, "RTT should be positive"); } Test(ping_tracker, slot_reuse_after_wraparound) { struct ping_tracker t; struct timespec ts_send; struct timespec ts_recv; int64_t rtt; ping_tracker_init(&t); ts_send = make_ts(0, 0); ts_recv = make_ts(0, 1000000); /* seq=1 -> slot 1 */ ping_tracker_record_send(&t, 1, &ts_send); rtt = ping_tracker_record_recv(&t, 1, &ts_recv); cr_assert(rtt >= 0, "First round RTT should be >= 0"); /* seq=129 -> slot 129 % 128 = 1, same slot */ ping_tracker_record_send(&t, 129, &ts_send); rtt = ping_tracker_record_recv(&t, 129, &ts_recv); cr_assert(rtt >= 0, "Second round RTT should be >= 0"); cr_assert_eq(ping_tracker_sent(&t), (size_t)2); cr_assert_eq(ping_tracker_recv(&t), (size_t)2); } Test(ping_tracker, full_buffer) { struct ping_tracker t; struct timespec ts; uint16_t seq; ping_tracker_init(&t); ts = make_ts(0, 0); for (seq = 1; seq <= 128; seq++) ping_tracker_record_send(&t, seq, &ts); cr_assert_eq(ping_tracker_sent(&t), (size_t)128); cr_assert_eq(ping_tracker_recv(&t), (size_t)0); }