Files @ 665aa326769e
Branch filter:

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

665aa326769e 4.1 KiB application/rls-services+xml Show Annotation Show as Raw Download as Raw
mh
add 'print' fn for testing, first test for new runtime
use std::sync::Arc;

use super::runtime::*;
use crate::ProtocolDescription;
use crate::protocol::eval::*;

#[test]
fn test_single_message() {
    // Simple test were we have a `putter` component, which will simply send a
    // single message (a boolean), and a `getter` component, which will receive
    // that message.
    // We will write this behaviour in the various ways that the language
    // currently allows. We will cheat a bit by peeking into the runtime to make
    // sure that the getter actually received the message.
    // TODO: Expose ports to a "native application"

    fn check_store_bool(value: &Value, expected: bool) {
        if let Value::Bool(value) = value {
            assert_eq!(*value, expected);
        } else {
            assert!(false);
        }
    }
    fn run_putter_getter(code: &[u8]) {
        // Compile code
        let pd = ProtocolDescription::parse(code)
            .expect("code successfully compiles");
        let pd = Arc::new(pd);

        // Construct runtime and the appropriate ports and connectors
        let mut rt = Runtime::new(pd);
        let (put_port, get_port) = rt.add_channel();

        let mut put_args = ValueGroup::new_stack(vec![
            put_port,
        ]);
        rt.add_component("", "putter", put_args)
            .expect("'putter' component created");

        let mut get_args = ValueGroup::new_stack(vec![
            get_port,
        ]);
        rt.add_component("", "getter", get_args)
            .expect("'getter' component created");

        // Run until completion
        rt.run();

        // Check for success (the 'received' and 'did_receive" flags)
        let getter_component = rt.connectors.get(&1).unwrap();
        let branch = &getter_component.branches[0];
        assert_eq!(branch.branch_state, BranchState::Finished);

        // Note: with the stack structure of the store, the first entry is the
        // "previous stack pos" and the second one is the input port passed to
        // the procedure. Hence the third/fourth entries are the boolean
        // variables on the stack.
        check_store_bool(&branch.code_state.prompt.store.stack[2], true);
        check_store_bool(&branch.code_state.prompt.store.stack[3], true);
    }

    // Without `fires()`, just a single valid behaviour
    run_putter_getter(
        b"primitive putter(out<bool> put_here) {
            synchronous {
                put(put_here, true);
            }
        }

        primitive getter(in<bool> get_here) {
            bool received = false;
            bool did_receive = false;

            synchronous {
                received = get(get_here);
                if (received) {
                    print(\"value was 'true'\");
                } else {
                    print(\"value was 'false'\");
                }
                did_receive = true;
            }
        }");

    // With `fires()`, but eliminating on the putter side
    run_putter_getter(
        b"primitive putter(out<bool> put_here) {
            synchronous {
                if (!fires(put_here)) {
                    assert(false);
                } else {
                    put(put_here, true);
                }
            }
        }

        primitive getter(in<bool> get_here) {
            bool received = false; bool did_receive = false;
            synchronous {
                if (fires(get_here)) {
                    received = get(get_here);
                    did_receive = true;
                }
            }
        }");

    // With `fires()`, but eliminating on the getter side
    run_putter_getter(
        b"primitive putter(out<bool> put_here) {
            synchronous {
                if (fires(put_here)) {
                    put(put_here, true);
                }
            }
        }

        primitive getter(in<bool> get_here) {
            bool received = false; bool did_receive = false;
            synchronous {
                if (fires(get_here)) {
                    received = get(get_here);
                    did_receive = true;
                } else {
                    assert(false);
                }
            }
        }"
    );
}