From 57dc46990c8d34f2ac1193a839b201feeb37e15a Mon Sep 17 00:00:00 2001 From: Andriy Berestovskyy Date: Tue, 4 Feb 2025 22:34:04 +0100 Subject: [PATCH 1/2] test: EXC-1878: Add failed stable memory grow tests Failed memory growth operations finish in just a few milliseconds, so 10k seems like a safe assertion. --- .../tests/execution_test.rs | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/rs/execution_environment/tests/execution_test.rs b/rs/execution_environment/tests/execution_test.rs index db5234f9cdd..6daa1cde238 100644 --- a/rs/execution_environment/tests/execution_test.rs +++ b/rs/execution_environment/tests/execution_test.rs @@ -2893,3 +2893,78 @@ fn no_critical_error_on_empty_data_segment() { "Wasm module has invalid data segment of 0 bytes at 1.", ); } + +#[test] +fn failed_stable_memory_grow_cost_and_time_single_canister() { + const NUM_WASM_PAGES: u64 = 116 * 1024 * MIB / 65_536; + + let env = StateMachineBuilder::new() + .with_subnet_type(SubnetType::Application) + .build(); + + let canister_id = create_universal_canister_with_cycles(&env, None, INITIAL_CYCLES_BALANCE); + + let timer = std::time::Instant::now(); + let initial_balance = env.cycle_balance(canister_id); + let _res = env.execute_ingress( + canister_id, + "update", + wasm() + .stable64_grow(NUM_WASM_PAGES) + .stable64_write(0, &[42]) + .trap() + .build(), + ); + let elapsed_ms = timer.elapsed().as_millis(); + let cycles_m = (initial_balance - env.cycle_balance(canister_id)) / 1000 / 1000; + assert!( + elapsed_ms < 10_000, + "Test timed out after {elapsed_ms} ms and {cycles_m} Mcycles" + ); +} + +#[test] +fn failed_stable_memory_grow_cost_and_time_multiple_canisters() { + const NUM_WASM_PAGES: u64 = 116 * 1024 * MIB / 65_536; + const NUM_CANISTERS: u64 = 128; + + let env = StateMachineBuilder::new() + .with_subnet_type(SubnetType::Application) + .build(); + + let mut canister_ids = vec![]; + for _ in 0..NUM_CANISTERS { + let canister_id = create_universal_canister_with_cycles(&env, None, INITIAL_CYCLES_BALANCE); + canister_ids.push(canister_id); + } + + let timer = std::time::Instant::now(); + let mut total_initial_balance = 0; + let mut payload = ic_state_machine_tests::PayloadBuilder::new(); + for canister_id in &canister_ids { + let balance = env.cycle_balance(*canister_id); + total_initial_balance += balance; + payload = payload.ingress( + PrincipalId::new_anonymous(), + *canister_id, + "update", + wasm() + .stable64_grow(NUM_WASM_PAGES) + .stable64_write(0, &[42]) + .trap() + .build(), + ); + } + env.execute_payload(payload); + let elapsed_ms = timer.elapsed().as_millis(); + let mut total_balance = 0; + for canister_id in &canister_ids { + let balance = env.cycle_balance(*canister_id); + total_balance += balance; + } + let cycles_m = (total_initial_balance - total_balance) / 1000 / 1000; + assert!( + elapsed_ms < 10_000, + "Test timed out after {elapsed_ms} ms and {cycles_m} Mcycles" + ); +} From ec8dcdeb64d5eec3338d35bd4ac8c8e5c874d985 Mon Sep 17 00:00:00 2001 From: Andriy Berestovskyy Date: Fri, 14 Feb 2025 14:43:29 +0100 Subject: [PATCH 2/2] Post-review fixes --- .../tests/execution_test.rs | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/rs/execution_environment/tests/execution_test.rs b/rs/execution_environment/tests/execution_test.rs index 6daa1cde238..21466424583 100644 --- a/rs/execution_environment/tests/execution_test.rs +++ b/rs/execution_environment/tests/execution_test.rs @@ -28,6 +28,8 @@ use std::{convert::TryInto, str::FromStr, sync::Arc, time::Duration}; /// One megabyte for better readability. const MIB: u64 = 1024 * 1024; +/// One gigabyte for better readability. +const GIB: u64 = 1024 * MIB; /// One billion for better cycles readability. const B: u128 = 1e9 as u128; @@ -2896,7 +2898,7 @@ fn no_critical_error_on_empty_data_segment() { #[test] fn failed_stable_memory_grow_cost_and_time_single_canister() { - const NUM_WASM_PAGES: u64 = 116 * 1024 * MIB / 65_536; + let num_wasm_pages = 116 * GIB / WASM_PAGE_SIZE_IN_BYTES; let env = StateMachineBuilder::new() .with_subnet_type(SubnetType::Application) @@ -2910,7 +2912,7 @@ fn failed_stable_memory_grow_cost_and_time_single_canister() { canister_id, "update", wasm() - .stable64_grow(NUM_WASM_PAGES) + .stable64_grow(num_wasm_pages) .stable64_write(0, &[42]) .trap() .build(), @@ -2919,21 +2921,22 @@ fn failed_stable_memory_grow_cost_and_time_single_canister() { let cycles_m = (initial_balance - env.cycle_balance(canister_id)) / 1000 / 1000; assert!( elapsed_ms < 10_000, - "Test timed out after {elapsed_ms} ms and {cycles_m} Mcycles" + "Test timed out after {elapsed_ms} ms and {cycles_m} M cycles" ); + assert!(cycles_m > 5); } #[test] fn failed_stable_memory_grow_cost_and_time_multiple_canisters() { - const NUM_WASM_PAGES: u64 = 116 * 1024 * MIB / 65_536; - const NUM_CANISTERS: u64 = 128; + let num_wasm_pages = 116 * GIB / WASM_PAGE_SIZE_IN_BYTES; + let num_canisters = 128; let env = StateMachineBuilder::new() .with_subnet_type(SubnetType::Application) .build(); let mut canister_ids = vec![]; - for _ in 0..NUM_CANISTERS { + for _ in 0..num_canisters { let canister_id = create_universal_canister_with_cycles(&env, None, INITIAL_CYCLES_BALANCE); canister_ids.push(canister_id); } @@ -2949,7 +2952,7 @@ fn failed_stable_memory_grow_cost_and_time_multiple_canisters() { *canister_id, "update", wasm() - .stable64_grow(NUM_WASM_PAGES) + .stable64_grow(num_wasm_pages) .stable64_write(0, &[42]) .trap() .build(), @@ -2965,6 +2968,7 @@ fn failed_stable_memory_grow_cost_and_time_multiple_canisters() { let cycles_m = (total_initial_balance - total_balance) / 1000 / 1000; assert!( elapsed_ms < 10_000, - "Test timed out after {elapsed_ms} ms and {cycles_m} Mcycles" + "Test timed out after {elapsed_ms} ms and {cycles_m} M cycles" ); + assert!(cycles_m > 800); }