net-tools/tests/ping/tracker/test_tracker.c
2026-03-18 21:08:01 +01:00

165 lines
4 KiB
C

#include <criterion/criterion.h>
#include <stdint.h>
#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(t.nb_sent, (size_t)0);
cr_assert_eq(t.nb_recv, (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(t.nb_sent, (size_t)1);
cr_assert_eq(t.nb_recv, (size_t)1);
}
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(t.nb_recv, (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(t.nb_sent, (size_t)3);
cr_assert_eq(t.nb_recv, (size_t)1);
cr_assert_eq(t.nb_sent - t.nb_recv, (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(t.nb_sent, (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(t.nb_sent, (size_t)2);
cr_assert_eq(t.nb_recv, (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(t.nb_sent, (size_t)128);
cr_assert_eq(t.nb_recv, (size_t)0);
}