From a974c8261a336e3a139d67305f959ee6797b48d2 Mon Sep 17 00:00:00 2001 From: Martin Raszyk Date: Fri, 17 Jan 2025 18:13:46 +0100 Subject: [PATCH] test: reproduce that global timer is not reset after loading snapshot --- .../pocket-ic/test_canister/src/canister.rs | 15 ++++++- packages/pocket-ic/tests/tests.rs | 40 +++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/packages/pocket-ic/test_canister/src/canister.rs b/packages/pocket-ic/test_canister/src/canister.rs index 239803ea47b..77ece6823dd 100644 --- a/packages/pocket-ic/test_canister/src/canister.rs +++ b/packages/pocket-ic/test_canister/src/canister.rs @@ -1,6 +1,5 @@ use candid::{define_function, CandidType, Principal}; use ic_cdk::api::call::{accept_message, arg_data_raw, reject, RejectionCode}; -use ic_cdk::api::instruction_counter; use ic_cdk::api::management_canister::ecdsa::{ ecdsa_public_key as ic_cdk_ecdsa_public_key, sign_with_ecdsa as ic_cdk_sign_with_ecdsa, EcdsaCurve, EcdsaKeyId, EcdsaPublicKeyArgument, EcdsaPublicKeyResponse, SignWithEcdsaArgument, @@ -9,6 +8,7 @@ use ic_cdk::api::management_canister::http_request::{ http_request as canister_http_outcall, CanisterHttpRequestArgument, HttpMethod, HttpResponse, TransformArgs, TransformContext, TransformFunc, }; +use ic_cdk::api::{instruction_counter, set_global_timer}; use ic_cdk::{inspect_message, query, trap, update}; use serde::{Deserialize, Serialize}; use serde_bytes::ByteBuf; @@ -347,4 +347,17 @@ fn trap_update() { trap("trap in update method"); } +// global timer + +#[export_name = "canister_global_timer"] +fn timer() { + ic_cdk::print("I'm running in a global timer!"); +} + +#[update] +fn set_timer() { + let time = ic_cdk::api::time() + 10_000_000_000; + set_global_timer(time); +} + fn main() {} diff --git a/packages/pocket-ic/tests/tests.rs b/packages/pocket-ic/tests/tests.rs index a872790851b..2eb2543b2e4 100644 --- a/packages/pocket-ic/tests/tests.rs +++ b/packages/pocket-ic/tests/tests.rs @@ -2220,3 +2220,43 @@ fn test_reject_response_type() { assert!(!err.certified); } } + +#[test] +fn loading_snapshot_resets_global_timer() { + let pic = PocketIc::new(); + + // We create a test canister. + let canister = pic.create_canister(); + pic.add_cycles(canister, INIT_CYCLES); + pic.install_canister(canister, test_canister_wasm(), vec![], None); + + // We take a snapshot of the test canister. + pic.stop_canister(canister, None).unwrap(); + let snapshot = pic.take_canister_snapshot(canister, None, None).unwrap(); + pic.start_canister(canister, None).unwrap(); + + // We set the global timer to 10s from now. + update_candid::<_, ((),)>(&pic, canister, "set_timer", ((),)).unwrap(); + + // We load the snapshot of the test canister taken before setting the global timer. + pic.stop_canister(canister, None).unwrap(); + pic.load_canister_snapshot(canister, None, snapshot.id) + .unwrap(); + pic.start_canister(canister, None).unwrap(); + + // We advance time by 10s and execute a couple of rounds to see if the global timer triggers. + pic.advance_time(std::time::Duration::from_secs(10)); + for _ in 0..4 { + pic.tick(); + } + + // there shouldn't be any logs since the timer should be reset after loading the snapshot + let logs: Vec<_> = pic + .fetch_canister_logs(canister, Principal::anonymous()) + .unwrap() + .into_iter() + .map(|log| String::from_utf8(log.content).unwrap()) + .collect(); + println!("logs: {:?}", logs); + assert!(logs.is_empty()); +}