Compare commits

..

3 commits

22 changed files with 165 additions and 540 deletions

View file

@ -1,4 +1,5 @@
bin_PROGRAMS = ft_ping
noinst_LTLIBRARIES = libping_core.la
PING_VERSION = 0.0.1
VERSION_HEADER = $(top_srcdir)/includes/version_gen.h
@ -40,8 +41,7 @@ $(VERSION_HEADER): FORCE
FORCE:
.PHONY: FORCE
ft_ping_SOURCES = \
main.c \
libping_core_la_SOURCES = \
cli/parse.c \
cli/handlers/handle_count.c \
cli/handlers/handle_dont_fragment.c \
@ -81,12 +81,6 @@ ft_ping_SOURCES = \
stats/stats_init.c \
stats/stats_update.c
ft_ping_CPPFLAGS = \
-I $(top_srcdir)/includes \
-I $(top_srcdir)/libicmp/includes \
-I $(top_srcdir)/libcli/include \
-D_GNU_SOURCE
BASE_CFLAGS = -std=c99 $(STRICT_CFLAGS)
if ENABLE_DEBUG
@ -101,13 +95,27 @@ else
SANITIZER_FLAGS =
endif
ft_ping_CFLAGS = $(BASE_CFLAGS) $(EXTRA_CFLAGS) $(SANITIZER_FLAGS)
PING_CPPFLAGS = \
-I $(top_srcdir)/includes \
-I $(top_srcdir)/libicmp/includes \
-I $(top_srcdir)/libcli/include \
-D_GNU_SOURCE
PING_CFLAGS = $(BASE_CFLAGS) $(EXTRA_CFLAGS) $(SANITIZER_FLAGS)
libping_core_la_CPPFLAGS = $(PING_CPPFLAGS)
libping_core_la_CFLAGS = $(PING_CFLAGS)
ft_ping_SOURCES = main.c
ft_ping_CPPFLAGS = $(PING_CPPFLAGS)
ft_ping_CFLAGS = $(PING_CFLAGS)
ft_ping_LDFLAGS = $(SANITIZER_FLAGS)
ft_ping_LDADD = \
libping_core.la \
$(top_srcdir)/libicmp/libicmp.a \
$(top_builddir)/libcli/src/libcli.la \
-lm
# Build libicmp (simple Makefile) before linking
$(top_srcdir)/libicmp/libicmp.a:
$(top_srcdir)/libicmp/libicmp.a: FORCE
$(MAKE) -C $(top_srcdir)/libicmp BUILD_STATIC=yes BUILD_SHARED=no

View file

