diff --git a/src/runtime2/tests/sync_failure.rs b/src/runtime2/tests/sync_failure.rs index ae6becc1f9226fcd4a2a1b3247d8f3c6027eedf0..2960280107bae342e742ad3988d1f629f30e6a54 100644 --- a/src/runtime2/tests/sync_failure.rs +++ b/src/runtime2/tests/sync_failure.rs @@ -50,28 +50,56 @@ primitive failing_at_location(in input, out output, Location loc) { } } -composite constructor_a(Location loc) { +composite constructor_pair_a(Location loc) { channel output_a -> input_a; channel output_b -> input_b; new failing_at_location(input_b, output_a, loc); new failing_at_location(input_a, output_b, Location::Never); } -composite constructor_b(Location loc) { +composite constructor_pair_b(Location loc) { channel output_a -> input_a; channel output_b -> input_b; new failing_at_location(input_b, output_a, Location::Never); new failing_at_location(input_a, output_b, loc); -}"; +} + +composite constructor_ring(u32 ring_size, u32 fail_a, Location loc_a, u32 fail_b, Location loc_b) { + channel output_first -> input_old; + channel output_cur -> input_new; + + u32 ring_index = 0; + while (ring_index < ring_size) { + auto cur_loc = Location::Never; + if (ring_index == fail_a) cur_loc = loc_a; + if (ring_index == fail_b) cur_loc = loc_b; + + new failing_at_location(input_old, output_cur, cur_loc); + + if (ring_index == ring_size - 2) { + // Don't create a new channel, join up the last one + output_cur = output_first; + input_old = input_new; + } else if (ring_index != ring_size - 1) { + channel output_fresh -> input_fresh; + input_old = input_new; + output_cur = output_fresh; + input_new = input_fresh; + } + + ring_index += 1; + } +} +"; #[test] -fn test_shared_sync_failure_variant_a() { +fn test_shared_sync_failure_pair_variant_a() { // One fails, the other one should somehow detect it and fail as well. This // variant constructs the failing component first. run_test_in_runtime(SHARED_SYNC_CODE, |api| { for variant in 0..4 { // all `Location` enum variants, except `Never`. // Create the channels - api.create_connector("", "constructor_a", ValueGroup::new_stack(vec![ + api.create_connector("", "constructor_pair_a", ValueGroup::new_stack(vec![ Value::Enum(variant) ])).expect("create connector"); } @@ -79,14 +107,29 @@ fn test_shared_sync_failure_variant_a() { } #[test] -fn test_shared_sync_failure_variant_b() { +fn test_shared_sync_failure_pair_variant_b() { // One fails, the other one should somehow detect it and fail as well. This // variant constructs the successful component first. run_test_in_runtime(SHARED_SYNC_CODE, |api| { for variant in 0..4 { - api.create_connector("", "constructor_b", ValueGroup::new_stack(vec![ + api.create_connector("", "constructor_pair_b", ValueGroup::new_stack(vec![ Value::Enum(variant) ])).expect("create connector"); } }) +} + +#[test] +fn test_shared_sync_failure_ring_variant_a() { + // Only one component in the ring should fail + const RING_SIZE: u32 = 4; + run_test_in_runtime(SHARED_SYNC_CODE, |api| { + for variant in 0..4 { + api.create_connector("", "constructor_ring", ValueGroup::new_stack(vec![ + Value::UInt32(RING_SIZE), + Value::UInt32(RING_SIZE / 2), Value::Enum(variant), // fail "halfway" the ring + Value::UInt32(RING_SIZE), Value::Enum(0), // never occurs, index is equal to ring size + ])).expect("create connector"); + } + }) } \ No newline at end of file