diff --git a/src/runtime/tests/api_component.rs b/src/runtime/tests/api_component.rs new file mode 100644 index 0000000000000000000000000000000000000000..67271d2986bb610f91a18425edff20de76b0b0f2 --- /dev/null +++ b/src/runtime/tests/api_component.rs @@ -0,0 +1,158 @@ +// Testing the api component. +// +// These tests explicitly do not use the "NUM_INSTANCES" constant because we're +// doing some communication with the native component. Hence only expect one + +use super::*; + +#[test] +fn test_put_and_get() { + const CODE: &'static str = " + primitive handler(in request, out response, u32 loops) { + u32 index = 0; + while (index < loops) { + sync { + auto value = get(request); + put(response, value * 2); + } + index += 1; + } + } + "; + + let pd = ProtocolDescription::parse(CODE.as_bytes()).unwrap(); + let rt = Runtime::new(NUM_THREADS, pd); + let mut api = rt.create_interface(); + + let req_chan = api.create_channel().unwrap(); + let resp_chan = api.create_channel().unwrap(); + + api.create_connector("", "handler", ValueGroup::new_stack(vec![ + Value::Input(PortId::new(req_chan.getter_id.index)), + Value::Output(PortId::new(resp_chan.putter_id.index)), + Value::UInt32(NUM_LOOPS), + ])).unwrap(); + + for loop_idx in 0..NUM_LOOPS { + api.perform_sync_round(vec![ + ApplicationSyncAction::Put(req_chan.putter_id, ValueGroup::new_stack(vec![Value::UInt32(loop_idx)])), + ApplicationSyncAction::Get(resp_chan.getter_id) + ]).expect("start sync round"); + + let result = api.wait().expect("finish sync round"); + assert!(result.len() == 1); + if let Value::UInt32(gotten) = result[0].values[0] { + assert_eq!(gotten, loop_idx * 2); + } else { + assert!(false); + } + } +} + +#[test] +fn test_getting_from_component() { + const CODE: &'static str =" + primitive loop_sender(out numbers, u32 cur, u32 last) { + while (cur < last) { + sync { + put(numbers, cur); + cur += 1; + } + } + }"; + + let pd = ProtocolDescription::parse(CODE.as_bytes()).unwrap(); + let rt = Runtime::new(NUM_THREADS, pd); + let mut api = rt.create_interface(); + + let channel = api.create_channel().unwrap(); + api.create_connector("", "loop_sender", ValueGroup::new_stack(vec![ + Value::Output(PortId::new(channel.putter_id.index)), + Value::UInt32(1337), + Value::UInt32(1337 + NUM_LOOPS) + ])).unwrap(); + + for loop_idx in 0..NUM_LOOPS { + api.perform_sync_round(vec![ + ApplicationSyncAction::Get(channel.getter_id), + ]).expect("start sync round"); + + let result = api.wait().expect("finish sync round"); + + assert!(result.len() == 1 && result[0].values.len() == 1); + if let Value::UInt32(gotten) = result[0].values[0] { + assert_eq!(gotten, 1337 + loop_idx); + } else { + assert!(false); + } + } +} + +#[test] +fn test_putting_to_component() { + const CODE: &'static str = " + primitive loop_receiver(in numbers, u32 cur, u32 last) { + while (cur < last) { + sync { + auto number = get(numbers); + assert(number == cur); + cur += 1; + } + } + } + "; + + let pd = ProtocolDescription::parse(CODE.as_bytes()).unwrap(); + let rt = Runtime::new(NUM_THREADS, pd); + let mut api = rt.create_interface(); + + let channel = api.create_channel().unwrap(); + api.create_connector("", "loop_receiver", ValueGroup::new_stack(vec![ + Value::Input(PortId::new(channel.getter_id.index)), + Value::UInt32(42), + Value::UInt32(42 + NUM_LOOPS) + ])).unwrap(); + + for loop_idx in 0..NUM_LOOPS { + api.perform_sync_round(vec![ + ApplicationSyncAction::Put(channel.putter_id, ValueGroup::new_stack(vec![Value::UInt32(42 + loop_idx)])), + ]).expect("start sync round"); + + // Note: if we finish a round, then it must have succeeded :) + api.wait().expect("finish sync round"); + } +} + +#[test] +fn test_doing_nothing() { + const CODE: &'static str = " + primitive getter(in input, u32 num_loops) { + u32 index = 0; + while (index < num_loops) { + sync {} + sync { auto res = get(input); assert(res); } + index += 1; + } + } + "; + + let pd = ProtocolDescription::parse(CODE.as_bytes()).unwrap(); + let rt = Runtime::new(NUM_THREADS, pd); + let mut api = rt.create_interface(); + + let channel = api.create_channel().unwrap(); + api.create_connector("", "getter", ValueGroup::new_stack(vec![ + Value::Input(PortId::new(channel.getter_id.index)), + Value::UInt32(NUM_LOOPS), + ])).unwrap(); + + for _ in 0..NUM_LOOPS { + api.perform_sync_round(vec![]).expect("start silent sync round"); + api.wait().expect("finish silent sync round"); + api.perform_sync_round(vec![ + ApplicationSyncAction::Put(channel.putter_id, ValueGroup::new_stack(vec![Value::Bool(true)])) + ]).expect("start firing sync round"); + let res = api.wait().expect("finish firing sync round"); + assert!(res.is_empty()); + } +} \ No newline at end of file