@ -1,59 +1,8 @@
check_PROGRAMS = ft_ping_test
check_PROGRAMS = test_tracker test_stats test_send
ft_ping_test_SOURCES = \
test_main.c \
cli/handlers/test_handle_count.c \
cli/handlers/test_handle_flood.c \
cli/handlers/test_handle_help.c \
cli/handlers/test_handle_interval.c \
cli/handlers/test_handle_quiet.c \
cli/handlers/test_handler_map.c \
cli/handlers/test_handle_size.c \
cli/handlers/test_handle_timeout.c \
cli/handlers/test_handle_ttl.c \
cli/handlers/test_handle_version.c \
cli/handlers/test_handle_verbose.c \
cli/handlers/test_handle_dont_fragment.c \
cli/handlers/test_handle_deadline.c \
cli/parse_utils/test_parse_int.c \
cli/parse_utils/test_parse_float.c \
cli/parse_utils/test_parse_inet_addr.c \
cli/parse_utils/test_parse_destinations.c \
ping/stats/test_stats.c \
ping/tracker/test_tracker.c \
$(top_srcdir)/src/ping/cli/parse.c \
$(top_srcdir)/src/ping/cli/handlers/handle_count.c \
$(top_srcdir)/src/ping/cli/handlers/handle_dont_fragment.c \
$(top_srcdir)/src/ping/cli/handlers/handle_deadline.c \
$(top_srcdir)/src/ping/cli/handlers/handle_flood.c \
$(top_srcdir)/src/ping/cli/handlers/handle_help.c \
$(top_srcdir)/src/ping/cli/handlers/handle_interval.c \
$(top_srcdir)/src/ping/cli/handlers/handle_quiet.c \
$(top_srcdir)/src/ping/cli/handlers/option_map.c \
$(top_srcdir)/src/ping/cli/handlers/handle_size.c \
$(top_srcdir)/src/ping/cli/handlers/handle_timeout.c \
$(top_srcdir)/src/ping/cli/handlers/handle_ttl.c \
$(top_srcdir)/src/ping/cli/handlers/handle_version.c \
$(top_srcdir)/src/ping/cli/handlers/handle_verbose.c \
$(top_srcdir)/src/ping/cli/parse_utils/parse_inet_addr.c \
$(top_srcdir)/src/ping/cli/parse_utils/parse_destinations.c \
$(top_srcdir)/src/ping/cli/config_free.c \
$(top_srcdir)/src/ping/cli/messages/help.c \
$(top_srcdir)/src/ping/cli/messages/version.c \
$(top_srcdir)/src/ping/cli/messages/error.c \
$(top_srcdir)/src/ping/tracker/init.c \
$(top_srcdir)/src/ping/tracker/record_send.c \
$(top_srcdir)/src/ping/tracker/record_recv.c \
$(top_srcdir)/src/ping/stats/stats_get.c \
$(top_srcdir)/src/ping/stats/stats_init.c \
$(top_srcdir)/src/ping/stats/stats_update.c
ft_ping_test_CPPFLAGS = \
-I $(top_srcdir)/includes \
-I $(top_srcdir)/libicmp/includes \
-I $(top_srcdir)/libcli/include \
-I $(top_srcdir)/tests \
-D_GNU_SOURCE
test_tracker_SOURCES = test_support.c ping/tracker/test_tracker.c
test_stats_SOURCES = test_support.c ping/stats/test_stats.c
test_send_SOURCES = test_support.c send/test_do_send.c
BASE_CFLAGS = -std=c99 $(STRICT_CFLAGS)
@ -69,15 +18,42 @@ else
SANITIZER_FLAGS =
endif
ft_ping_test_CFLAGS = $(BASE_CFLAGS) $(EXTRA_CFLAGS) $(SANITIZER_FLAGS)
ft_ping_test_LDFLAGS = $(SANITIZER_FLAGS)
ft_ping_test_LDADD = \
TEST_CPPFLAGS = \
-I $(top_srcdir)/includes \
-I $(top_srcdir)/libicmp/includes \
-I $(top_srcdir)/libcli/include \
-I $(top_srcdir)/tests \
-D_GNU_SOURCE
TEST_CFLAGS = $(BASE_CFLAGS) $(EXTRA_CFLAGS) $(SANITIZER_FLAGS)
TEST_LDADD = \
$(top_builddir)/src/ping/libping_core.la \
$(top_srcdir)/libicmp/libicmp.a \
$(top_builddir)/libcli/src/libcli.la \
$(CRITERION_LIBS) \
-lm
TESTS = ft_ping_test
test_tracker_CPPFLAGS = $(TEST_CPPFLAGS)
test_tracker_CFLAGS = $(TEST_CFLAGS)
test_tracker_LDFLAGS = $(SANITIZER_FLAGS)
test_tracker_LDADD = $(TEST_LDADD)
test_stats_CPPFLAGS = $(TEST_CPPFLAGS)
test_stats_CFLAGS = $(TEST_CFLAGS)
test_stats_LDFLAGS = $(SANITIZER_FLAGS)
test_stats_LDADD = $(TEST_LDADD)
test_send_CPPFLAGS = $(TEST_CPPFLAGS)
test_send_CFLAGS = $(TEST_CFLAGS)
test_send_LDFLAGS = $(SANITIZER_FLAGS) \
-Wl,--wrap=icmp_send_echo \
-Wl,--wrap=icmp_should_retry \
-Wl,--wrap=icmp_strerror \
-Wl,--wrap=ping_scheduler_arm
test_send_LDADD = $(TEST_LDADD)
TESTS = test_tracker test_stats test_send
# Version header needed by test_main.c
BUILT_SOURCES = $(top_srcdir)/includes/version_gen.h

View file

@ -1,24 +0,0 @@
#include <criterion/criterion.h>
#include "ping/cli.h"
#include "internal/ping/cli_handlers.h"
/* Test 1: basic test */
Test(cli_handle_count, valid_number)
{
struct ping_config config = {0};
const char *arg = "42";
int ret = cli_handle_count(arg, &config);
cr_assert_eq(ret, CLI_SUCCESS);
cr_assert_eq(config.count, 42);
}
/* Test 2: invalid number */
Test(cli_handle_count, invalid_number)
{
struct ping_config config = {0};
const char *arg = "-42";
int ret = cli_handle_count(arg, &config);
cr_assert_eq(ret, CLI_ERROR);
}

View file

@ -1,22 +0,0 @@
#include <criterion/criterion.h>
#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);
}

View file

@ -1,14 +0,0 @@
#include <criterion/criterion.h>
#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);
}

