Skip to content

Commit 6daeec8

Browse files
committed
Add a simple test for TCP sockets
Add two test programs, sockets-client.c and sockets-server.c, that are run by the test driver as separate executables (since without threads, this can't be written as a single test).
1 parent 7c616cb commit 6daeec8

File tree

3 files changed

+167
-0
lines changed

3 files changed

+167
-0
lines changed

test/scripts/run-test.sh

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,40 @@ ENGINE="${ENGINE:-wasmtime}"
1212
[ -n "$WASM" ] || (echo "missing WASM variable" && exit 1)
1313
[ -n "$DIR" ] || (echo "missing DIR variable" && exit 1)
1414

15+
# Run the client/server sockets test, which requires a client and server
16+
# running in separate processes
17+
run_sockets_test() {
18+
# Args are the same for client and server
19+
cd $DIR
20+
server_wasm=`echo $WASM | sed -e 's/client/server/g'`
21+
echo "$ENV $ENGINE $RUN $server_wasm $ARGS" > server_cmd.sh
22+
chmod +x server_cmd.sh
23+
# Start the server
24+
./server_cmd.sh &> server_output.log &
25+
PID=$!
26+
[ $? -ne -1 ] || (echo "Failed to start server $server_wasm" && exit 1)
27+
echo "$ENV $ENGINE $RUN $WASM $ARGS" > cmd.sh
28+
chmod +x cmd.sh
29+
# Allow time for the server to start
30+
sleep 1
31+
# Start the client
32+
./cmd.sh &> output.log
33+
test_result=$?
34+
# Server normally exits on its own, but kill it in case the test failed
35+
if [ ps -p $PID > /dev/null 2>&1 ]; then
36+
kill -9 $PID
37+
fi
38+
[ $test_result -eq 0 ] || echo "Test failed" >> output.log
39+
}
40+
41+
testname=$(basename $WASM)
42+
if [ $testname == "sockets-server.component.wasm" ]; then
43+
exit 0
44+
fi
45+
if [ $testname == "sockets-client.component.wasm" ]; then
46+
run_sockets_test
47+
exit $?
48+
fi
1549
cd $DIR
1650
mkdir -p fs
1751
echo "$ENV $ENGINE $RUN $WASM $ARGS" > cmd.sh

test/src/misc/sockets-client.c

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
//! filter.py(TARGET_TRIPLE): wasm32-wasip2
2+
//! add-flags.py(RUN): --wasi=inherit-network=y
3+
#include <errno.h>
4+
#include <fcntl.h>
5+
#include <stdio.h>
6+
#include <stdlib.h>
7+
#include <string.h>
8+
#include <unistd.h>
9+
#include <netdb.h>
10+
#include <sys/socket.h>
11+
#include <netinet/in.h>
12+
#include <arpa/inet.h>
13+
#include "test.h"
14+
15+
#define TEST(c) do { \
16+
errno = 0; \
17+
if (!(c)) \
18+
t_error("%s failed (errno = %d)\n", #c, errno); \
19+
} while(0)
20+
21+
int BUFSIZE = 256;
22+
23+
// See sockets-server.c -- must be running already as a separate executable
24+
void test_tcp_client() {
25+
// Prepare server socket
26+
int server_port = 4001;
27+
28+
// Prepare client socket
29+
// Use blocking sockets
30+
int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
31+
TEST(socket_fd != -1);
32+
33+
// Prepare sockaddr_in for client
34+
struct sockaddr_in sockaddr_in;
35+
sockaddr_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
36+
sockaddr_in.sin_family = AF_INET;
37+
sockaddr_in.sin_port = htons(server_port);
38+
39+
// Connect from client
40+
char message[] = "There's gonna be a party when the wolf comes home";
41+
int len = strlen(message);
42+
char client_buffer[BUFSIZE];
43+
44+
TEST(connect(socket_fd, (struct sockaddr*)&sockaddr_in, sizeof(sockaddr_in)) != -1);
45+
46+
// Client writes a message to server
47+
TEST(send(socket_fd, message, len, 0) == len);
48+
49+
// Client reads from server
50+
int32_t bytes_received = recv(socket_fd, client_buffer, len, 0);
51+
TEST(bytes_received == len);
52+
53+
// Message received should be the same as message sent
54+
TEST(strcmp(message, client_buffer) == 0);
55+
56+
// Shut down client
57+
close(socket_fd);
58+
}
59+
60+
int main(void)
61+
{
62+
test_tcp_client();
63+
64+
return t_status;
65+
}

test/src/misc/sockets-server.c

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
//! filter.py(TARGET_TRIPLE): wasm32-wasip2
2+
//! add-flags.py(RUN): --wasi=inherit-network=y
3+
#include <errno.h>
4+
#include <fcntl.h>
5+
#include <stdbool.h>
6+
#include <stdio.h>
7+
#include <stdlib.h>
8+
#include <string.h>
9+
#include <unistd.h>
10+
#include <netdb.h>
11+
#include <sys/socket.h>
12+
#include <netinet/in.h>
13+
#include <arpa/inet.h>
14+
#include "test.h"
15+
16+
#define TEST(c) do { \
17+
errno = 0; \
18+
if (!(c)) \
19+
t_error("%s failed (errno = %d)\n", #c, errno); \
20+
} while(0)
21+
22+
int BUFSIZE = 256;
23+
24+
void run_tcp_server() {
25+
// Prepare server socket
26+
int server_port = 4001;
27+
// Use blocking sockets
28+
int server_socket_fd = socket(AF_INET, SOCK_STREAM, 0);
29+
30+
// Bind server to socket
31+
struct sockaddr_in server_address;
32+
server_address.sin_family = AF_INET;
33+
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
34+
server_address.sin_port = htons(server_port);
35+
TEST(bind(server_socket_fd, (struct sockaddr*)&server_address, sizeof(server_address)) != -1);
36+
37+
// Listen on socket
38+
char buffer[BUFSIZE];
39+
socklen_t client_len = sizeof(struct sockaddr_in);
40+
int client_socket_fd;
41+
struct sockaddr_in client_address;
42+
int32_t bytes_read = 0, total_bytes_read = 0;
43+
TEST(listen(server_socket_fd, 1) != -1);
44+
45+
// Server accepts connection
46+
client_socket_fd = accept(server_socket_fd, (struct sockaddr*)&client_address, &client_len);
47+
TEST(client_socket_fd != -1);
48+
49+
// Server waits for input and echoes message back to client
50+
// The server shuts down after the client closes the connection
51+
while ((bytes_read = recv(client_socket_fd, buffer, BUFSIZE, 0)) > 0) {
52+
total_bytes_read += bytes_read;
53+
// Echo back the data received from the client
54+
send(client_socket_fd, buffer, bytes_read, 0);
55+
}
56+
57+
TEST(total_bytes_read > 0);
58+
59+
close(client_socket_fd);
60+
close(server_socket_fd);
61+
}
62+
63+
int main()
64+
{
65+
run_tcp_server();
66+
67+
return t_status;
68+
}

0 commit comments

Comments
 (0)