You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
111 lines
3.8 KiB
111 lines
3.8 KiB
/** |
|
* Test for UDP socket API |
|
* Tests basic create/destroy, send/receive functionality |
|
*/ |
|
|
|
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <string.h> |
|
#include <unistd.h> |
|
#include <assert.h> |
|
#include <sys/socket.h> |
|
#include <netinet/in.h> |
|
#include <arpa/inet.h> |
|
|
|
#include "../src/udp_socket.h" |
|
|
|
static int g_packet_received = 0; |
|
static char g_received_data[1024]; |
|
static size_t g_received_len = 0; |
|
static struct sockaddr_storage g_received_from; |
|
|
|
static void test_recv_callback(udp_socket_t* sock, |
|
const uint8_t* data, |
|
size_t len, |
|
const struct sockaddr* from_addr, |
|
void* user_data) { |
|
(void)sock; |
|
(void)user_data; |
|
|
|
g_packet_received = 1; |
|
g_received_len = len < sizeof(g_received_data) ? len : sizeof(g_received_data) - 1; |
|
memcpy(g_received_data, data, g_received_len); |
|
g_received_data[g_received_len] = '\0'; |
|
|
|
memcpy(&g_received_from, from_addr, from_addr->sa_family == AF_INET ? |
|
sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6)); |
|
} |
|
|
|
int main() { |
|
printf("=== UDP Socket Test ===\n"); |
|
|
|
// Test 1: Create socket |
|
printf("Test 1: Creating UDP socket..."); |
|
udp_socket_t* sock1 = udp_socket_create(NULL, 0); |
|
assert(sock1 != NULL); |
|
printf(" PASS (fd=%d)\n", udp_socket_get_fd(sock1)); |
|
|
|
// Test 2: Get local address |
|
printf("Test 2: Getting local address..."); |
|
struct sockaddr_storage local_addr; |
|
socklen_t addr_len; |
|
udp_socket_get_local_addr(sock1, &local_addr, &addr_len); |
|
assert(local_addr.ss_family == AF_INET); |
|
struct sockaddr_in* sin = (struct sockaddr_in*)&local_addr; |
|
printf(" PASS (port=%d)\n", ntohs(sin->sin_port)); |
|
|
|
uint16_t bound_port = ntohs(sin->sin_port); |
|
|
|
// Test 3: Create second socket |
|
printf("Test 3: Creating second UDP socket..."); |
|
udp_socket_t* sock2 = udp_socket_create(NULL, 0); |
|
assert(sock2 != NULL); |
|
printf(" PASS (fd=%d)\n", udp_socket_get_fd(sock2)); |
|
|
|
// Test 4: Set receive callback |
|
printf("Test 4: Setting receive callback..."); |
|
udp_socket_set_recv_callback(sock1, test_recv_callback, NULL); |
|
printf(" PASS\n"); |
|
|
|
// Test 5: Send data from sock2 to sock1 |
|
printf("Test 5: Sending data..."); |
|
struct sockaddr_in dest_addr; |
|
dest_addr.sin_family = AF_INET; |
|
dest_addr.sin_port = htons(bound_port); |
|
inet_pton(AF_INET, "127.0.0.1", &dest_addr.sin_addr); |
|
|
|
const char* test_data = "Hello, UDP!"; |
|
int sent = udp_socket_send(sock2, (const uint8_t*)test_data, strlen(test_data), |
|
(struct sockaddr*)&dest_addr); |
|
assert(sent > 0); |
|
printf(" PASS (sent %d bytes)\n", sent); |
|
|
|
// Даем время на доставку |
|
usleep(10000); |
|
|
|
// Test 6: Receive data (simulate - нужен poll loop в реальном приложении) |
|
printf("Test 6: Checking receive (manual test required)...\n"); |
|
printf(" To test receive, use: echo -n \"test\" | nc -u 127.0.0.1 %d\n", bound_port); |
|
|
|
// Test 7: Test port binding |
|
printf("Test 7: Testing port binding conflict..."); |
|
udp_socket_t* sock3 = udp_socket_create(NULL, bound_port); |
|
assert(sock3 == NULL); // Should fail - port already in use |
|
printf(" PASS (correctly rejected binding to used port)\n"); |
|
|
|
// Test 8: Set socket option |
|
printf("Test 8: Setting socket option (SO_REUSEADDR)..."); |
|
int reuse = 1; |
|
int ret = udp_socket_set_option(sock1, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); |
|
assert(ret == 0); |
|
printf(" PASS\n"); |
|
|
|
// Cleanup |
|
printf("Test 9: Destroying sockets..."); |
|
udp_socket_destroy(sock1); |
|
udp_socket_destroy(sock2); |
|
printf(" PASS\n"); |
|
|
|
printf("\n=== All UDP Socket Tests Passed ===\n"); |
|
return 0; |
|
} |