View file

@ -1,15 +0,0 @@
#include <criterion/criterion.h>
#include "ping/cli.h"
#include "internal/ping/cli_handlers.h"
#include "ping/ft_ping_flags.h"
/* Test 1: test flag*/
Test(handle_flood, flag_test)
{
struct ping_config config = {0};
const char *arg = "";
const int ret = cli_handle_flood(arg, &config);
cr_assert(HAS_FLAG(config.flags, FLAG_FLOOD));
cr_assert_eq(ret, CLI_SUCCESS);
}

View file

@ -1,13 +0,0 @@
#include <criterion/criterion.h>
#include "ping/cli.h"
#include "internal/ping/cli_handlers.h"
/* Test 1: exit code test */
Test(handle_help, exit_code)
{
struct ping_config config = {0};
const char *arg = "";
int ret = cli_handle_help(arg, &config);
cr_assert_eq(ret, CLI_EXIT_SUCCESS);
}

View file

@ -1,24 +0,0 @@
#include <criterion/criterion.h>
#include "ping/cli.h"
#include "internal/ping/cli_handlers.h"
/* Test 1: basic test */
Test(cli_handle_interval, valid_number)
{
struct ping_config config = {0};
const char *arg = ".42";
int ret = cli_handle_interval(arg, &config);
cr_assert_eq(ret, CLI_SUCCESS);
cr_assert_float_eq(config.interval, .42, .001);
}
/* Test 2: invalid number */
Test(cli_handle_interval, invalid_number)
{
struct ping_config config = {0};
const char *arg = "-42";
int ret = cli_handle_interval(arg, &config);
cr_assert_eq(ret, CLI_ERROR);
}

View file

@ -1,15 +0,0 @@
#include "ping/cli.h"
#include "ping/ft_ping_flags.h"
#include "internal/ping/cli_handlers.h"
#include <criterion/criterion.h>
/* Test 1: test flag*/
Test(handle_quiet, flag_test)
{
struct ping_config config = {0};
const char *arg = "";
const int ret = cli_handle_quiet(arg, &config);
cr_assert(HAS_FLAG(config.flags, FLAG_QUIET));
cr_assert_eq(ret, CLI_SUCCESS);
}

View file

@ -1,34 +0,0 @@
#include <criterion/criterion.h>
#include "ping/cli.h"
#include "internal/ping/cli_handlers.h"
/* Test 1: basic test */
Test(cli_handle_size, valid_number)
{
struct ping_config config = {0};
const char *arg = "65527";
int ret = cli_handle_size(arg, &config);
cr_assert_eq(ret, CLI_SUCCESS);
cr_assert_eq(config.packet_size, 65527);
}
/* Test 2: invalid number */
Test(cli_handle_size, invalid_number)
{
struct ping_config config = {0};
const char *arg = "-42";
int ret = cli_handle_size(arg, &config);
cr_assert_eq(ret, CLI_ERROR);
}
/* Test 3: max test */
Test(cli_handle_size, limit_test)
{
struct ping_config config = {0};
const char *arg = "65528";
int ret = cli_handle_size(arg, &config);
cr_assert_eq(ret, CLI_ERROR);
}

View file

@ -1,24 +0,0 @@
#include <criterion/criterion.h>
#include "ping/cli.h"
#include "internal/ping/cli_handlers.h"
/* Test 1: basic test */
Test(cli_handle_timeout, valid_number)
{
struct ping_config config = {0};
const char *arg = ".42";
int ret = cli_handle_timeout(arg, &config);
cr_assert_eq(ret, CLI_SUCCESS);
cr_assert_float_eq(config.timeout, .42, .001);
}
/* Test 2: invalid number */
Test(cli_handle_timeout, invalid_number)
{
struct ping_config config = {0};
const char *arg = "-42";
int ret = cli_handle_timeout(arg, &config);
cr_assert_eq(ret, CLI_ERROR);
}

View file

@ -1,34 +0,0 @@
#include <criterion/criterion.h>
#include "ping/cli.h"
#include "internal/ping/cli_handlers.h"
/* Test 1: basic test */
Test(cli_handle_ttl, valid_number)
{
struct ping_config config = {0};
const char *arg = "255";
int ret = cli_handle_ttl(arg, &config);
cr_assert_eq(ret, CLI_SUCCESS);
cr_assert_eq(config.ttl, 255);
}
/* Test 2: invalid number */
Test(cli_handle_ttl, invalid_number)
{
struct ping_config config = {0};
const char *arg = "-1";
int ret = cli_handle_ttl(arg, &config);
cr_assert_eq(ret, CLI_ERROR);
}
/* Test 3: max test */
Test(cli_handle_ttl, limit_test)
{
struct ping_config config = {0};
const char *arg = "256";
int ret = cli_handle_ttl(arg, &config);
cr_assert_eq(ret, CLI_ERROR);
}

