From b6915bfde6e67bd09695019a3113c8c1a723f9ea Mon Sep 17 00:00:00 2001 From: Adam Bratschi-Kaye Date: Thu, 21 Nov 2024 09:46:05 +0000 Subject: [PATCH] no long execution tests --- .../src/execution/install_code/tests.rs | 136 ++++++------ .../tests/orthogonal_persistence.rs | 62 +++--- .../src/hypervisor/tests.rs | 202 +++++++++--------- .../src/scheduler/tests.rs | 98 ++++----- 4 files changed, 249 insertions(+), 249 deletions(-) diff --git a/rs/execution_environment/src/execution/install_code/tests.rs b/rs/execution_environment/src/execution/install_code/tests.rs index 737f293e9ec..8d82ba86f7a 100644 --- a/rs/execution_environment/src/execution/install_code/tests.rs +++ b/rs/execution_environment/src/execution/install_code/tests.rs @@ -462,74 +462,74 @@ fn install_code_succeeds_with_enough_wasm_custom_sections_memory() { ); } -#[test] -fn install_code_respects_wasm_custom_sections_available_memory() { - // As we install canisters in a loop, using more memory spawns thousands of - // canister sandboxes, which lead to a few GiB memory usage. - let available_wasm_custom_sections_memory = 20 * 1024; // 20KiB - - // This value might need adjustment if something changes in the canister's - // wasm that gets installed in the test. - let total_memory_taken_per_canister_in_bytes = 364249; - - let mut test = ExecutionTestBuilder::new() - .with_install_code_instruction_limit(1_000_000_000) - .with_install_code_slice_instruction_limit(1_000_000_000) - .with_subnet_wasm_custom_sections_memory(available_wasm_custom_sections_memory) - .with_manual_execution() - .build(); - - let subnet_available_memory_before = test.subnet_available_memory().get_execution_memory(); - let mut iterations = 0; - loop { - let canister_id = test - .create_canister_with_allocation(Cycles::new(1_000_000_000_000_000), None, None) - .unwrap(); - - let payload = InstallCodeArgs { - mode: CanisterInstallMode::Install, - canister_id: canister_id.get(), - wasm_module: include_bytes!("../../../tests/test-data/custom_sections.wasm").to_vec(), - arg: vec![], - compute_allocation: None, - memory_allocation: None, - sender_canister_version: None, - }; - - if test - .subnet_message(Method::InstallCode, payload.encode()) - .is_err() - { - // We expect that at some point there is not enough wasm custom sections - // memory left on the subnet and the request to install the canister - // will fail. - break; - } - iterations += 1; - } - - // One more request to install a canister with wasm custom sections should fail. - let canister_id = test - .create_canister_with_allocation(Cycles::new(1_000_000_000_000_000), None, None) - .unwrap(); - - let payload = InstallCodeArgs { - mode: CanisterInstallMode::Install, - canister_id: canister_id.get(), - wasm_module: include_bytes!("../../../tests/test-data/custom_sections.wasm").to_vec(), - arg: vec![], - compute_allocation: None, - memory_allocation: None, - sender_canister_version: None, - }; - let result = test.subnet_message(Method::InstallCode, payload.encode()); - - assert!(result.is_err()); - assert_eq!( - test.subnet_available_memory().get_execution_memory(), - subnet_available_memory_before - iterations * total_memory_taken_per_canister_in_bytes - ); -} +// #[test] +// fn install_code_respects_wasm_custom_sections_available_memory() { +// // As we install canisters in a loop, using more memory spawns thousands of +// // canister sandboxes, which lead to a few GiB memory usage. +// let available_wasm_custom_sections_memory = 20 * 1024; // 20KiB + +// // This value might need adjustment if something changes in the canister's +// // wasm that gets installed in the test. +// let total_memory_taken_per_canister_in_bytes = 364249; + +// let mut test = ExecutionTestBuilder::new() +// .with_install_code_instruction_limit(1_000_000_000) +// .with_install_code_slice_instruction_limit(1_000_000_000) +// .with_subnet_wasm_custom_sections_memory(available_wasm_custom_sections_memory) +// .with_manual_execution() +// .build(); + +// let subnet_available_memory_before = test.subnet_available_memory().get_execution_memory(); +// let mut iterations = 0; +// loop { +// let canister_id = test +// .create_canister_with_allocation(Cycles::new(1_000_000_000_000_000), None, None) +// .unwrap(); + +// let payload = InstallCodeArgs { +// mode: CanisterInstallMode::Install, +// canister_id: canister_id.get(), +// wasm_module: include_bytes!("../../../tests/test-data/custom_sections.wasm").to_vec(), +// arg: vec![], +// compute_allocation: None, +// memory_allocation: None, +// sender_canister_version: None, +// }; + +// if test +// .subnet_message(Method::InstallCode, payload.encode()) +// .is_err() +// { +// // We expect that at some point there is not enough wasm custom sections +// // memory left on the subnet and the request to install the canister +// // will fail. +// break; +// } +// iterations += 1; +// } + +// // One more request to install a canister with wasm custom sections should fail. +// let canister_id = test +// .create_canister_with_allocation(Cycles::new(1_000_000_000_000_000), None, None) +// .unwrap(); + +// let payload = InstallCodeArgs { +// mode: CanisterInstallMode::Install, +// canister_id: canister_id.get(), +// wasm_module: include_bytes!("../../../tests/test-data/custom_sections.wasm").to_vec(), +// arg: vec![], +// compute_allocation: None, +// memory_allocation: None, +// sender_canister_version: None, +// }; +// let result = test.subnet_message(Method::InstallCode, payload.encode()); + +// assert!(result.is_err()); +// assert_eq!( +// test.subnet_available_memory().get_execution_memory(), +// subnet_available_memory_before - iterations * total_memory_taken_per_canister_in_bytes +// ); +// } fn execute_install_code_message_dts_helper( test: &mut ExecutionTest, diff --git a/rs/execution_environment/src/execution_environment/tests/orthogonal_persistence.rs b/rs/execution_environment/src/execution_environment/tests/orthogonal_persistence.rs index 860ecd0574e..2083a36cc01 100644 --- a/rs/execution_environment/src/execution_environment/tests/orthogonal_persistence.rs +++ b/rs/execution_environment/src/execution_environment/tests/orthogonal_persistence.rs @@ -117,35 +117,35 @@ const TEST_NUM_PAGES: usize = 32; const TEST_NUM_WRITES: usize = 20; const WASM_PAGE_SIZE_BYTES: usize = 65536; -#[test] -// generate multiple writes of varying size to random memory locations, apply them both to a -// canister and a simple Vec buffer and compare the results. -fn test_orthogonal_persistence() { - let config = ProptestConfig { - cases: 20, - failure_persistence: None, - ..ProptestConfig::default() - }; - let algorithm = config.rng_algorithm; - let mut runner = TestRunner::new_with_rng(config, TestRng::deterministic_rng(algorithm)); - runner - .run( - &random_writes(TEST_HEAP_SIZE_BYTES, TEST_NUM_WRITES), - |writes| { - let mut test = ExecutionTestBuilder::new().build(); - let mut heap = vec![0; TEST_HEAP_SIZE_BYTES]; - let wat = make_module_wat(TEST_NUM_PAGES); - let canister_id = test.canister_from_wat(wat).unwrap(); +// #[test] +// // generate multiple writes of varying size to random memory locations, apply them both to a +// // canister and a simple Vec buffer and compare the results. +// fn test_orthogonal_persistence() { +// let config = ProptestConfig { +// cases: 20, +// failure_persistence: None, +// ..ProptestConfig::default() +// }; +// let algorithm = config.rng_algorithm; +// let mut runner = TestRunner::new_with_rng(config, TestRng::deterministic_rng(algorithm)); +// runner +// .run( +// &random_writes(TEST_HEAP_SIZE_BYTES, TEST_NUM_WRITES), +// |writes| { +// let mut test = ExecutionTestBuilder::new().build(); +// let mut heap = vec![0; TEST_HEAP_SIZE_BYTES]; +// let wat = make_module_wat(TEST_NUM_PAGES); +// let canister_id = test.canister_from_wat(wat).unwrap(); - for w in &writes { - buf_apply_write(&mut heap, w); - write_bytes(&mut test, canister_id, w.dst, &w.bytes); - // verify the heap - let canister_heap = dump_heap(&mut test, canister_id); - prop_assert_eq!(&heap[..], &canister_heap[..]); - } - Ok(()) - }, - ) - .unwrap(); -} +// for w in &writes { +// buf_apply_write(&mut heap, w); +// write_bytes(&mut test, canister_id, w.dst, &w.bytes); +// // verify the heap +// let canister_heap = dump_heap(&mut test, canister_id); +// prop_assert_eq!(&heap[..], &canister_heap[..]); +// } +// Ok(()) +// }, +// ) +// .unwrap(); +// } diff --git a/rs/execution_environment/src/hypervisor/tests.rs b/rs/execution_environment/src/hypervisor/tests.rs index 70560cd4a23..ec2f0f7154f 100644 --- a/rs/execution_environment/src/hypervisor/tests.rs +++ b/rs/execution_environment/src/hypervisor/tests.rs @@ -1800,36 +1800,36 @@ fn ic0_msg_reject_fails_if_called_twice() { .contains("ic0.msg_reject: the call is already replied")); } -#[test] -fn some_ic0_calls_fail_if_called_with_huge_size() { - fn test(syscall: &str) { - let mut test = ExecutionTestBuilder::new() - // 3T Cycles should be more than enough for a single ingress call. - .with_initial_canister_cycles(3_000_000_000_000) - .build(); - let wat = format!( - r#" - (module - (import "ic0" "{syscall}" - (func $ic0_{syscall} (param i32) (param i32)) - ) - (func (export "canister_update test") - (call $ic0_{syscall} (i32.const 0) (i32.const {SIZE})) - ) - (memory 1 1) - )"#, - SIZE = u32::MAX - ); - let canister_id = test.canister_from_wat(wat).unwrap(); - - let err = test.ingress(canister_id, "test", vec![]).unwrap_err(); - // It must be neither a contract violation nor timeout. - assert_eq!(ErrorCode::CanisterInstructionLimitExceeded, err.code()); - } - for syscall in ["msg_reject", "call_data_append", "msg_reply_data_append"] { - test(syscall); - } -} +// #[test] +// fn some_ic0_calls_fail_if_called_with_huge_size() { +// fn test(syscall: &str) { +// let mut test = ExecutionTestBuilder::new() +// // 3T Cycles should be more than enough for a single ingress call. +// .with_initial_canister_cycles(3_000_000_000_000) +// .build(); +// let wat = format!( +// r#" +// (module +// (import "ic0" "{syscall}" +// (func $ic0_{syscall} (param i32) (param i32)) +// ) +// (func (export "canister_update test") +// (call $ic0_{syscall} (i32.const 0) (i32.const {SIZE})) +// ) +// (memory 1 1) +// )"#, +// SIZE = u32::MAX +// ); +// let canister_id = test.canister_from_wat(wat).unwrap(); + +// let err = test.ingress(canister_id, "test", vec![]).unwrap_err(); +// // It must be neither a contract violation nor timeout. +// assert_eq!(ErrorCode::CanisterInstructionLimitExceeded, err.code()); +// } +// for syscall in ["msg_reject", "call_data_append", "msg_reply_data_append"] { +// test(syscall); +// } +// } #[test] fn ic0_msg_reject_code_works() { @@ -3952,77 +3952,77 @@ fn random_operations( prop::collection::vec(operation, 1..num_operations) } -#[test] -#[cfg(not(all(target_arch = "aarch64", target_vendor = "apple")))] -fn random_memory_accesses() { - // Limit the number of cases to keep the running time low. - let config = ProptestConfig { - cases: 20, - failure_persistence: None, - ..ProptestConfig::default() - }; - let algorithm = config.rng_algorithm; - let mut runner = TestRunner::new_with_rng(config, TestRng::deterministic_rng(algorithm)); - runner - .run(&random_operations(10, 100), |operations| { - const PAGES_PER_WASM_PAGE: i32 = WASM_PAGE_SIZE / 4096; - let mut pages = vec![0_u8; 10 * PAGES_PER_WASM_PAGE as usize]; - let mut dirty = vec![false; 10 * PAGES_PER_WASM_PAGE as usize]; - let mut memory_accessor = MemoryAccessor::new(10); - for op in operations { - match op { - Operation::Read(page) => { - prop_assert_eq!( - vec![pages[page as usize]; 4096], - memory_accessor.read(page * 4096, 4096) - ); - // Read uses the first page as a scratchpad for arguments. - dirty[0] = true; - } - Operation::Write(page, value) => { - // Pages are already zero initialized, so writing zero - // doesn't necessarily dirty them. Avoid zeros to make - // dirty page tracking in the test precise. - prop_assert!(value > 0); - memory_accessor.write(page * 4096, &[value; 4096]); - - // Confirm that the write was correct by reading the page. - prop_assert_eq!(vec![value; 4096], memory_accessor.read(page * 4096, 4096)); - pages[page as usize] = value; - dirty[page as usize] = true; - // Write uses the first page as a scratchpad for arguments. - dirty[0] = true; - } - Operation::GrowAndRead => { - prop_assert_eq!(vec![0; 65536], memory_accessor.grow_and_read()); - pages.extend(vec![0_u8; PAGES_PER_WASM_PAGE as usize]); - dirty.extend(vec![false; PAGES_PER_WASM_PAGE as usize]); - // Read uses the first page as a scratchpad for arguments. - dirty[0] = true; - } - Operation::GrowAndWrite(value) => { - // Pages are already zero initialized, so writing zero - // doesn't necessarily dirty them. Avoid zeros to make - // dirty page tracking in the test precise. - prop_assert!(value > 0); - memory_accessor.grow_and_write(&[value; WASM_PAGE_SIZE as usize]); - // Confirm that the write was correct by reading the pages. - prop_assert_eq!( - vec![value; WASM_PAGE_SIZE as usize], - memory_accessor.read(pages.len() as i32 * 4096, WASM_PAGE_SIZE) - ); - pages.extend(vec![value; PAGES_PER_WASM_PAGE as usize]); - dirty.extend(vec![true; PAGES_PER_WASM_PAGE as usize]); - // Write uses the first page as a scratchpad for arguments. - dirty[0] = true; - } - } - } - memory_accessor.verify_dirty_pages(&dirty); - Ok(()) - }) - .unwrap(); -} +// #[test] +// #[cfg(not(all(target_arch = "aarch64", target_vendor = "apple")))] +// fn random_memory_accesses() { +// // Limit the number of cases to keep the running time low. +// let config = ProptestConfig { +// cases: 20, +// failure_persistence: None, +// ..ProptestConfig::default() +// }; +// let algorithm = config.rng_algorithm; +// let mut runner = TestRunner::new_with_rng(config, TestRng::deterministic_rng(algorithm)); +// runner +// .run(&random_operations(10, 100), |operations| { +// const PAGES_PER_WASM_PAGE: i32 = WASM_PAGE_SIZE / 4096; +// let mut pages = vec![0_u8; 10 * PAGES_PER_WASM_PAGE as usize]; +// let mut dirty = vec![false; 10 * PAGES_PER_WASM_PAGE as usize]; +// let mut memory_accessor = MemoryAccessor::new(10); +// for op in operations { +// match op { +// Operation::Read(page) => { +// prop_assert_eq!( +// vec![pages[page as usize]; 4096], +// memory_accessor.read(page * 4096, 4096) +// ); +// // Read uses the first page as a scratchpad for arguments. +// dirty[0] = true; +// } +// Operation::Write(page, value) => { +// // Pages are already zero initialized, so writing zero +// // doesn't necessarily dirty them. Avoid zeros to make +// // dirty page tracking in the test precise. +// prop_assert!(value > 0); +// memory_accessor.write(page * 4096, &[value; 4096]); + +// // Confirm that the write was correct by reading the page. +// prop_assert_eq!(vec![value; 4096], memory_accessor.read(page * 4096, 4096)); +// pages[page as usize] = value; +// dirty[page as usize] = true; +// // Write uses the first page as a scratchpad for arguments. +// dirty[0] = true; +// } +// Operation::GrowAndRead => { +// prop_assert_eq!(vec![0; 65536], memory_accessor.grow_and_read()); +// pages.extend(vec![0_u8; PAGES_PER_WASM_PAGE as usize]); +// dirty.extend(vec![false; PAGES_PER_WASM_PAGE as usize]); +// // Read uses the first page as a scratchpad for arguments. +// dirty[0] = true; +// } +// Operation::GrowAndWrite(value) => { +// // Pages are already zero initialized, so writing zero +// // doesn't necessarily dirty them. Avoid zeros to make +// // dirty page tracking in the test precise. +// prop_assert!(value > 0); +// memory_accessor.grow_and_write(&[value; WASM_PAGE_SIZE as usize]); +// // Confirm that the write was correct by reading the pages. +// prop_assert_eq!( +// vec![value; WASM_PAGE_SIZE as usize], +// memory_accessor.read(pages.len() as i32 * 4096, WASM_PAGE_SIZE) +// ); +// pages.extend(vec![value; PAGES_PER_WASM_PAGE as usize]); +// dirty.extend(vec![true; PAGES_PER_WASM_PAGE as usize]); +// // Write uses the first page as a scratchpad for arguments. +// dirty[0] = true; +// } +// } +// } +// memory_accessor.verify_dirty_pages(&dirty); +// Ok(()) +// }) +// .unwrap(); +// } // Verify that the `memory.fill` instruction has cost linear with it's size // argument. diff --git a/rs/execution_environment/src/scheduler/tests.rs b/rs/execution_environment/src/scheduler/tests.rs index 4aacc327b92..bb73933d4d7 100644 --- a/rs/execution_environment/src/scheduler/tests.rs +++ b/rs/execution_environment/src/scheduler/tests.rs @@ -4464,55 +4464,55 @@ fn should_never_consume_more_than_max_instructions_per_round_in_a_single_executi ); } -#[test_strategy::proptest] -// This test verifies that the scheduler is deterministic, i.e. given -// the same input, if we execute a round of computation, we always -// get the same result. -fn scheduler_deterministically_produces_same_output_given_same_input( - #[strategy(arb_scheduler_test_double(2..10, 1..20, 1..100, M..B, 1..M, 100, false))] test: ( - SchedulerTest, - SchedulerTest, - usize, - NumInstructions, - NumInstructions, - ), -) { - let (mut test1, mut test2, _cores, _instructions_per_round, _instructions_per_message) = test; - assert_eq!(test1.state(), test2.state()); - test1.execute_round(ExecutionRoundType::OrdinaryRound); - test2.execute_round(ExecutionRoundType::OrdinaryRound); - assert_eq!(test1.state(), test2.state()); -} - -#[test_strategy::proptest] -// This test verifies that the scheduler can successfully deplete the induction -// pool given sufficient consecutive execution rounds. -fn scheduler_can_deplete_induction_pool_given_enough_execution_rounds( - #[strategy(arb_scheduler_test(2..10, 1..20, 1..100, M..B, 1..M, 100, false))] test: ( - SchedulerTest, - usize, - NumInstructions, - NumInstructions, - ), -) { - let (mut test, _scheduler_cores, instructions_per_round, instructions_per_message) = test; - let available_messages = get_available_messages(test.state()); - let minimum_executed_messages = min( - available_messages, - instructions_per_round / instructions_per_message, - ); - let required_rounds = if minimum_executed_messages != 0 { - available_messages / minimum_executed_messages + 1 - } else { - 1 - }; - for _ in 0..required_rounds { - test.execute_round(ExecutionRoundType::OrdinaryRound); - } - for canister_state in test.state().canisters_iter() { - assert_eq!(canister_state.system_state.queues().ingress_queue_size(), 0); - } -} +// #[test_strategy::proptest] +// // This test verifies that the scheduler is deterministic, i.e. given +// // the same input, if we execute a round of computation, we always +// // get the same result. +// fn scheduler_deterministically_produces_same_output_given_same_input( +// #[strategy(arb_scheduler_test_double(2..10, 1..20, 1..100, M..B, 1..M, 100, false))] test: ( +// SchedulerTest, +// SchedulerTest, +// usize, +// NumInstructions, +// NumInstructions, +// ), +// ) { +// let (mut test1, mut test2, _cores, _instructions_per_round, _instructions_per_message) = test; +// assert_eq!(test1.state(), test2.state()); +// test1.execute_round(ExecutionRoundType::OrdinaryRound); +// test2.execute_round(ExecutionRoundType::OrdinaryRound); +// assert_eq!(test1.state(), test2.state()); +// } + +// #[test_strategy::proptest] +// // This test verifies that the scheduler can successfully deplete the induction +// // pool given sufficient consecutive execution rounds. +// fn scheduler_can_deplete_induction_pool_given_enough_execution_rounds( +// #[strategy(arb_scheduler_test(2..10, 1..20, 1..100, M..B, 1..M, 100, false))] test: ( +// SchedulerTest, +// usize, +// NumInstructions, +// NumInstructions, +// ), +// ) { +// let (mut test, _scheduler_cores, instructions_per_round, instructions_per_message) = test; +// let available_messages = get_available_messages(test.state()); +// let minimum_executed_messages = min( +// available_messages, +// instructions_per_round / instructions_per_message, +// ); +// let required_rounds = if minimum_executed_messages != 0 { +// available_messages / minimum_executed_messages + 1 +// } else { +// 1 +// }; +// for _ in 0..required_rounds { +// test.execute_round(ExecutionRoundType::OrdinaryRound); +// } +// for canister_state in test.state().canisters_iter() { +// assert_eq!(canister_state.system_state.queues().ingress_queue_size(), 0); +// } +// } #[test_strategy::proptest] // This test verifies that the scheduler does not lose any canisters