diff --git a/test/scripts/run-test.sh b/test/scripts/run-test.sh index 87961418..267dd0d3 100755 --- a/test/scripts/run-test.sh +++ b/test/scripts/run-test.sh @@ -12,6 +12,40 @@ ENGINE="${ENGINE:-wasmtime}" [ -n "$WASM" ] || (echo "missing WASM variable" && exit 1) [ -n "$DIR" ] || (echo "missing DIR variable" && exit 1) +# Run the client/server sockets test, which requires a client and server +# running in separate processes +run_sockets_test() { + # Args are the same for client and server + cd $DIR + server_wasm=`echo $WASM | sed -e 's/client/server/g'` + echo "$ENV $ENGINE $RUN $server_wasm $ARGS" > server_cmd.sh + chmod +x server_cmd.sh + # Start the server + ./server_cmd.sh &> server_output.log & + PID=$! + [ $? -ne -1 ] || (echo "Failed to start server $server_wasm" && exit 1) + echo "$ENV $ENGINE $RUN $WASM $ARGS" > cmd.sh + chmod +x cmd.sh + # Allow time for the server to start + sleep 1 + # Start the client + ./cmd.sh &> output.log + test_result=$? + # Server normally exits on its own, but kill it in case the test failed + if [ ps -p $PID > /dev/null 2>&1 ]; then + kill -9 $PID + fi + [ $test_result -eq 0 ] || echo "Test failed" >> output.log +} + +testname=$(basename $WASM) +if [ $testname == "sockets-server.component.wasm" ]; then + exit 0 +fi +if [ $testname == "sockets-client.component.wasm" ]; then + run_sockets_test + exit $? +fi cd $DIR mkdir -p fs echo "$ENV $ENGINE $RUN $WASM $ARGS" > cmd.sh diff --git a/test/src/misc/sockets-client.c b/test/src/misc/sockets-client.c new file mode 100644 index 00000000..2b0368c1 --- /dev/null +++ b/test/src/misc/sockets-client.c @@ -0,0 +1,65 @@ +//! filter.py(TARGET_TRIPLE): wasm32-wasip2 +//! add-flags.py(RUN): --wasi=inherit-network=y +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "test.h" + +#define TEST(c) do { \ + errno = 0; \ + if (!(c)) \ + t_error("%s failed (errno = %d)\n", #c, errno); \ +} while(0) + +int BUFSIZE = 256; + +// See sockets-server.c -- must be running already as a separate executable +void test_tcp_client() { + // Prepare server socket + int server_port = 4001; + + // Prepare client socket + // Use blocking sockets + int socket_fd = socket(AF_INET, SOCK_STREAM, 0); + TEST(socket_fd != -1); + + // Prepare sockaddr_in for client + struct sockaddr_in sockaddr_in; + sockaddr_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + sockaddr_in.sin_family = AF_INET; + sockaddr_in.sin_port = htons(server_port); + + // Connect from client + char message[] = "There's gonna be a party when the wolf comes home"; + int len = strlen(message); + char client_buffer[BUFSIZE]; + + TEST(connect(socket_fd, (struct sockaddr*)&sockaddr_in, sizeof(sockaddr_in)) != -1); + + // Client writes a message to server + TEST(send(socket_fd, message, len, 0) == len); + + // Client reads from server + int32_t bytes_received = recv(socket_fd, client_buffer, len, 0); + TEST(bytes_received == len); + + // Message received should be the same as message sent + TEST(strcmp(message, client_buffer) == 0); + + // Shut down client + close(socket_fd); +} + +int main(void) +{ + test_tcp_client(); + + return t_status; +} diff --git a/test/src/misc/sockets-server.c b/test/src/misc/sockets-server.c new file mode 100644 index 00000000..fcbce28d --- /dev/null +++ b/test/src/misc/sockets-server.c @@ -0,0 +1,68 @@ +//! filter.py(TARGET_TRIPLE): wasm32-wasip2 +//! add-flags.py(RUN): --wasi=inherit-network=y +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "test.h" + +#define TEST(c) do { \ + errno = 0; \ + if (!(c)) \ + t_error("%s failed (errno = %d)\n", #c, errno); \ +} while(0) + +int BUFSIZE = 256; + +void run_tcp_server() { + // Prepare server socket + int server_port = 4001; + // Use blocking sockets + int server_socket_fd = socket(AF_INET, SOCK_STREAM, 0); + + // Bind server to socket + struct sockaddr_in server_address; + server_address.sin_family = AF_INET; + server_address.sin_addr.s_addr = htonl(INADDR_ANY); + server_address.sin_port = htons(server_port); + TEST(bind(server_socket_fd, (struct sockaddr*)&server_address, sizeof(server_address)) != -1); + + // Listen on socket + char buffer[BUFSIZE]; + socklen_t client_len = sizeof(struct sockaddr_in); + int client_socket_fd; + struct sockaddr_in client_address; + int32_t bytes_read = 0, total_bytes_read = 0; + TEST(listen(server_socket_fd, 1) != -1); + + // Server accepts connection + client_socket_fd = accept(server_socket_fd, (struct sockaddr*)&client_address, &client_len); + TEST(client_socket_fd != -1); + + // Server waits for input and echoes message back to client + // The server shuts down after the client closes the connection + while ((bytes_read = recv(client_socket_fd, buffer, BUFSIZE, 0)) > 0) { + total_bytes_read += bytes_read; + // Echo back the data received from the client + send(client_socket_fd, buffer, bytes_read, 0); + } + + TEST(total_bytes_read > 0); + + close(client_socket_fd); + close(server_socket_fd); +} + +int main() +{ + run_tcp_server(); + + return t_status; +}