diff --git a/src/runtime2/tests/mod.rs b/src/runtime2/tests/mod.rs index b795bc4b6387425f1b393d2029784e0561618d45..fb47364e1adef4283a1a5f4961be67cd7bead285 100644 --- a/src/runtime2/tests/mod.rs +++ b/src/runtime2/tests/mod.rs @@ -247,3 +247,133 @@ fn test_random_u32_temporary_thingo() { let rt = Runtime::new(1, true, pd).unwrap(); create_component(&rt, "", "constructor", no_args()); } + +#[test] +fn test_tcp_socket_http_request() { + let _pd = ProtocolDescription::parse(b" + import std.internet::*; + + primitive requester(out cmd_tx, in data_rx) { + print(\"*** TCPSocket: Sending request\"); + sync { + put(cmd_tx, Cmd::Send(b\"GET / HTTP/1.1\\r\\n\\r\\n\")); + } + + print(\"*** TCPSocket: Receiving response\"); + auto buffer = {}; + auto done_receiving = false; + sync while (!done_receiving) { + put(cmd_tx, Cmd::Receive); + auto data = get(data_rx); + buffer @= data; + + // Completely crap detection of end-of-document. But here we go, we + // try to detect the trailing . Proper way would be to parse + // for 'content-length' or 'content-encoding' + s32 index = 0; + s32 partial_length = cast(length(data) - 7); + while (index < partial_length) { + // No string conversion yet, so check byte buffer one byte at + // a time. + auto c1 = data[index]; + if (c1 == cast('<')) { + auto c2 = data[index + 1]; + auto c3 = data[index + 2]; + auto c4 = data[index + 3]; + auto c5 = data[index + 4]; + auto c6 = data[index + 5]; + auto c7 = data[index + 6]; + if ( // i.e. if (data[index..] == '' + c2 == cast('/') && c3 == cast('h') && c4 == cast('t') && + c5 == cast('m') && c6 == cast('l') && c7 == cast('>') + ) { + print(\"*** TCPSocket: Detected \"); + put(cmd_tx, Cmd::Finish); + done_receiving = true; + } + } + index += 1; + } + } + + print(\"*** TCPSocket: Requesting shutdown\"); + sync { + put(cmd_tx, Cmd::Shutdown); + } + } + + composite main() { + channel cmd_tx -> cmd_rx; + channel data_tx -> data_rx; + new tcp_client({142, 250, 179, 163}, 80, cmd_rx, data_tx); // port 80 of google + new requester(cmd_tx, data_rx); + } + ").expect("compilation"); + + // This test is disabled because it performs a HTTP request to google. + // let rt = Runtime::new(1, true, pd).unwrap(); + // create_component(&rt, "", "main", no_args()); +} + +#[test] +fn test_sending_receiving_union() { + let pd = ProtocolDescription::parse(b" + union Cmd { + Set(u8[]), + Get, + Shutdown, + } + + primitive database(in rx, out tx) { + auto stored = {}; + auto done = false; + while (!done) { + sync { + auto command = get(rx); + if (let Cmd::Set(bytes) = command) { + print(\"database: storing value\"); + stored = bytes; + } else if (let Cmd::Get = command) { + print(\"database: returning value\"); + put(tx, stored); + } else if (let Cmd::Shutdown = command) { + print(\"database: shutting down\"); + done = true; + } else while (true) print(\"impossible\"); // no other case possible + } + } + } + + primitive client(out tx, in rx, u32 num_rounds) { + auto round = 0; + while (round < num_rounds) { + auto set_value = b\"hello there\"; + print(\"client: putting a value\"); + sync put(tx, Cmd::Set(set_value)); + + auto retrieved = {}; + print(\"client: retrieving what was sent\"); + sync { + put(tx, Cmd::Get); + retrieved = get(rx); + } + + if (set_value != retrieved) while (true) print(\"wrong!\"); + + round += 1; + } + + sync put(tx, Cmd::Shutdown); + } + + composite main() { + auto num_rounds = 5; + channel cmd_tx -> cmd_rx; + channel data_tx -> data_rx; + new database(cmd_rx, data_tx); + new client(cmd_tx, data_rx, num_rounds); + } + ").expect("compilation"); + let rt = Runtime::new(1, false, pd).unwrap(); + create_component(&rt, "", "main", no_args()); +} \ No newline at end of file