View file

@ -1,15 +0,0 @@
#include "ping/cli.h"
#include "ping/ft_ping_flags.h"
#include "internal/ping/cli_handlers.h"
#include <criterion/criterion.h>
/* Test 1: test flag*/
Test(handle_verbose, flag_test)
{
struct ping_config config = {0};
const char *arg = "";
const int ret = cli_handle_verbose(arg, &config);
cr_assert(HAS_FLAG(config.flags, FLAG_VERBOSE));
cr_assert_eq(ret, CLI_SUCCESS);
}

View file

@ -1,13 +0,0 @@
#include <criterion/criterion.h>
#include "ping/cli.h"
#include "internal/ping/cli_handlers.h"
/* Test 1: exit code test */
Test(handle_version, exit_code)
{
struct ping_config config = {0};
const char *arg = "";
int ret = cli_handle_version(arg, &config);
cr_assert_eq(ret, CLI_EXIT_SUCCESS);
}

View file

@ -1,17 +0,0 @@
#include "internal/ping/cli_handlers.h"
#include <criterion/criterion.h>
#include <stddef.h>
/* Test 1: g_options is null terminated */
Test(_test_handler_map, always_pass)
{
size_t i = 0;
for (i = 0; NULL != g_options[i].description; ++i);
cr_assert(g_options[i].description == NULL);
cr_assert(g_options[i].arg_type == 0);
cr_assert(g_options[i].handler == NULL);
cr_assert(g_options[i].has_arg == 0);
cr_assert(g_options[i].long_opt == NULL);
cr_assert(g_options[i].short_opt == 0);
}

View file

@ -1,38 +0,0 @@
#include <criterion/criterion.h>
#include <stdlib.h>
#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);
}

View file

@ -1,69 +0,0 @@
#include <criterion/criterion.h>
#include "internal/cli/parse_utils.h"
/* Test 1: Valid simple number */
Test(parse_float, valid_number)
{
float result;
int ret = cli_parse_float("42.42", &result);
cr_assert_eq(ret, 0);
cr_assert_float_eq(result, 42.42, 0.0001);
}
/* Test 2: Zero */
Test(parse_float, zero)
{
float result;
int ret = cli_parse_float("0", &result);
cr_assert_eq(ret, 0);
cr_assert_float_eq(result, 0, 0.0001);
}
/* Test 3: NULL pointer */
Test(parse_float, null_pointer)
{
float result;
int ret = cli_parse_float(NULL, &result);
cr_assert_eq(ret, 1);
}
/* Test 4: Empty string */
Test(parse_float, empty_string)
{
float result;
int ret = cli_parse_float("", &result);
cr_assert_eq(ret, 1);
}
/* Test 5: Negative number (cli_parse_float accepts negatives; use cli_parse_ufloat to reject) */
Test(parse_float, negative_number)
{
float result;
int ret = cli_parse_float("-42", &result);
cr_assert_eq(ret, 0);
cr_assert_float_eq(result, -42.0f, 0.001f);
}
/* Test 6: Invalid characters */
Test(parse_float, invalid_characters)
{
float result;
int ret = cli_parse_float("42abc", &result);
cr_assert_eq(ret, 1);
}
/* Test 7: Dot + number */
Test(parse_float, dot)
{
float result;
int ret = cli_parse_float(".42", &result);
cr_assert_eq(ret, 0);
cr_assert_float_eq(result, 0.42, 0.0001);
}

View file

@ -1,21 +0,0 @@
#include <criterion/criterion.h>
#include <string.h>
#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("invalid.host.local", &out);
cr_assert_eq(ret, 1);
}

View file

