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 put_here) { synchronous { put(put_here, true); } } primitive getter(in 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 put_here) { synchronous { if (!fires(put_here)) { assert(false); } else { put(put_here, true); } } } primitive getter(in 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 put_here) { synchronous { if (fires(put_here)) { put(put_here, true); } } } primitive getter(in get_here) { bool received = false; bool did_receive = false; synchronous { if (fires(get_here)) { received = get(get_here); did_receive = true; } else { assert(false); } } }" ); }