diff --git a/sources/ping.mk b/sources/ping.mk index ff15633..e54eda2 100644 --- a/sources/ping.mk +++ b/sources/ping.mk @@ -55,8 +55,12 @@ PING_TESTS = $(PING_TESTS_DIR)/test_main.c \ $(PING_TESTS_DIR)/cli/handlers/test_handle_ttl.c \ $(PING_TESTS_DIR)/cli/handlers/test_handle_version.c \ $(PING_TESTS_DIR)/cli/handlers/test_handle_verbose.c \ + $(PING_TESTS_DIR)/cli/handlers/test_handle_dont_fragment.c \ + $(PING_TESTS_DIR)/cli/handlers/test_handle_deadline.c \ $(PING_TESTS_DIR)/cli/parse_utils/test_parse_int.c \ $(PING_TESTS_DIR)/cli/parse_utils/test_parse_float.c \ + $(PING_TESTS_DIR)/cli/parse_utils/test_parse_inet_addr.c \ + $(PING_TESTS_DIR)/cli/parse_utils/test_parse_destinations.c \ $(PING_TESTS_DIR)/ping/stats/test_stats.c \ $(PING_TESTS_DIR)/ping/tracker/test_tracker.c \ diff --git a/tests/cli/handlers/test_handle_deadline.c b/tests/cli/handlers/test_handle_deadline.c new file mode 100644 index 0000000..d253da3 --- /dev/null +++ b/tests/cli/handlers/test_handle_deadline.c @@ -0,0 +1,22 @@ +#include +#include "ping/cli.h" +#include "internal/ping/cli_handlers.h" + +Test(cli_handle_deadline, valid_number) +{ + struct ping_config config = {0}; + const char *arg = "1.5"; + int ret = cli_handle_deadline(arg, &config); + + cr_assert_eq(ret, CLI_SUCCESS); + cr_assert_float_eq(config.deadline, 1.5, .001); +} + +Test(cli_handle_deadline, invalid_number) +{ + struct ping_config config = {0}; + const char *arg = "-1"; + int ret = cli_handle_deadline(arg, &config); + + cr_assert_eq(ret, CLI_ERROR); +} diff --git a/tests/cli/handlers/test_handle_dont_fragment.c b/tests/cli/handlers/test_handle_dont_fragment.c new file mode 100644 index 0000000..a1b40d9 --- /dev/null +++ b/tests/cli/handlers/test_handle_dont_fragment.c @@ -0,0 +1,14 @@ +#include +#include "ping/cli.h" +#include "ping/ft_ping_flags.h" +#include "internal/ping/cli_handlers.h" + +Test(handle_dont_fragment, flag_test) +{ + struct ping_config config = {0}; + const char *arg = ""; + const int ret = cli_handle_dont_fragment(arg, &config); + + cr_assert(HAS_FLAG(config.flags, FLAG_DONT_FRAGMENT)); + cr_assert_eq(ret, CLI_SUCCESS); +} diff --git a/tests/cli/parse_utils/test_parse_destinations.c b/tests/cli/parse_utils/test_parse_destinations.c new file mode 100644 index 0000000..b8eebbe --- /dev/null +++ b/tests/cli/parse_utils/test_parse_destinations.c @@ -0,0 +1,38 @@ +#include +#include +#include "ping/cli.h" +#include "internal/ping/parse_utils.h" + +Test(cli_parse_destinations, no_destinations) +{ + struct ping_config config = {0}; + char *argv[] = {"ping"}; + int argc = 1; + int ret = cli_parse_destinations(argc, argv, argc, &config); + + cr_assert_eq(ret, CLI_ERROR); +} + +Test(cli_parse_destinations, single_destination) +{ + struct ping_config config = {0}; + char *argv[] = {"ping", "127.0.0.1"}; + int argc = 2; + int ret = cli_parse_destinations(argc, argv, 1, &config); + + cr_assert_eq(ret, CLI_SUCCESS); + cr_assert_eq(config.nb_destinations, (size_t)1); + free(config.destinations); +} + +Test(cli_parse_destinations, multiple_destinations) +{ + struct ping_config config = {0}; + char *argv[] = {"ping", "127.0.0.1", "127.0.0.2"}; + int argc = 3; + int ret = cli_parse_destinations(argc, argv, 1, &config); + + cr_assert_eq(ret, CLI_SUCCESS); + cr_assert_eq(config.nb_destinations, (size_t)2); + free(config.destinations); +} diff --git a/tests/cli/parse_utils/test_parse_inet_addr.c b/tests/cli/parse_utils/test_parse_inet_addr.c new file mode 100644 index 0000000..f9e7976 --- /dev/null +++ b/tests/cli/parse_utils/test_parse_inet_addr.c @@ -0,0 +1,21 @@ +#include +#include +#include "ping/ping.h" +#include "internal/ping/parse_utils.h" + +Test(cli_parse_inet_addr, valid_ip) +{ + struct destinations out = {0}; + int ret = cli_parse_inet_addr("127.0.0.1", &out); + + cr_assert_eq(ret, 0); + cr_assert_str_eq(out.dom, "127.0.0.1"); +} + +Test(cli_parse_inet_addr, invalid_host) +{ + struct destinations out = {0}; + int ret = cli_parse_inet_addr("not.a.real.host.invalid", &out); + + cr_assert_eq(ret, 1); +} diff --git a/tests/ping/stats/test_stats.c b/tests/ping/stats/test_stats.c index 3c0de39..01d2120 100644 --- a/tests/ping/stats/test_stats.c +++ b/tests/ping/stats/test_stats.c @@ -62,3 +62,54 @@ Test(ping_stats, identical_values_mdev_zero) cr_assert_float_eq(avg_ms, 15.0, 1e-6); cr_assert_float_eq(mdev_ms, 0.0, 1e-3); } + +Test(ping_stats, count_tracked) +{ + struct ping_stats s; + + ping_stats_init(&s); + ping_stats_update(&s, 10000000LL); + ping_stats_update(&s, 20000000LL); + ping_stats_update(&s, 30000000LL); + cr_assert_eq(s.count, (size_t)3); +} + +Test(ping_stats, min_max_out_of_order) +{ + struct ping_stats s; + double min_ms, max_ms, avg_ms, mdev_ms; + + ping_stats_init(&s); + ping_stats_update(&s, 30000000LL); /* 30 ms */ + ping_stats_update(&s, 10000000LL); /* 10 ms */ + ping_stats_update(&s, 20000000LL); /* 20 ms */ + ping_stats_get(&s, &min_ms, &max_ms, &avg_ms, &mdev_ms); + cr_assert_float_eq(min_ms, 10.0, 1e-6); + cr_assert_float_eq(max_ms, 30.0, 1e-6); +} + +Test(ping_stats, large_rtt_no_overflow) +{ + struct ping_stats s; + double min_ms, max_ms, avg_ms, mdev_ms; + + ping_stats_init(&s); + ping_stats_update(&s, 10000000000LL); /* 10 s = 10000 ms */ + ping_stats_get(&s, &min_ms, &max_ms, &avg_ms, &mdev_ms); + cr_assert(min_ms > 0.0, "min_ms should be > 0"); + cr_assert(max_ms > 0.0, "max_ms should be > 0"); + cr_assert(avg_ms > 0.0, "avg_ms should be > 0"); + cr_assert_float_eq(avg_ms, 10000.0, 1e-3); +} + +Test(ping_stats, two_values_avg) +{ + struct ping_stats s; + double min_ms, max_ms, avg_ms, mdev_ms; + + ping_stats_init(&s); + ping_stats_update(&s, 10000000LL); /* 10 ms */ + ping_stats_update(&s, 30000000LL); /* 30 ms */ + ping_stats_get(&s, &min_ms, &max_ms, &avg_ms, &mdev_ms); + cr_assert_float_eq(avg_ms, 20.0, 1e-6); +} diff --git a/tests/ping/tracker/test_tracker.c b/tests/ping/tracker/test_tracker.c index 3e88d4c..c6524fd 100644 --- a/tests/ping/tracker/test_tracker.c +++ b/tests/ping/tracker/test_tracker.c @@ -101,3 +101,67 @@ Test(ping_tracker, lost_count) 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); +}