@ -1,68 +0,0 @@
#include <criterion/criterion.h>
#include <stdint.h>
#include "internal/cli/parse_utils.h"
/* Test 1: Valid simple number */
Test(parse_uint64, valid_number)
{
uint64_t result;
int ret = cli_parse_uint64("42", &result);
cr_assert_eq(ret, 0);
cr_assert_eq(result, 42);
}
/* Test 2: Zero */
Test(parse_uint64, zero)
{
uint64_t result;
int ret = cli_parse_uint64("0", &result);
cr_assert_eq(ret, 0);
cr_assert_eq(result, 0);
}
/* Test 3: NULL pointer */
Test(parse_uint64, null_pointer)
{
uint64_t result;
int ret = cli_parse_uint64(NULL, &result);
cr_assert_eq(ret, 1);
}
/* Test 4: Empty string */
Test(parse_uint64, empty_string)
{
uint64_t result;
int ret = cli_parse_uint64("", &result);
cr_assert_eq(ret, 1);
}
/* Test 5: Negative number */
Test(parse_uint64, negative_number)
{
uint64_t result;
int ret = cli_parse_uint64("-42", &result);
cr_assert_eq(ret, 1);
}
/* Test 6: Invalid characters */
Test(parse_uint64, invalid_characters)
{
uint64_t result;
int ret = cli_parse_uint64("42abc", &result);
cr_assert_eq(ret, 1);
}
/* Test 7: Overflow */
Test(parse_uint64, overflow)
{
uint64_t result;
int ret = cli_parse_uint64("18446744073709551616", &result);
cr_assert_eq(ret, 1);
}

106
tests/send/test_do_send.c Normal file
View file

@ -0,0 +1,106 @@
#include <criterion/criterion.h>
#include <netinet/in.h>
#include "compiler.h"
#include <stddef.h>
#include <stdint.h>
#include "icmp.h"
#include "internal/ping/send.h"
#include "internal/ping/ping_state.h"
#include "internal/ping/tracker.h"
#include "ping/ping.h"
/* Controllable mock state */
int g_mock_send_ret;
int g_mock_retry_ret;
int __wrap_icmp_send_echo(icmp_handle_t *h __unused, struct in_addr dest
__unused, uint16_t id __unused, uint16_t seq __unused, uint8_t ttl
__unused, const void *payload __unused, size_t len __unused)
{
return g_mock_send_ret;
}
int __wrap_icmp_should_retry(const icmp_handle_t *h __unused)
{
return g_mock_retry_ret;
}
const char *__wrap_icmp_strerror(const icmp_handle_t *h __unused)
{
return "mock error";
}
int __wrap_ping_scheduler_arm(const struct ping_config *c __unused)
{
return 0;
}
static struct ping_config g_config;
static struct ping_tracker g_tracker;
static struct ping_state g_state;
static void
setup(void)
{
g_config = (struct ping_config){0};
g_state = (struct ping_state){
.handle = NULL,
.config = &g_config,
.tracker = &g_tracker,
.seq = 0,
};
ping_tracker_init(&g_tracker);
g_mock_send_ret = 0;
g_mock_retry_ret = 0;
}
Test(do_send, success_increments_seq, .init = setup)
{
g_mock_send_ret = 0;
do_send(&g_state, 16);
cr_assert_eq(g_state.seq, (uint16_t)1);
cr_assert_eq(g_tracker.nb_sent, (size_t)1);
}
Test(do_send, eagain_does_not_consume_seq, .init = setup)
{
g_mock_send_ret = 1;
g_mock_retry_ret = 1;
do_send(&g_state, 16);
cr_assert_eq(g_state.seq, (uint16_t)0);
cr_assert_eq(g_tracker.nb_sent, (size_t)0);
}
Test(do_send, hard_error_does_not_consume_seq, .init = setup)
{
g_mock_send_ret = -1;
g_mock_retry_ret = 0;
do_send(&g_state, 16);
cr_assert_eq(g_state.seq, (uint16_t)0);
cr_assert_eq(g_tracker.nb_sent, (size_t)0);
}
Test(do_send, multiple_success_increments_seq, .init = setup)
{
g_mock_send_ret = 0;
do_send(&g_state, 16);
do_send(&g_state, 16);
do_send(&g_state, 16);
cr_assert_eq(g_state.seq, (uint16_t)3);
cr_assert_eq(g_tracker.nb_sent, (size_t)3);
}
Test(do_send, eagain_then_success_uses_same_seq, .init = setup)
{
g_mock_send_ret = 1;
g_mock_retry_ret = 1;
do_send(&g_state, 16);
cr_assert_eq(g_state.seq, (uint16_t)0);
g_mock_send_ret = 0;
g_mock_retry_ret = 0;
do_send(&g_state, 16);
cr_assert_eq(g_state.seq, (uint16_t)1);
cr_assert_eq(g_tracker.nb_sent, (size_t)1);
}

View file

@ -1,9 +0,0 @@
#include <criterion/criterion.h>
#include "version_gen.h"
char *g_prog_name = "ft_ping";
Test(dummy, always_pass)
{
cr_assert(1, "Hello, world!");
}

4
tests/test_support.c Normal file
View file

@ -0,0 +1,4 @@
#include "version_gen.h"
char *g_prog_name = "ft_ping";