// sync_failure.rs
//
// Various tests to ensure that failing components fail in a consistent way.
use super::*;
#[test]
fn test_local_sync_failure() {
// If the component exits cleanly, then the runtime exits cleanly, and the
// test will finish
const CODE: &'static str = "
primitive immediate_failure_inside_sync() {
u32[] only_allows_index_0 = { 1 };
while (true) sync { // note the infinite loop
auto value = only_allows_index_0[1];
}
}
primitive immediate_failure_outside_sync() {
u32[] only_allows_index_0 = { 1 };
auto never_gonna_get = only_allows_index_0[1];
while (true) sync {}
}
";
// let thing = TestTimer::new("local_sync_failure");
run_test_in_runtime(CODE, |api| {
api.create_connector("", "immediate_failure_outside_sync", ValueGroup::new_stack(Vec::new()))
.expect("create component");
api.create_connector("", "immediate_failure_inside_sync", ValueGroup::new_stack(Vec::new()))
.expect("create component");
})
}
#[test]
fn test_shared_sync_failure() {
// Same as above. One of the components should fail, the other should follow
// suit because it cannot complete a sync round. We intentionally have an
// infinite loop in the while condition because we need at least two loops
// for the last error to get picked up.
const CODE: &'static str = "
enum Location { BeforeSync, AfterPut, AfterGet, AfterSync, Never }
primitive failing_at_location(in<bool> input, out<bool> output, Location loc) {
u32[] failure_array = {};
while (true) {
if (loc == Location::BeforeSync) failure_array[0];
sync {
put(output, true);
if (loc == Location::AfterPut) failure_array[0];
auto received = get(input);
assert(received);
if (loc == Location::AfterGet) failure_array[0];
}
if (loc == Location::AfterSync) failure_array[0];
}
}
composite constructor(Location loc) {
channel output_a -> input_a;
channel output_b -> input_b;
new failing_at_location(input_a, output_b, Location::Never);
new failing_at_location(input_b, output_a, loc);
}
";
run_test_in_runtime(CODE, |api| {
for variant in 0..4 { // all `Location` enum variants, except `Never`.
// Create the channels
api.create_connector("", "constructor", ValueGroup::new_stack(vec![
Value::Enum(variant)
])).expect("create connector");
}
})
}