tc_sal_socket.c 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030
  1. /*
  2. * Copyright (c) 2006-2025, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2025-09-16 kurisaw initial commit
  9. */
  10. #include <rtthread.h>
  11. #include <string.h>
  12. #include <arpa/inet.h>
  13. #include <netdb.h>
  14. #include <sys/time.h>
  15. #include <sys/ioctl.h>
  16. #include <unistd.h>
  17. #include <fcntl.h>
  18. #include <netdev.h>
  19. #include <errno.h>
  20. #include "utest.h"
  21. #include "sal_socket.h"
  22. /**
  23. * @brief Comprehensive test suite for RT-Thread SAL (Socket Abstraction Layer) socket operations
  24. *
  25. * @note This test suite validates:
  26. * - 1.basic socket creation with valid and invalid parameters
  27. * - 2.socket binding functionality with proper address configuration
  28. * - 3.listen operation with various backlog configurations
  29. * - 4.TCP connection establishment and error handling
  30. * - 5.accept operation with timeout and error conditions
  31. * - 6.TCP data transmission (send/receive) with echo verification
  32. * - 7.UDP communication including sendto/recvfrom operations
  33. * - 8.proper socket closure and cleanup procedures
  34. * - 9.socket address information retrieval (getsockname/getpeername)
  35. * - 10.network device status checking and fallback mechanisms
  36. * - 11.thread-safe socket operations using RT-Thread synchronization
  37. * - 12.socket timeout configuration and non-blocking mode handling
  38. * - 13.error handling for invalid parameters and network failures
  39. * - 14.port management to avoid conflicts during concurrent testing
  40. */
  41. /* Test configuration */
  42. #define TEST_SERVER_BASE_PORT 9000 /* Base port to avoid conflicts */
  43. #define TEST_CLIENT_PORT_OFFSET 100 /* Offset for client ports */
  44. #define TEST_BUFFER_SIZE 1024
  45. #define TEST_TIMEOUT_MS 3000
  46. #define TEST_INVALID_IP "192.168.999.999"
  47. #define TEST_MAX_RETRY_ATTEMPTS 3 /* Max retry attempts for network operations */
  48. #define TEST_CONNECTION_TIMEOUT 8000 /* Increased to 8s for threaded setup */
  49. #define ACCEPT_POLL_TIMEOUT_MS 3000 /* Increased poll timeout for non-blocking accept */
  50. #define CLIENT_DELAY_MS 1000 /* Increased delay after connect before close */
  51. /* Thread synchronization */
  52. #define THREAD_WAIT_TIMEOUT 3000 /* Increased to 3s for thread waits */
  53. #define SOCKET_TIMEOUT_MS 3000 /* 3 seconds for socket operations */
  54. /* Test data */
  55. static char test_send_data[] = "Hello, RT-Thread SAL!";
  56. static char test_recv_buffer[TEST_BUFFER_SIZE];
  57. /* Local IP for tests (fallback to loopback) */
  58. static char local_ip[16] = "127.0.0.1";
  59. /* Thread synchronization structures */
  60. static struct rt_event test_event;
  61. static volatile int server_ready = 0;
  62. /* Test helper functions */
  63. static int get_available_port(int base_port)
  64. {
  65. static int port_counter = 0;
  66. int port = base_port + (port_counter++ * 2); /* Increment by 2 to avoid adjacent port conflicts */
  67. LOG_D("Generated available port: %d", port);
  68. return port;
  69. }
  70. static void safe_strcpy(char *dest, const char *src, size_t dest_size)
  71. {
  72. if (dest_size > 0)
  73. {
  74. strncpy(dest, src, dest_size - 1);
  75. dest[dest_size - 1] = '\0';
  76. }
  77. LOG_D("Copied string '%s' to destination with size %u", src, dest_size);
  78. }
  79. static void check_network_status(void)
  80. {
  81. LOG_I("Checking network device status...");
  82. /* Try to create a simple socket to test network availability */
  83. int test_sock = sal_socket(AF_INET, SOCK_STREAM, 0);
  84. if (test_sock < 0)
  85. {
  86. LOG_E("Network test socket creation failed: %d", test_sock);
  87. LOG_E("Network device or protocol family issue detected");
  88. return;
  89. }
  90. LOG_I("Network test socket created successfully: %d", test_sock);
  91. sal_closesocket(test_sock);
  92. /* Fallback to loopback; dynamic IP via netdev may not be available */
  93. safe_strcpy(local_ip, "127.0.0.1", sizeof(local_ip));
  94. LOG_I("Using loopback IP address for testing: %s", local_ip);
  95. LOG_I("Network device appears operational");
  96. }
  97. static int set_socket_timeout(int sock, int timeout_ms)
  98. {
  99. struct timeval timeout;
  100. timeout.tv_sec = timeout_ms / 1000;
  101. timeout.tv_usec = (timeout_ms % 1000) * 1000;
  102. int ret1 = sal_setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
  103. int ret2 = sal_setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
  104. if (ret1 == 0 && ret2 == 0)
  105. {
  106. LOG_D("Set socket %d timeout to %d ms", sock, timeout_ms);
  107. return 0;
  108. }
  109. else
  110. {
  111. LOG_W("Failed to set socket %d timeout to %d ms", sock, timeout_ms);
  112. return -1;
  113. }
  114. }
  115. static int create_test_socket(int domain, int type, int protocol)
  116. {
  117. int sock = sal_socket(domain, type, protocol);
  118. if (sock >= 0)
  119. {
  120. LOG_I("Created socket %d (domain=%d, type=%d, protocol=%d)", sock, domain, type, protocol);
  121. /* Set timeout for all socket operations to prevent blocking */
  122. if (set_socket_timeout(sock, SOCKET_TIMEOUT_MS) != 0)
  123. {
  124. LOG_W("Failed to set timeout for socket %d", sock);
  125. }
  126. /* Enable SO_REUSEADDR to allow reusing ports and avoid bind failures due to TIME_WAIT */
  127. int opt = 1;
  128. sal_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
  129. LOG_D("Enabled SO_REUSEADDR for socket %d", sock);
  130. }
  131. else
  132. {
  133. LOG_E("Failed to create socket (domain=%d, type=%d, protocol=%d)", domain, type, protocol);
  134. }
  135. return sock;
  136. }
  137. static void close_test_socket(int sock)
  138. {
  139. if (sock >= 0)
  140. {
  141. sal_closesocket(sock);
  142. LOG_I("Closed socket %d", sock);
  143. }
  144. }
  145. /* Server thread function */
  146. static void server_thread_entry(void *parameter)
  147. {
  148. int port = (int)parameter;
  149. int server_sock = -1;
  150. struct sockaddr_in bind_addr;
  151. int ret;
  152. LOG_I("Starting server thread on port %d", port);
  153. /* Create server socket */
  154. server_sock = create_test_socket(AF_INET, SOCK_STREAM, 0);
  155. if (server_sock < 0)
  156. {
  157. LOG_E("Failed to create server socket");
  158. rt_event_send(&test_event, 0x01);
  159. return;
  160. }
  161. /* Setup bind address */
  162. memset(&bind_addr, 0, sizeof(bind_addr));
  163. bind_addr.sin_family = AF_INET;
  164. bind_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  165. bind_addr.sin_port = htons(port);
  166. LOG_D("Configured server bind address: port %d", port);
  167. /* Bind server socket */
  168. ret = sal_bind(server_sock, (struct sockaddr *)&bind_addr, sizeof(bind_addr));
  169. if (ret != 0)
  170. {
  171. LOG_E("Failed to bind server socket %d: return=%d, errno=%d", server_sock, ret, errno);
  172. close_test_socket(server_sock);
  173. rt_event_send(&test_event, 0x01);
  174. return;
  175. }
  176. LOG_I("Server socket %d bound to port %d", server_sock, port);
  177. /* Listen on server socket */
  178. ret = sal_listen(server_sock, 5);
  179. if (ret != 0)
  180. {
  181. LOG_E("Failed to listen on server socket %d: return=%d, errno=%d", server_sock, ret, errno);
  182. close_test_socket(server_sock);
  183. rt_event_send(&test_event, 0x01);
  184. return;
  185. }
  186. LOG_I("Server socket %d listening with backlog 5", server_sock);
  187. server_ready = 1;
  188. rt_event_send(&test_event, 0x02);
  189. LOG_I("Server ready and signaled on port %d", port);
  190. /* Wait for client connection */
  191. ret = rt_event_recv(&test_event, 0x04, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
  192. RT_WAITING_FOREVER, RT_NULL);
  193. if (ret != RT_EOK)
  194. {
  195. LOG_E("Failed to receive client connect signal: %d", ret);
  196. rt_event_send(&test_event, 0x01);
  197. close_test_socket(server_sock);
  198. return;
  199. }
  200. LOG_D("Received client connect signal");
  201. /* Non-blocking accept loop to avoid blocking on aborted connections */
  202. int mode = 1;
  203. sal_ioctlsocket(server_sock, FIONBIO, &mode);
  204. LOG_D("Set server socket %d to non-blocking mode", server_sock);
  205. int elapsed = 0;
  206. int check_interval = 50;
  207. int accepted_sock = -1;
  208. while (elapsed < ACCEPT_POLL_TIMEOUT_MS)
  209. {
  210. accepted_sock = sal_accept(server_sock, RT_NULL, RT_NULL);
  211. if (accepted_sock >= 0)
  212. {
  213. LOG_I("Accepted connection on socket %d", accepted_sock);
  214. set_socket_timeout(accepted_sock, SOCKET_TIMEOUT_MS);
  215. close_test_socket(accepted_sock);
  216. break;
  217. }
  218. else
  219. {
  220. int saved_errno = errno;
  221. if (saved_errno != EWOULDBLOCK && saved_errno != EAGAIN)
  222. {
  223. LOG_E("Accept failed on socket %d: return=%d, errno=%d", server_sock, accepted_sock, saved_errno);
  224. break;
  225. }
  226. }
  227. rt_thread_mdelay(check_interval);
  228. elapsed += check_interval;
  229. }
  230. if (accepted_sock < 0)
  231. {
  232. LOG_E("Accept poll timeout or failed on socket %d", server_sock);
  233. rt_event_send(&test_event, 0x01);
  234. }
  235. /* Restore blocking mode */
  236. mode = 0;
  237. sal_ioctlsocket(server_sock, FIONBIO, &mode);
  238. LOG_D("Restored server socket %d to blocking mode", server_sock);
  239. /* Cleanup */
  240. close_test_socket(server_sock);
  241. rt_event_send(&test_event, 0x08);
  242. LOG_I("Server thread completed");
  243. }
  244. /* Client thread function */
  245. static void client_thread_entry(void *parameter)
  246. {
  247. int port = (int)parameter;
  248. int client_sock = -1;
  249. struct sockaddr_in connect_addr;
  250. int ret;
  251. LOG_I("Starting client thread for port %d", port);
  252. /* Wait for server to be ready */
  253. ret = rt_event_recv(&test_event, 0x02, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
  254. THREAD_WAIT_TIMEOUT, RT_NULL);
  255. if (ret != RT_EOK)
  256. {
  257. LOG_E("Failed to receive server ready signal: %d", ret);
  258. rt_event_send(&test_event, 0x10);
  259. return;
  260. }
  261. LOG_D("Received server ready signal");
  262. if (!server_ready)
  263. {
  264. LOG_W("Server not ready, skipping connection");
  265. rt_event_send(&test_event, 0x10);
  266. return;
  267. }
  268. /* Create client socket */
  269. client_sock = create_test_socket(AF_INET, SOCK_STREAM, 0);
  270. if (client_sock < 0)
  271. {
  272. LOG_E("Failed to create client socket");
  273. rt_event_send(&test_event, 0x10);
  274. return;
  275. }
  276. /* Setup connect address */
  277. memset(&connect_addr, 0, sizeof(connect_addr));
  278. connect_addr.sin_family = AF_INET;
  279. connect_addr.sin_addr.s_addr = inet_addr(local_ip);
  280. connect_addr.sin_port = htons(port);
  281. LOG_D("Configured client connect address: %s:%d", local_ip, port);
  282. /* Connect to server */
  283. LOG_I("Attempting to connect to server %s:%d", local_ip, port);
  284. ret = sal_connect(client_sock, (struct sockaddr *)&connect_addr, sizeof(connect_addr));
  285. LOG_I("Connect result: %d", ret);
  286. if (ret == 0)
  287. {
  288. LOG_I("Connection to server successful");
  289. rt_thread_mdelay(CLIENT_DELAY_MS);
  290. }
  291. else
  292. {
  293. LOG_E("Connection to server failed: return=%d, errno=%d", ret, errno);
  294. }
  295. /* Signal server that we've attempted connection */
  296. rt_event_send(&test_event, 0x04);
  297. LOG_D("Signaled server of connection attempt");
  298. /* Cleanup */
  299. close_test_socket(client_sock);
  300. rt_event_send(&test_event, 0x10);
  301. LOG_I("Client thread completed");
  302. }
  303. static int setup_test_server_threaded(int *server_sock, int *client_sock, int port)
  304. {
  305. rt_thread_t server_thread = RT_NULL;
  306. rt_thread_t client_thread = RT_NULL;
  307. rt_uint32_t recv_events = 0;
  308. LOG_I("Setting up threaded test server on port %d", port);
  309. /* Initialize event */
  310. rt_event_init(&test_event, "test_event", RT_IPC_FLAG_FIFO);
  311. server_ready = 0;
  312. LOG_D("Initialized test event");
  313. /* Create server thread */
  314. server_thread = rt_thread_create("server", server_thread_entry, (void *)port,
  315. 2048, RT_THREAD_PRIORITY_MAX / 2, 20);
  316. if (server_thread == RT_NULL)
  317. {
  318. LOG_E("Failed to create server thread");
  319. rt_event_detach(&test_event);
  320. return -1;
  321. }
  322. LOG_I("Created server thread");
  323. /* Create client thread */
  324. client_thread = rt_thread_create("client", client_thread_entry, (void *)port,
  325. 2048, RT_THREAD_PRIORITY_MAX / 2, 20);
  326. if (client_thread == RT_NULL)
  327. {
  328. LOG_E("Failed to create client thread");
  329. rt_thread_delete(server_thread);
  330. rt_event_detach(&test_event);
  331. return -1;
  332. }
  333. LOG_I("Created client thread");
  334. /* Start threads */
  335. rt_thread_startup(server_thread);
  336. rt_thread_startup(client_thread);
  337. LOG_I("Started server and client threads");
  338. /* Wait for both threads to complete */
  339. rt_event_recv(&test_event, 0x18 | 0x01, RT_EVENT_FLAG_OR,
  340. TEST_CONNECTION_TIMEOUT, &recv_events);
  341. LOG_D("Received events: 0x%x", recv_events);
  342. /* Cleanup threads */
  343. rt_thread_delete(server_thread);
  344. rt_thread_delete(client_thread);
  345. rt_event_detach(&test_event);
  346. LOG_I("Cleaned up threads and event");
  347. /* Check if setup partially successful */
  348. if ((recv_events & 0x10) != 0)
  349. {
  350. LOG_I("Test server setup partially successful (connect verified)");
  351. return 0;
  352. }
  353. else
  354. {
  355. LOG_E("Test server setup failed");
  356. return -1;
  357. }
  358. }
  359. static void cleanup_test_connection(int server_sock, int client_sock, int accepted_sock)
  360. {
  361. if (accepted_sock >= 0)
  362. {
  363. close_test_socket(accepted_sock);
  364. }
  365. if (client_sock >= 0)
  366. {
  367. close_test_socket(client_sock);
  368. }
  369. if (server_sock >= 0)
  370. {
  371. close_test_socket(server_sock);
  372. }
  373. LOG_I("Cleaned up test connection sockets");
  374. }
  375. /* Test cases for basic socket operations */
  376. static void TC_sal_socket_create(void)
  377. {
  378. int sock;
  379. LOG_I("Starting TC_sal_socket_create tests...");
  380. /* Test valid socket creation */
  381. LOG_I("Testing TCP socket creation...");
  382. sock = sal_socket(AF_INET, SOCK_STREAM, 0);
  383. LOG_I("TCP socket created: %d", sock);
  384. uassert_true(sock >= 0);
  385. close_test_socket(sock);
  386. LOG_I("Testing UDP socket creation...");
  387. sock = sal_socket(AF_INET, SOCK_DGRAM, 0);
  388. LOG_I("UDP socket created: %d", sock);
  389. uassert_true(sock >= 0);
  390. close_test_socket(sock);
  391. /* Test invalid parameters */
  392. LOG_I("Testing invalid family parameter...");
  393. sock = sal_socket(-1, SOCK_STREAM, 0);
  394. LOG_I("Invalid family result: %d", sock);
  395. uassert_true(sock < 0);
  396. LOG_I("Testing invalid type parameter...");
  397. sock = sal_socket(AF_INET, -1, 0);
  398. LOG_I("Invalid type result: %d", sock);
  399. uassert_true(sock < 0);
  400. LOG_I("Testing invalid protocol parameter...");
  401. sock = sal_socket(AF_INET, SOCK_STREAM, -1);
  402. LOG_I("Invalid protocol result: %d", sock);
  403. uassert_true(sock < 0);
  404. LOG_I("TC_sal_socket_create tests completed");
  405. }
  406. static void TC_sal_socket_bind(void)
  407. {
  408. int sock = -1;
  409. struct sockaddr_in addr;
  410. int ret;
  411. int test_port = get_available_port(TEST_SERVER_BASE_PORT);
  412. LOG_I("Starting TC_sal_socket_bind tests...");
  413. /* Test valid bind */
  414. LOG_I("Creating socket for bind test on port %d...", test_port);
  415. sock = create_test_socket(AF_INET, SOCK_STREAM, 0);
  416. if (sock < 0)
  417. {
  418. LOG_E("Failed to create socket for bind test");
  419. return;
  420. }
  421. memset(&addr, 0, sizeof(addr));
  422. addr.sin_family = AF_INET;
  423. addr.sin_addr.s_addr = htonl(INADDR_ANY);
  424. addr.sin_port = htons(test_port);
  425. LOG_I("Attempting to bind socket %d to port %d...", sock, test_port);
  426. ret = sal_bind(sock, (struct sockaddr *)&addr, sizeof(addr));
  427. LOG_I("Bind result: %d (expected 0)", ret);
  428. uassert_int_equal(ret, 0);
  429. close_test_socket(sock);
  430. sock = -1;
  431. LOG_I("Skipping NULL address bind test (would cause assertion)");
  432. /* Test bind with invalid socket */
  433. LOG_I("Testing bind with invalid socket...");
  434. ret = sal_bind(-1, (struct sockaddr *)&addr, sizeof(addr));
  435. LOG_I("Invalid socket bind result: %d (expected -1)", ret);
  436. uassert_int_equal(ret, -1);
  437. LOG_I("TC_sal_socket_bind tests completed");
  438. }
  439. static void TC_sal_socket_listen(void)
  440. {
  441. int sock = -1;
  442. struct sockaddr_in addr;
  443. int ret;
  444. int test_port = get_available_port(TEST_SERVER_BASE_PORT);
  445. LOG_I("Starting TC_sal_socket_listen tests...");
  446. LOG_I("Creating socket for listen test...");
  447. sock = create_test_socket(AF_INET, SOCK_STREAM, 0);
  448. if (sock < 0)
  449. {
  450. LOG_E("Failed to create socket for listen test");
  451. return;
  452. }
  453. /* Bind socket first */
  454. LOG_I("Binding socket %d for listen test on port %d...", sock, test_port);
  455. memset(&addr, 0, sizeof(addr));
  456. addr.sin_family = AF_INET;
  457. addr.sin_addr.s_addr = htonl(INADDR_ANY);
  458. addr.sin_port = htons(test_port);
  459. ret = sal_bind(sock, (struct sockaddr *)&addr, sizeof(addr));
  460. if (ret != 0)
  461. {
  462. LOG_E("Failed to bind socket %d for listen test: %d", sock, ret);
  463. close_test_socket(sock);
  464. return;
  465. }
  466. /* Test valid listen */
  467. LOG_I("Testing listen with backlog 5 on socket %d...", sock);
  468. ret = sal_listen(sock, 5);
  469. LOG_I("Listen result: %d (expected 0)", ret);
  470. uassert_int_equal(ret, 0);
  471. /* Test invalid backlog */
  472. LOG_I("Testing listen with invalid backlog (-1)...");
  473. ret = sal_listen(sock, -1);
  474. LOG_I("Invalid backlog listen result: %d", ret);
  475. if (ret != -1 && ret != 0)
  476. {
  477. LOG_W("Unexpected listen result for invalid backlog: %d", ret);
  478. }
  479. close_test_socket(sock);
  480. sock = -1;
  481. /* Test listen on invalid socket */
  482. LOG_I("Testing listen on invalid socket...");
  483. ret = sal_listen(-1, 5);
  484. LOG_I("Invalid socket listen result: %d (expected -1)", ret);
  485. uassert_int_equal(ret, -1);
  486. LOG_I("TC_sal_socket_listen tests completed");
  487. }
  488. static void TC_sal_socket_connect(void)
  489. {
  490. int ret;
  491. int test_port = get_available_port(TEST_SERVER_BASE_PORT);
  492. LOG_I("Starting TC_sal_socket_connect tests...");
  493. /* Setup test server using threaded approach */
  494. LOG_I("Setting up test server on port %d...", test_port);
  495. ret = setup_test_server_threaded(RT_NULL, RT_NULL, test_port);
  496. if (ret != 0)
  497. {
  498. LOG_W("Test server setup failed, may be expected in some environments");
  499. }
  500. else
  501. {
  502. LOG_I("Test server setup completed successfully");
  503. }
  504. /* Test connect to invalid address */
  505. LOG_I("Testing connect to invalid address %s...", TEST_INVALID_IP);
  506. int client_sock = create_test_socket(AF_INET, SOCK_STREAM, 0);
  507. if (client_sock >= 0)
  508. {
  509. struct sockaddr_in connect_addr;
  510. memset(&connect_addr, 0, sizeof(connect_addr));
  511. connect_addr.sin_family = AF_INET;
  512. connect_addr.sin_addr.s_addr = inet_addr(TEST_INVALID_IP);
  513. connect_addr.sin_port = htons(test_port);
  514. ret = sal_connect(client_sock, (struct sockaddr *)&connect_addr, sizeof(connect_addr));
  515. LOG_I("Invalid address connect result: %d (expected -1)", ret);
  516. uassert_int_equal(ret, -1);
  517. close_test_socket(client_sock);
  518. }
  519. LOG_I("TC_sal_socket_connect tests completed");
  520. }
  521. static void TC_sal_socket_accept(void)
  522. {
  523. int server_sock = -1;
  524. struct sockaddr_in bind_addr;
  525. int ret;
  526. int test_port = get_available_port(TEST_SERVER_BASE_PORT);
  527. LOG_I("Starting TC_sal_socket_accept tests...");
  528. /* Setup test server */
  529. LOG_I("Creating server socket...");
  530. server_sock = create_test_socket(AF_INET, SOCK_STREAM, 0);
  531. if (server_sock < 0)
  532. {
  533. LOG_E("Failed to create server socket");
  534. return;
  535. }
  536. memset(&bind_addr, 0, sizeof(bind_addr));
  537. bind_addr.sin_family = AF_INET;
  538. bind_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  539. bind_addr.sin_port = htons(test_port);
  540. LOG_I("Binding server socket %d to port %d...", server_sock, test_port);
  541. ret = sal_bind(server_sock, (struct sockaddr *)&bind_addr, sizeof(bind_addr));
  542. if (ret != 0)
  543. {
  544. LOG_E("Failed to bind server socket %d: %d", server_sock, ret);
  545. close_test_socket(server_sock);
  546. return;
  547. }
  548. LOG_I("Starting to listen on server socket %d...", server_sock);
  549. ret = sal_listen(server_sock, 5);
  550. if (ret != 0)
  551. {
  552. LOG_E("Failed to listen on server socket %d: %d", server_sock, ret);
  553. close_test_socket(server_sock);
  554. return;
  555. }
  556. /* Test accept on valid socket with timeout */
  557. LOG_I("Testing accept with timeout on socket %d...", server_sock);
  558. struct sockaddr_in client_addr;
  559. socklen_t addr_len = sizeof(client_addr);
  560. int accepted_sock = sal_accept(server_sock, (struct sockaddr*)&client_addr, &addr_len);
  561. if (accepted_sock >= 0)
  562. {
  563. LOG_W("Unexpected connection accepted: %d", accepted_sock);
  564. close_test_socket(accepted_sock);
  565. }
  566. else
  567. {
  568. LOG_I("Accept timed out as expected: %d", accepted_sock);
  569. }
  570. close_test_socket(server_sock);
  571. server_sock = -1;
  572. /* Test accept on invalid socket */
  573. LOG_I("Testing accept on invalid socket...");
  574. accepted_sock = sal_accept(-1, (struct sockaddr *)&client_addr, &addr_len);
  575. LOG_I("Invalid socket accept result: %d (expected -1)", accepted_sock);
  576. uassert_int_equal(accepted_sock, -1);
  577. LOG_I("TC_sal_socket_accept tests completed");
  578. }
  579. static void TC_sal_socket_send_recv(void)
  580. {
  581. int ret;
  582. int test_port = get_available_port(TEST_SERVER_BASE_PORT);
  583. int len = strlen(test_send_data);
  584. LOG_I("Starting TC_sal_socket_send_recv tests...");
  585. /* Setup test connection using threaded approach */
  586. LOG_I("Setting up test server on port %d...", test_port);
  587. ret = setup_test_server_threaded(RT_NULL, RT_NULL, test_port);
  588. if (ret != 0)
  589. {
  590. LOG_W("Failed to setup test server, skipping send/recv tests (may be expected)");
  591. return;
  592. }
  593. /* Simple send/recv test extension */
  594. LOG_I("Testing send/recv with data exchange...");
  595. int server_sock = create_test_socket(AF_INET, SOCK_STREAM, 0);
  596. int client_sock = create_test_socket(AF_INET, SOCK_STREAM, 0);
  597. if (server_sock < 0 || client_sock < 0)
  598. {
  599. LOG_E("Failed to create sockets for send/recv");
  600. goto cleanup_sr;
  601. }
  602. struct sockaddr_in bind_addr, connect_addr;
  603. memset(&bind_addr, 0, sizeof(bind_addr));
  604. bind_addr.sin_family = AF_INET;
  605. bind_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  606. bind_addr.sin_port = htons(test_port + 1);
  607. ret = sal_bind(server_sock, (struct sockaddr *)&bind_addr, sizeof(bind_addr));
  608. if (ret != 0)
  609. {
  610. LOG_E("Server bind failed: %d", ret);
  611. goto cleanup_sr;
  612. }
  613. LOG_I("Server socket %d bound to port %d", server_sock, test_port + 1);
  614. ret = sal_listen(server_sock, 5);
  615. if (ret != 0)
  616. {
  617. LOG_E("Server listen failed: %d", ret);
  618. goto cleanup_sr;
  619. }
  620. LOG_I("Server socket %d listening", server_sock);
  621. memset(&connect_addr, 0, sizeof(connect_addr));
  622. connect_addr.sin_family = AF_INET;
  623. connect_addr.sin_addr.s_addr = inet_addr(local_ip);
  624. connect_addr.sin_port = bind_addr.sin_port;
  625. ret = sal_connect(client_sock, (struct sockaddr *)&connect_addr, sizeof(connect_addr));
  626. if (ret != 0)
  627. {
  628. LOG_E("Client connect failed: %d", ret);
  629. goto cleanup_sr;
  630. }
  631. LOG_I("Client socket %d connected", client_sock);
  632. /* Server accept */
  633. int accepted_sock = sal_accept(server_sock, NULL, NULL);
  634. if (accepted_sock < 0)
  635. {
  636. LOG_E("Server accept failed: %d", accepted_sock);
  637. goto cleanup_sr;
  638. }
  639. LOG_I("Server accepted connection on socket %d", accepted_sock);
  640. /* Client send */
  641. ret = sal_sendto(client_sock, test_send_data, len, 0, NULL, 0);
  642. if (ret != len)
  643. {
  644. LOG_E("Client send failed: %d bytes sent, expected %d", ret, len);
  645. goto cleanup_sr;
  646. }
  647. LOG_I("Client sent %d bytes", ret);
  648. /* Server recv and echo */
  649. memset(test_recv_buffer, 0, sizeof(test_recv_buffer));
  650. ret = sal_recvfrom(accepted_sock, test_recv_buffer, sizeof(test_recv_buffer), 0, NULL, NULL);
  651. if (ret == len && memcmp(test_recv_buffer, test_send_data, len) == 0)
  652. {
  653. LOG_I("Server received %d bytes, matches sent data", ret);
  654. uassert_int_equal(ret, len);
  655. }
  656. else
  657. {
  658. LOG_E("Server recv failed: expected %d bytes, got %d", len, ret);
  659. }
  660. ret = sal_sendto(accepted_sock, test_recv_buffer, ret, 0, NULL, 0);
  661. if (ret != len)
  662. {
  663. LOG_E("Server echo send failed: %d bytes sent, expected %d", ret, len);
  664. }
  665. else
  666. {
  667. LOG_I("Server sent echo %d bytes", ret);
  668. }
  669. /* Client recv echo */
  670. memset(test_recv_buffer, 0, sizeof(test_recv_buffer));
  671. ret = sal_recvfrom(client_sock, test_recv_buffer, sizeof(test_recv_buffer), 0, NULL, NULL);
  672. if (ret == len && memcmp(test_recv_buffer, test_send_data, len) == 0)
  673. {
  674. LOG_I("Client received echo %d bytes, matches sent data", ret);
  675. uassert_int_equal(ret, len);
  676. }
  677. else
  678. {
  679. LOG_E("Client recv echo failed: expected %d bytes, got %d", len, ret);
  680. }
  681. cleanup_sr:
  682. cleanup_test_connection(server_sock, client_sock, accepted_sock);
  683. LOG_I("TC_sal_socket_send_recv tests completed");
  684. }
  685. static void TC_sal_socket_udp_communication(void)
  686. {
  687. int server_sock = -1, client_sock = -1;
  688. struct sockaddr_in server_bind_addr, client_bind_addr, from_addr;
  689. struct sockaddr_in server_dest_addr, client_dest_addr;
  690. socklen_t addr_len;
  691. int ret;
  692. int len;
  693. int server_port = get_available_port(TEST_SERVER_BASE_PORT);
  694. int client_port = server_port + TEST_CLIENT_PORT_OFFSET;
  695. LOG_I("Starting TC_sal_socket_udp_communication tests...");
  696. /* Create UDP sockets */
  697. server_sock = create_test_socket(AF_INET, SOCK_DGRAM, 0);
  698. if (server_sock < 0)
  699. {
  700. LOG_E("Failed to create server UDP socket");
  701. goto cleanup;
  702. }
  703. client_sock = create_test_socket(AF_INET, SOCK_DGRAM, 0);
  704. if (client_sock < 0)
  705. {
  706. LOG_E("Failed to create client UDP socket");
  707. goto cleanup;
  708. }
  709. /* Setup server bind address */
  710. memset(&server_bind_addr, 0, sizeof(server_bind_addr));
  711. server_bind_addr.sin_family = AF_INET;
  712. server_bind_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  713. server_bind_addr.sin_port = htons(server_port);
  714. /* Bind server socket */
  715. ret = sal_bind(server_sock, (struct sockaddr *)&server_bind_addr, sizeof(server_bind_addr));
  716. if (ret != 0)
  717. {
  718. LOG_W("Server bind failed, may be expected: return=%d, errno=%d", ret, errno);
  719. goto cleanup;
  720. }
  721. LOG_I("Server socket %d bound to port %d", server_sock, server_port);
  722. /* Setup client bind address */
  723. memset(&client_bind_addr, 0, sizeof(client_bind_addr));
  724. client_bind_addr.sin_family = AF_INET;
  725. client_bind_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  726. client_bind_addr.sin_port = htons(client_port);
  727. /* Bind client socket */
  728. ret = sal_bind(client_sock, (struct sockaddr *)&client_bind_addr, sizeof(client_bind_addr));
  729. if (ret != 0)
  730. {
  731. LOG_W("Client bind failed, may be expected: return=%d, errno=%d", ret, errno);
  732. goto cleanup;
  733. }
  734. LOG_I("Client socket %d bound to port %d", client_sock, client_port);
  735. /* Setup destination addresses */
  736. memset(&server_dest_addr, 0, sizeof(server_dest_addr));
  737. server_dest_addr.sin_family = AF_INET;
  738. server_dest_addr.sin_addr.s_addr = inet_addr(local_ip);
  739. server_dest_addr.sin_port = htons(server_port);
  740. memset(&client_dest_addr, 0, sizeof(client_dest_addr));
  741. client_dest_addr.sin_family = AF_INET;
  742. client_dest_addr.sin_addr.s_addr = inet_addr(local_ip);
  743. client_dest_addr.sin_port = htons(client_port);
  744. /* Test UDP sendto/recvfrom */
  745. len = strlen(test_send_data);
  746. LOG_I("Sending %d bytes from client to server...", len);
  747. ret = sal_sendto(client_sock, test_send_data, len, 0,
  748. (struct sockaddr *)&server_dest_addr, sizeof(server_dest_addr));
  749. if (ret != len)
  750. {
  751. LOG_W("UDP send failed, may be expected: %d bytes sent, errno=%d", ret, errno);
  752. goto cleanup;
  753. }
  754. LOG_I("Client sent %d bytes to server", ret);
  755. addr_len = sizeof(from_addr);
  756. memset(test_recv_buffer, 0, sizeof(test_recv_buffer));
  757. ret = sal_recvfrom(server_sock, test_recv_buffer, sizeof(test_recv_buffer), 0,
  758. (struct sockaddr *)&from_addr, &addr_len);
  759. if (ret != len)
  760. {
  761. LOG_W("UDP recv failed, may be expected: %d bytes received, errno=%d", ret, errno);
  762. goto cleanup;
  763. }
  764. LOG_I("Server received %d bytes", ret);
  765. uassert_str_equal(test_recv_buffer, test_send_data);
  766. /* Test reverse direction */
  767. LOG_I("Sending %d bytes from server to client...", len);
  768. ret = sal_sendto(server_sock, test_send_data, len, 0,
  769. (struct sockaddr *)&client_dest_addr, sizeof(client_dest_addr));
  770. if (ret != len)
  771. {
  772. LOG_W("Reverse UDP send failed, may be expected: %d bytes sent, errno=%d", ret, errno);
  773. goto cleanup;
  774. }
  775. LOG_I("Server sent %d bytes to client", ret);
  776. addr_len = sizeof(from_addr);
  777. memset(test_recv_buffer, 0, sizeof(test_recv_buffer));
  778. ret = sal_recvfrom(client_sock, test_recv_buffer, sizeof(test_recv_buffer), 0,
  779. (struct sockaddr *)&from_addr, &addr_len);
  780. if (ret != len)
  781. {
  782. LOG_W("Reverse UDP recv failed, may be expected: %d bytes received, errno=%d", ret, errno);
  783. goto cleanup;
  784. }
  785. LOG_I("Client received %d bytes", ret);
  786. uassert_str_equal(test_recv_buffer, test_send_data);
  787. cleanup:
  788. close_test_socket(server_sock);
  789. close_test_socket(client_sock);
  790. LOG_I("TC_sal_socket_udp_communication tests completed");
  791. }
  792. static void TC_sal_socket_close(void)
  793. {
  794. int sock = -1;
  795. LOG_I("Starting TC_sal_socket_close tests...");
  796. /* Test close valid socket */
  797. LOG_I("Testing close valid socket...");
  798. sock = create_test_socket(AF_INET, SOCK_STREAM, 0);
  799. LOG_I("Closing socket %d...", sock);
  800. uassert_int_equal(sal_closesocket(sock), 0);
  801. sock = -1;
  802. /* Test close invalid socket */
  803. LOG_I("Testing close invalid socket...");
  804. uassert_int_equal(sal_closesocket(-1), -1);
  805. /* Test double close */
  806. LOG_I("Testing double close...");
  807. sock = create_test_socket(AF_INET, SOCK_STREAM, 0);
  808. sal_closesocket(sock);
  809. LOG_I("Double closing socket %d (should be safe)", sock);
  810. LOG_I("TC_sal_socket_close tests completed");
  811. }
  812. static void TC_sal_socket_getpeername_getsockname(void)
  813. {
  814. int server_sock = -1;
  815. struct sockaddr_in addr;
  816. socklen_t addr_len;
  817. int ret;
  818. int test_port = get_available_port(TEST_SERVER_BASE_PORT);
  819. LOG_I("Starting TC_sal_socket_getpeername_getsockname tests...");
  820. /* Create and bind a socket for testing */
  821. server_sock = create_test_socket(AF_INET, SOCK_STREAM, 0);
  822. if (server_sock < 0)
  823. {
  824. LOG_E("Failed to create socket for getpeername/getsockname tests");
  825. return;
  826. }
  827. /* Bind socket */
  828. memset(&addr, 0, sizeof(addr));
  829. addr.sin_family = AF_INET;
  830. addr.sin_addr.s_addr = htonl(INADDR_ANY);
  831. addr.sin_port = htons(test_port);
  832. ret = sal_bind(server_sock, (struct sockaddr *)&addr, sizeof(addr));
  833. if (ret != 0)
  834. {
  835. LOG_W("Bind failed, may be expected: return=%d, errno=%d", ret, errno);
  836. close_test_socket(server_sock);
  837. return;
  838. }
  839. LOG_I("Server socket %d bound to port %d", server_sock, test_port);
  840. /* Test getsockname on valid socket */
  841. LOG_I("Testing getsockname on socket %d...", server_sock);
  842. addr_len = sizeof(addr);
  843. ret = sal_getsockname(server_sock, (struct sockaddr*)&addr, &addr_len);
  844. LOG_I("Getsockname result: %d (expected 0)", ret);
  845. uassert_int_equal(ret, 0);
  846. uassert_int_equal(addr.sin_family, AF_INET);
  847. close_test_socket(server_sock);
  848. server_sock = -1;
  849. /* Test on invalid socket */
  850. LOG_I("Testing getsockname/getpeername on invalid socket...");
  851. addr_len = sizeof(addr);
  852. ret = sal_getsockname(-1, (struct sockaddr*)&addr, &addr_len);
  853. LOG_I("Invalid socket getsockname result: %d (expected -1)", ret);
  854. uassert_int_equal(ret, -1);
  855. ret = sal_getpeername(-1, (struct sockaddr *)&addr, &addr_len);
  856. LOG_I("Invalid socket getpeername result: %d (expected -1)", ret);
  857. uassert_int_equal(ret, -1);
  858. LOG_I("TC_sal_socket_getpeername_getsockname tests completed");
  859. }
  860. static void utest_do_tc(void)
  861. {
  862. LOG_I("===========================================");
  863. LOG_I("Starting SAL Socket Basic API Tests");
  864. LOG_I("===========================================");
  865. /* Check network status before starting tests */
  866. check_network_status();
  867. /* Run test cases - each is independent */
  868. UTEST_UNIT_RUN(TC_sal_socket_create);
  869. UTEST_UNIT_RUN(TC_sal_socket_bind);
  870. UTEST_UNIT_RUN(TC_sal_socket_listen);
  871. UTEST_UNIT_RUN(TC_sal_socket_connect);
  872. UTEST_UNIT_RUN(TC_sal_socket_accept);
  873. UTEST_UNIT_RUN(TC_sal_socket_send_recv);
  874. UTEST_UNIT_RUN(TC_sal_socket_udp_communication);
  875. UTEST_UNIT_RUN(TC_sal_socket_getpeername_getsockname);
  876. UTEST_UNIT_RUN(TC_sal_socket_close);
  877. LOG_I("===========================================");
  878. LOG_I("SAL Socket Basic API Tests Completed");
  879. LOG_I("===========================================");
  880. }
  881. UTEST_TC_EXPORT(utest_do_tc, "components.net.sal.socket_basic", RT_NULL, RT_NULL, 30);