@@ -392,7 +392,7 @@ void test_xsocket_invalid_type(void)
392392
393393/*
394394 * Test: Create maximum number of sockets
395- * - Tests that the application can create up to CONFIG_POSIX_OPEN_MAX-1 sockets
395+ * - Tests that the application can create up to CONFIG_POSIX_OPEN_MAX sockets
396396 * - Verifies that attempting to create one more socket fails
397397 */
398398void test_xsocket_max_sockets (void )
@@ -776,6 +776,223 @@ void test_xconnect_operation(void)
776776 send_at_command ("AT#XCLOSE=1\r\n" );
777777}
778778
779+ /*
780+ * Test: Socket listen operation via AT command
781+ * - Command: AT#XLISTEN=<handle>\r\n
782+ * - Tests: Putting a TCP socket into listening mode
783+ */
784+ void test_xlisten_operation (void )
785+ {
786+ const char * response ;
787+ const char * cgpaddr_resp = "+CGPADDR: 0,\"10.0.0.1\",\"\"\r\nOK\r\n" ;
788+
789+ /* Create TCP server socket first */
790+ __cmock_nrf_socket_ExpectAndReturn (NRF_AF_INET , NRF_SOCK_STREAM , NRF_IPPROTO_TCP , 5 );
791+ __cmock_nrf_setsockopt_ExpectAnyArgsAndReturn (0 ); /* SO_SNDTIMEO */
792+ __cmock_nrf_setsockopt_ExpectAnyArgsAndReturn (0 ); /* SO_POLLCB */
793+ send_at_command ("AT#XSOCKET=1,1,1\r\n" ); /* family=1, type=1, role=1 (server) */
794+ response = get_captured_response ();
795+ TEST_ASSERT_TRUE (strstr (response , "#XSOCKET: 5,1,6" ) != NULL );
796+ clear_captured_response ();
797+
798+ /* Bind to port 8080 before listening */
799+ __cmock_nrf_modem_at_cmd_CMockExpectAnyArgsAndReturn (__LINE__ , 0 );
800+ __cmock_nrf_modem_at_cmd_CMockReturnMemThruPtr_buf (__LINE__ , (void * )cgpaddr_resp ,
801+ strlen (cgpaddr_resp ) + 1 );
802+ __cmock_nrf_modem_at_cmd_CMockIgnoreArg_len (__LINE__ );
803+ __cmock_nrf_modem_at_cmd_CMockIgnoreArg_fmt (__LINE__ );
804+ __cmock_zsock_inet_pton_ExpectAnyArgsAndReturn (1 );
805+ __cmock_nrf_inet_pton_ExpectAnyArgsAndReturn (1 );
806+ __cmock_nrf_bind_ExpectAndReturn (5 , NULL , sizeof (struct nrf_sockaddr_in ), 0 );
807+ __cmock_nrf_bind_IgnoreArg_address ();
808+ __cmock_nrf_bind_IgnoreArg_address_len ();
809+ send_at_command ("AT#XBIND=5,8080\r\n" );
810+ response = get_captured_response ();
811+ TEST_ASSERT_TRUE (strstr (response , "OK" ) != NULL );
812+ clear_captured_response ();
813+
814+ /* Mock fcntl to set non-blocking mode and listen */
815+ __cmock_nrf_fcntl_ExpectAndReturn (5 , NRF_F_SETFL , NRF_O_NONBLOCK , 0 );
816+ __cmock_nrf_listen_ExpectAndReturn (5 , 2 , 0 ); /* backlog=2 (fixed in modem) */
817+
818+ /* Execute listen command */
819+ send_at_command ("AT#XLISTEN=5\r\n" );
820+
821+ /* Verify successful listen response */
822+ response = get_captured_response ();
823+ if (strstr (response , "OK" ) == NULL ) {
824+ printf ("XLISTEN response: %s\n" , response );
825+ }
826+ TEST_ASSERT_TRUE (strstr (response , "OK" ) != NULL );
827+
828+ /* Close socket */
829+ __cmock_nrf_close_ExpectAndReturn (5 , 0 );
830+ send_at_command ("AT#XCLOSE=5\r\n" );
831+ }
832+
833+ /*
834+ * Test: AT#XLISTEN? (READ command type)
835+ * - Verifies READ command lists all listening sockets
836+ */
837+ void test_xlisten_read_command (void )
838+ {
839+ const char * response ;
840+ const char * cgpaddr_resp = "+CGPADDR: 0,\"10.0.0.1\",\"\"\r\nOK\r\n" ;
841+
842+ /* Create TCP server socket */
843+ __cmock_nrf_socket_ExpectAndReturn (NRF_AF_INET , NRF_SOCK_STREAM , NRF_IPPROTO_TCP , 3 );
844+ __cmock_nrf_setsockopt_ExpectAnyArgsAndReturn (0 );
845+ __cmock_nrf_setsockopt_ExpectAnyArgsAndReturn (0 );
846+ send_at_command ("AT#XSOCKET=1,1,1\r\n" );
847+ clear_captured_response ();
848+
849+ /* Bind to port 9000 */
850+ __cmock_nrf_modem_at_cmd_CMockExpectAnyArgsAndReturn (__LINE__ , 0 );
851+ __cmock_nrf_modem_at_cmd_CMockReturnMemThruPtr_buf (__LINE__ , (void * )cgpaddr_resp ,
852+ strlen (cgpaddr_resp ) + 1 );
853+ __cmock_nrf_modem_at_cmd_CMockIgnoreArg_len (__LINE__ );
854+ __cmock_nrf_modem_at_cmd_CMockIgnoreArg_fmt (__LINE__ );
855+ __cmock_zsock_inet_pton_ExpectAnyArgsAndReturn (1 );
856+ __cmock_nrf_inet_pton_ExpectAnyArgsAndReturn (1 );
857+ __cmock_nrf_bind_ExpectAndReturn (3 , NULL , sizeof (struct nrf_sockaddr_in ), 0 );
858+ __cmock_nrf_bind_IgnoreArg_address ();
859+ __cmock_nrf_bind_IgnoreArg_address_len ();
860+ send_at_command ("AT#XBIND=3,9000\r\n" );
861+ clear_captured_response ();
862+
863+ /* Put socket in listening mode */
864+ __cmock_nrf_fcntl_ExpectAndReturn (3 , NRF_F_SETFL , NRF_O_NONBLOCK , 0 );
865+ __cmock_nrf_listen_ExpectAndReturn (3 , 2 , 0 );
866+ send_at_command ("AT#XLISTEN=3\r\n" );
867+ clear_captured_response ();
868+
869+ /* Execute read command */
870+ send_at_command ("AT#XLISTEN?\r\n" );
871+
872+ /* Verify response contains listening socket details */
873+ response = get_captured_response ();
874+ /* Format: #XLISTEN: <handle>,<cid>,<local_port> */
875+ TEST_ASSERT_TRUE (strstr (response , "#XLISTEN: 3,0,9000" ) != NULL );
876+ TEST_ASSERT_TRUE (strstr (response , "OK" ) != NULL );
877+
878+ /* Close socket */
879+ __cmock_nrf_close_ExpectAndReturn (3 , 0 );
880+ send_at_command ("AT#XCLOSE=3\r\n" );
881+ }
882+
883+ /*
884+ * Test: AT#XLISTEN with socket that is not bound
885+ * - Should fail because socket must be bound before listen
886+ */
887+ void test_xlisten_not_bound (void )
888+ {
889+ const char * response ;
890+
891+ /* Create TCP server socket but don't bind it */
892+ __cmock_nrf_socket_ExpectAndReturn (NRF_AF_INET , NRF_SOCK_STREAM , NRF_IPPROTO_TCP , 2 );
893+ __cmock_nrf_setsockopt_ExpectAnyArgsAndReturn (0 );
894+ __cmock_nrf_setsockopt_ExpectAnyArgsAndReturn (0 );
895+ send_at_command ("AT#XSOCKET=1,1,1\r\n" );
896+ clear_captured_response ();
897+
898+ /* Try to listen without binding - should fail */
899+ send_at_command ("AT#XLISTEN=2\r\n" );
900+
901+ /* Verify error response */
902+ response = get_captured_response ();
903+ TEST_ASSERT_TRUE (strstr (response , "ERROR" ) != NULL );
904+
905+ /* Close socket */
906+ __cmock_nrf_close_ExpectAndReturn (2 , 0 );
907+ send_at_command ("AT#XCLOSE=2\r\n" );
908+ }
909+
910+ /*
911+ * Test: Socket accept operation via AT command
912+ * - Command: AT#XACCEPT=<handle>\r\n
913+ * - Tests: Accepting an incoming connection on a listening socket
914+ */
915+ void test_xaccept_operation (void )
916+ {
917+ const char * response ;
918+ const char * cgpaddr_resp = "+CGPADDR: 0,\"10.0.0.1\",\"\"\r\nOK\r\n" ;
919+
920+ /* Create TCP server socket */
921+ __cmock_nrf_socket_ExpectAndReturn (NRF_AF_INET , NRF_SOCK_STREAM , NRF_IPPROTO_TCP , 1 );
922+ __cmock_nrf_setsockopt_ExpectAnyArgsAndReturn (0 );
923+ __cmock_nrf_setsockopt_ExpectAnyArgsAndReturn (0 );
924+ send_at_command ("AT#XSOCKET=1,1,1\r\n" );
925+ clear_captured_response ();
926+
927+ /* Bind to port 7000 */
928+ __cmock_nrf_modem_at_cmd_CMockExpectAnyArgsAndReturn (__LINE__ , 0 );
929+ __cmock_nrf_modem_at_cmd_CMockReturnMemThruPtr_buf (__LINE__ , (void * )cgpaddr_resp ,
930+ strlen (cgpaddr_resp ) + 1 );
931+ __cmock_nrf_modem_at_cmd_CMockIgnoreArg_len (__LINE__ );
932+ __cmock_nrf_modem_at_cmd_CMockIgnoreArg_fmt (__LINE__ );
933+ __cmock_zsock_inet_pton_ExpectAnyArgsAndReturn (1 );
934+ __cmock_nrf_inet_pton_ExpectAnyArgsAndReturn (1 );
935+ __cmock_nrf_bind_ExpectAndReturn (1 , NULL , sizeof (struct nrf_sockaddr_in ), 0 );
936+ __cmock_nrf_bind_IgnoreArg_address ();
937+ __cmock_nrf_bind_IgnoreArg_address_len ();
938+ send_at_command ("AT#XBIND=1,7000\r\n" );
939+ clear_captured_response ();
940+
941+ /* Put socket in listening mode */
942+ __cmock_nrf_fcntl_ExpectAndReturn (1 , NRF_F_SETFL , NRF_O_NONBLOCK , 0 );
943+ __cmock_nrf_listen_ExpectAndReturn (1 , 2 , 0 );
944+ send_at_command ("AT#XLISTEN=1\r\n" );
945+ clear_captured_response ();
946+
947+ /* Mock successful accept - returns new socket fd=7 */
948+ __cmock_nrf_accept_ExpectAnyArgsAndReturn (7 );
949+ __cmock_zsock_inet_ntop_ExpectAnyArgsAndReturn ("192.168.1.100" ); /* util_get_peer_addr */
950+ __cmock_nrf_setsockopt_ExpectAnyArgsAndReturn (0 ); /* POLLCB for new socket */
951+ __cmock_nrf_setsockopt_ExpectAnyArgsAndReturn (0 ); /* POLLCB restore for listening socket */
952+
953+ /* Execute accept command */
954+ send_at_command ("AT#XACCEPT=1\r\n" );
955+
956+ /* Verify successful accept response */
957+ /* Format: #XACCEPT: <new_handle>,<cid>,"<peer_addr>",<peer_port> */
958+ response = get_captured_response ();
959+ TEST_ASSERT_TRUE (strstr (response , "#XACCEPT: 7,0," ) != NULL );
960+ TEST_ASSERT_TRUE (strstr (response , "OK" ) != NULL );
961+
962+ /* Close sockets */
963+ __cmock_nrf_close_ExpectAndReturn (7 , 0 );
964+ send_at_command ("AT#XCLOSE=7\r\n" );
965+ __cmock_nrf_close_ExpectAndReturn (1 , 0 );
966+ send_at_command ("AT#XCLOSE=1\r\n" );
967+ }
968+
969+ /*
970+ * Test: AT#XACCEPT with socket that is not listening
971+ * - Should fail because socket must be in listening mode
972+ */
973+ void test_xaccept_not_listening (void )
974+ {
975+ const char * response ;
976+
977+ /* Create TCP client socket (not server) */
978+ __cmock_nrf_socket_ExpectAndReturn (NRF_AF_INET , NRF_SOCK_STREAM , NRF_IPPROTO_TCP , 4 );
979+ __cmock_nrf_setsockopt_ExpectAnyArgsAndReturn (0 );
980+ __cmock_nrf_setsockopt_ExpectAnyArgsAndReturn (0 );
981+ send_at_command ("AT#XSOCKET=1,1,0\r\n" ); /* role=0 (client) */
982+ clear_captured_response ();
983+
984+ /* Try to accept on a client socket - should fail */
985+ send_at_command ("AT#XACCEPT=4\r\n" );
986+
987+ /* Verify error response */
988+ response = get_captured_response ();
989+ TEST_ASSERT_TRUE (strstr (response , "ERROR" ) != NULL );
990+
991+ /* Close socket */
992+ __cmock_nrf_close_ExpectAndReturn (4 , 0 );
993+ send_at_command ("AT#XCLOSE=4\r\n" );
994+ }
995+
779996/*
780997 * Test: Send data via AT#XSEND with unformatted string
781998 * - Command: AT#XSEND=<handle>,<mode>,<flags>,"<data>"\r\n
0 commit comments