#include #include #include #include "internal/icmp_internal.h" #include "internal/icmp_socket.h" #include "test_helpers.h" /* Test 1: socket_create() success (skip without privileges) */ Test(socket, create_success) { struct icmp_handle h = {0}; int ret = socket_create(&h); if (-1 == ret && ICMP_ERR_PERMISSION == h.last_error) { cr_skip("Test requires CAP_NET_RAW or root privileges"); } cr_assert_eq(ret, 0, "socket_create() failed: %s", h.error_msg); cr_assert_geq(h.fd, 0, "Expected valid file descriptor"); cr_assert_eq(h.last_error, ICMP_OK, "Expected no error"); close(h.fd); } /* Test 2: socket_create() sets error message on failure */ Test(socket, create_error_message) { struct icmp_handle h = {0}; int ret = socket_create(&h); if (0 == ret) { /* We have privileges - can't test error case */ close(h.fd); cr_skip("Test requires missing CAP_NET_RAW"); } /* Without privileges, should get ICMP_ERR_PERMISSION */ cr_assert_eq(h.last_error, ICMP_ERR_PERMISSION); cr_assert_neq(h.error_msg[0], '\0', "Error message should not be empty"); } /* Test 3: socket_configure() success (skip without privileges) */ Test(socket, configure_success) { if (0 == has_net_raw_capability()) { cr_skip("Test requires CAP_NET_RAW or root privileges"); } struct icmp_handle h = {0}; socket_create(&h); int ret = socket_configure(&h); cr_assert_eq(ret, 0, "socket_configure() failed: %s", h.error_msg); cr_assert_eq(h.last_error, ICMP_OK, "Expected no error"); /* Verify O_NONBLOCK flag is set */ int flags = fcntl(h.fd, F_GETFL, 0); cr_assert(flags & O_NONBLOCK, "O_NONBLOCK flag not set"); close(h.fd); } /* Test 4: socket_configure() with invalid fd (always runnable) */ Test(socket, configure_invalid_fd) { struct icmp_handle h = {0}; h.fd = -1; int ret = socket_configure(&h); cr_assert_eq(ret, -1, "Expected -1 for invalid fd"); cr_assert_eq(h.last_error, ICMP_ERR_SOCKET, "Expected ICMP_ERR_SOCKET"); cr_assert_neq(h.error_msg[0], '\0', "Error message should not be empty"); }