Files @ b7d434ab8020
Branch filter:

Location: CSY/reowolf/src/runtime2/tests/mod.rs - annotation

b7d434ab8020 8.9 KiB application/rls-services+xml Show Source Show as Raw Download as Raw
MH
Remove distinction between primitive/composite components
53d3950d9b6b
53d3950d9b6b
53d3950d9b6b
bf4c0ee5ba65
bf4c0ee5ba65
38c129959044
1f78496722d1
38c129959044
1cc3bd69b119
1f78496722d1
1f78496722d1
38c129959044
1f78496722d1
1f78496722d1
1f78496722d1
1f78496722d1
1f78496722d1
1f78496722d1
1f78496722d1
1f78496722d1
1f78496722d1
1f78496722d1
bf4c0ee5ba65
bf4c0ee5ba65
bf4c0ee5ba65
38c129959044
bf4c0ee5ba65
113e4349a706
38c129959044
bf4c0ee5ba65
bf4c0ee5ba65
bf4c0ee5ba65
1f78496722d1
53d3950d9b6b
53d3950d9b6b
53d3950d9b6b
53d3950d9b6b
53d3950d9b6b
53d3950d9b6b
53d3950d9b6b
53d3950d9b6b
53d3950d9b6b
1f78496722d1
53d3950d9b6b
637115283740
bf4c0ee5ba65
0781cf1b7abf
0781cf1b7abf
0781cf1b7abf
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
113e4349a706
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
1f78496722d1
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
1f78496722d1
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
637115283740
1f78496722d1
637115283740
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
1f78496722d1
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
1f78496722d1
113e4349a706
53d3950d9b6b
use crate::protocol::*;
use crate::protocol::eval::*;
use crate::runtime2::runtime::*;
use crate::runtime2::component::{CompCtx, CompPDL};

mod messaging;
mod error_handling;
mod transfer_ports;
mod internet;

const LOG_LEVEL: LogLevel = LogLevel::Debug;
const NUM_THREADS: u32 = 1;

pub(crate) fn compile_and_create_component(source: &str, routine_name: &str, args: ValueGroup) {
    let protocol = ProtocolDescription::parse(source.as_bytes())
        .expect("successful compilation");
    let runtime = Runtime::new(NUM_THREADS, LOG_LEVEL, protocol)
        .expect("successful runtime startup");
    create_component(&runtime, "", routine_name, args);
}

pub(crate) fn create_component(rt: &Runtime, module_name: &str, routine_name: &str, args: ValueGroup) {
    let prompt = rt.inner.protocol.new_component(
        module_name.as_bytes(), routine_name.as_bytes(), args
    ).expect("create prompt");
    let reserved = rt.inner.start_create_component();
    let ctx = CompCtx::new(&reserved);
    let component = Box::new(CompPDL::new(prompt, 0));
    let (key, _) = rt.inner.finish_create_component(reserved, component, ctx, false);
    rt.inner.enqueue_work(key);
}

pub(crate) fn no_args() -> ValueGroup { ValueGroup::new_stack(Vec::new()) }

#[test]
fn test_component_creation() {
    let pd = ProtocolDescription::parse(b"
    primitive nothing_at_all() {
        s32 a = 5;
        auto b = 5 + a;
    }
    ").expect("compilation");
    let rt = Runtime::new(1, LOG_LEVEL, pd).unwrap();

    for _i in 0..20 {
        create_component(&rt, "", "nothing_at_all", no_args());
    }
}

#[test]
fn test_simple_select() {
    let pd = ProtocolDescription::parse(b"
    func infinite_assert<T>(T val, T expected) -> () {
        while (val != expected) { print(\"nope!\"); }
        return ();
    }

    primitive receiver(in<u32> in_a, in<u32> in_b, u32 num_sends) {
        auto num_from_a = 0;
        auto num_from_b = 0;
        while (num_from_a + num_from_b < 2 * num_sends) {
            sync select {
                auto v = get(in_a) -> {
                    print(\"got something from A\");
                    auto _ = infinite_assert(v, num_from_a);
                    num_from_a += 1;
                }
                auto v = get(in_b) -> {
                    print(\"got something from B\");
                    auto _ = infinite_assert(v, num_from_b);
                    num_from_b += 1;
                }
            }
        }
    }

    primitive sender(out<u32> tx, u32 num_sends) {
        auto index = 0;
        while (index < num_sends) {
            sync {
                put(tx, index);
                index += 1;
            }
        }
    }

    composite constructor() {
        auto num_sends = 1;
        channel tx_a -> rx_a;
        channel tx_b -> rx_b;
        new sender(tx_a, num_sends);
        new receiver(rx_a, rx_b, num_sends);
        new sender(tx_b, num_sends);
    }
    ").expect("compilation");
    let rt = Runtime::new(3, LOG_LEVEL, pd).unwrap();
    create_component(&rt, "", "constructor", no_args());
}

#[test]
fn test_unguarded_select() {
    let pd = ProtocolDescription::parse(b"
    primitive constructor_outside_select() {
        u32 index = 0;
        while (index < 5) {
            sync select { auto v = () -> print(\"hello\"); }
            index += 1;
        }
    }

    primitive constructor_inside_select() {
        u32 index = 0;
        while (index < 5) {
            sync select { auto v = () -> index += 1; }
        }
    }
    ").expect("compilation");
    let rt = Runtime::new(3, LOG_LEVEL, pd).unwrap();
    create_component(&rt, "", "constructor_outside_select", no_args());
    create_component(&rt, "", "constructor_inside_select", no_args());
}

#[test]
fn test_empty_select() {
    let pd = ProtocolDescription::parse(b"
    primitive constructor() {
        u32 index = 0;
        while (index < 5) {
            sync select {}
            index += 1;
        }
    }
    ").expect("compilation");
    let rt = Runtime::new(3, LOG_LEVEL, pd).unwrap();
    create_component(&rt, "", "constructor", no_args());
}

#[test]
fn test_random_u32_temporary_thingo() {
    let pd = ProtocolDescription::parse(b"
    import std.random::random_u32;

    primitive random_taker(in<u32> generator, u32 num_values) {
        auto i = 0;
        while (i < num_values) {
            sync {
                auto a = get(generator);
            }
            i += 1;
        }
    }

    composite constructor() {
        channel tx -> rx;
        auto num_values = 25;
        new random_u32(tx, 1, 100, num_values);
        new random_taker(rx, num_values);
    }
    ").expect("compilation");
    let rt = Runtime::new(1, LOG_LEVEL, 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> cmd_tx, in<u8[]> 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 </html>. 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..] == '</html>'
                        c2 == cast('/') && c3 == cast('h') && c4 == cast('t') &&
                        c5 == cast('m') && c6 == cast('l') && c7 == cast('>')
                    ) {
                        print(\"*** TCPSocket: Detected </html>\");
                        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<Cmd> rx, out<u8[]> 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<Cmd> tx, in<u8[]> 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, LOG_LEVEL, pd).unwrap();
    create_component(&rt, "", "main", no_args());
}