diff --git a/src/runtime2/tests/internet.rs b/src/runtime2/tests/internet.rs index 246726d62cd982b04b85ee5f814e15aff5203926..4859ca49ef963f54db2e9dbf0140f0707c4fe145 100644 --- a/src/runtime2/tests/internet.rs +++ b/src/runtime2/tests/internet.rs @@ -71,4 +71,108 @@ fn test_stdlib_file() { new fake_client(connection); } ", "constructor", no_args()); +} + +#[test] +fn test_tcp_listener_and_client() { + compile_and_create_component(" + import std.internet::*; + + func listen_port() -> u16 { + return 2393; + } + + comp server(u32 num_connections) { + // Start tcp listener + channel listen_cmd_tx -> listen_cmd_rx; + channel listen_conn_tx -> listen_conn_rx; + new tcp_listener({}, listen_port(), listen_cmd_rx, listen_conn_tx); + + // Fake channels such that we can create a dummy connection variable + channel client_cmd_tx -> unused_client_cmd_rx; + channel unused_client_data_tx -> client_data_rx; + auto new_connection = TcpConnection{ + tx: client_cmd_tx, + rx: client_data_rx, + }; + + auto connection_counter = 0; + while (connection_counter < num_connections) { + // Wait until we get a connection + print(\"server: waiting for an accepted connection\"); + sync { + put(listen_cmd_tx, ListenerCmd::Accept); + new_connection = get(listen_conn_rx); + } + + // We have a new connection, spawn an 'echoer' for it + print(\"server: spawning an echo'ing component\"); + new echo_machine(new_connection); + connection_counter += 1; + } + + // Shut down the listener + print(\"server: shutting down listener\"); + } + + // Waits for a single TCP byte (to simplify potentially having to + // concatenate requests) and echos it + comp echo_machine(TcpConnection conn) { + auto data_to_echo = {}; + + // Wait for a message + sync { + print(\"echo: receiving data\"); + put(conn.tx, ClientCmd::Receive); + data_to_echo = get(conn.rx); + put(conn.tx, ClientCmd::Finish); + } + + // Echo the message + print(\"echo: sending back data\"); + sync put(conn.tx, ClientCmd::Send(data_to_echo)); + + // Ask the tcp connection to shut down + print(\"echo: shutting down\"); + sync put(conn.tx, ClientCmd::Shutdown); + } + + comp echo_requester(u8 byte_to_send) { + channel cmd_tx -> cmd_rx; + channel data_tx -> data_rx; + new tcp_client({127, 0, 0, 1}, listen_port(), cmd_rx, data_tx); + + // Send the message + print(\"requester: sending bytes\"); + sync put(cmd_tx, ClientCmd::Send({ byte_to_send })); + + // Receive the echo'd byte + auto received_byte = byte_to_send + 1; + sync { + print(\"requester: receiving echo response\"); + put(cmd_tx, ClientCmd::Receive); + received_byte = get(data_rx)[0]; + put(cmd_tx, ClientCmd::Finish); + } + + // Silly check, as always + while (byte_to_send != received_byte) { + print(\"requester: Oh no! The echo is an otherworldly distorter\"); + } + + // Shut down the TCP connection + print(\"requester: shutting down TCP component\"); + sync put(cmd_tx, ClientCmd::Shutdown); + } + + comp constructor() { + auto num_connections = 1; + new server(num_connections); + + auto connection_index = 0; + while (connection_index < num_connections) { + new echo_requester(cast(connection_index)); + } + } + ", "constructor", no_args()); } \ No newline at end of file