#include #include #include #include "icmp.h" #include "internal/icmp_internal.h" /* Helper: check if we have CAP_NET_RAW capability */ static int has_net_raw_capability(void) { icmp_handle_t *h = icmp_create(); if (NULL != h) { icmp_destroy(h); return 1; } return 0; } /* Test 1: icmp_create() success (skip without privileges) */ Test(handle, create_success) { icmp_handle_t *h = icmp_create(); if (NULL == h) { cr_skip("Test requires CAP_NET_RAW or root privileges"); } cr_assert_not_null(h, "icmp_create() returned NULL"); /* Verify FD is valid */ int fd = icmp_get_fd(h); cr_assert_geq(fd, 0, "Expected valid file descriptor"); /* Verify no error */ const char *err = icmp_strerror(h); cr_assert_str_eq(err, "No error"); icmp_destroy(h); } /* Test 2: icmp_create() returns NULL without privileges */ Test(handle, create_without_privileges) { icmp_handle_t *h = icmp_create(); if (NULL != h) { icmp_destroy(h); cr_skip("Test requires missing CAP_NET_RAW"); } cr_assert_null(h, "Expected NULL without privileges"); } /* Test 3: icmp_create() sets non-blocking mode */ Test(handle, create_nonblocking) { if (0 == has_net_raw_capability()) { cr_skip("Test requires CAP_NET_RAW or root privileges"); } icmp_handle_t *h = icmp_create(); cr_assert_not_null(h); int fd = icmp_get_fd(h); int flags = fcntl(fd, F_GETFL, 0); cr_assert(flags & O_NONBLOCK, "Socket should be non-blocking"); icmp_destroy(h); } /* Test 4: icmp_create() initializes handle properly */ Test(handle, create_initializes_handle) { if (0 == has_net_raw_capability()) { cr_skip("Test requires CAP_NET_RAW or root privileges"); } icmp_handle_t *h = icmp_create(); cr_assert_not_null(h); struct icmp_handle *handle = (struct icmp_handle *)h; cr_assert_geq(handle->fd, 0, "FD should be valid"); cr_assert_eq(handle->last_error, ICMP_OK, "Error should be ICMP_OK"); cr_assert_eq(handle->error_msg[0], '\0', "Error message should be empty"); icmp_destroy(h); }