Skip to content

Commit

Permalink
test(sns): Porting sns-testing to the ICP mono repo (#3979)
Browse files Browse the repository at this point in the history
This PR implements the next-gen
[sns-testing](https://github.com/dfinity/sns-testing) tool. It can now
be written in Rust and continuously tested against the latest SNS
features.

At the core of this tool lies the [PocketIC
framework](https://crates.io/crates/pocket-ic/6.0.0), the testing
framework capable of creating a fully deterministic environment for
testing complex ICP dapp scenarios.

This PR is authored by Serokell and reviewed by the DFINITY Foundation.
Please refer to the reviews here:
#3654

---------

Co-authored-by: Roman Melnikov <[email protected]>
Co-authored-by: Roman Melnikov <[email protected]>
  • Loading branch information
3 people authored Feb 17, 2025
1 parent 7ac415c commit 5b947cb
Show file tree
Hide file tree
Showing 22 changed files with 833 additions and 43 deletions.
25 changes: 25 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,7 @@ members = [
"rs/sns/swap",
"rs/sns/swap/proto_library",
"rs/sns/test_utils",
"rs/sns/testing",
"rs/starter",
"rs/state_manager",
"rs/state_machine_tests",
Expand Down
2 changes: 2 additions & 0 deletions packages/pocket-ic/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased

### Added
- The function `PocketIc::try_get_controllers` which gets the controllers of a canister but doesn't panic if the target canister
doesn't exist.
- The function `PocketIcBuilder::with_bitcoind_addrs` to specify multiple addresses and ports at which `bitcoind` processes are listening.
- The function `PocketIc::query_call_with_effective_principal` for making generic query calls (including management canister query calls).
- The function `PocketIc::ingress_status` to fetch the status of an update call submitted through an ingress message.
Expand Down
12 changes: 11 additions & 1 deletion packages/pocket-ic/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ use candid::{
Principal,
};
use ic_transport_types::SubnetMetrics;
use reqwest::Url;
use reqwest::{StatusCode, Url};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use slog::Level;
Expand Down Expand Up @@ -649,6 +649,16 @@ impl PocketIc {
runtime.block_on(async { self.pocket_ic.get_controllers(canister_id).await })
}

/// Get the controllers of a canister.
#[instrument(ret, skip(self), fields(instance_id=self.pocket_ic.instance_id, canister_id = %canister_id.to_string()))]
pub fn try_get_controllers(
&self,
canister_id: CanisterId,
) -> Result<Vec<Principal>, (StatusCode, String)> {
let runtime = self.runtime.clone();
runtime.block_on(async { self.pocket_ic.try_get_controllers(canister_id).await })
}

/// Get the current cycles balance of a canister.
#[instrument(ret, skip(self), fields(instance_id=self.pocket_ic.instance_id, canister_id = %canister_id.to_string()))]
pub fn cycle_balance(&self, canister_id: CanisterId) -> u128 {
Expand Down
15 changes: 12 additions & 3 deletions packages/pocket-ic/src/nonblocking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -519,16 +519,25 @@ impl PocketIc {
/// Panics if the canister does not exist.
#[instrument(ret, skip(self), fields(instance_id=self.instance_id, canister_id = %canister_id.to_string()))]
pub async fn get_controllers(&self, canister_id: CanisterId) -> Vec<Principal> {
self.try_get_controllers(canister_id).await.unwrap()
}

/// Get the controllers of a canister.
#[instrument(ret, skip(self), fields(instance_id=self.instance_id, canister_id = %canister_id.to_string()))]
pub async fn try_get_controllers(
&self,
canister_id: CanisterId,
) -> Result<Vec<Principal>, (StatusCode, String)> {
let endpoint = "read/get_controllers";
let result: Vec<RawPrincipalId> = self
.post(
let result: Result<Vec<RawPrincipalId>, (StatusCode, String)> = self
.try_post(
endpoint,
RawCanisterId {
canister_id: canister_id.as_slice().to_vec(),
},
)
.await;
result.into_iter().map(|p| p.into()).collect()
result.map(|v| v.into_iter().map(|p| p.into()).collect())
}

/// Get the current cycles balance of a canister.
Expand Down
13 changes: 13 additions & 0 deletions packages/pocket-ic/tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1739,6 +1739,19 @@ fn get_controllers_of_nonexisting_canister() {
let _ = pic.get_controllers(canister_id);
}

#[test]
fn try_get_controllers_of_nonexisting_canister() {
let pic = PocketIc::new();

let canister_id = pic.create_canister();
pic.add_cycles(canister_id, 100_000_000_000_000);
pic.stop_canister(canister_id, None).unwrap();
pic.delete_canister(canister_id, None).unwrap();

let res = pic.try_get_controllers(canister_id);
assert!(res.is_err())
}

#[test]
fn test_canister_snapshots() {
let pic = PocketIc::new();
Expand Down
2 changes: 1 addition & 1 deletion rs/ledger_suite/icp/index/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use serde_bytes::ByteBuf;

pub mod logs;

#[derive(Debug, CandidType, Deserialize)]
#[derive(Clone, Debug, CandidType, Deserialize)]
pub struct InitArg {
pub ledger_id: Principal,
}
Expand Down
6 changes: 5 additions & 1 deletion rs/nervous_system/agent/src/pocketic_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,11 @@ impl CallCanisters for PocketIcAgent<'_> {
) -> Result<CanisterInfo, Self::Error> {
let canister_id = canister_id.into();

let controllers = self.pocket_ic.get_controllers(canister_id).await;
let controllers = self
.pocket_ic
.try_get_controllers(canister_id)
.await
.unwrap_or(vec![]);

let Some(controller) = controllers.into_iter().last() else {
return Err(Self::Error::BlackHole);
Expand Down
Loading

0 comments on commit 5b947cb

Please sign in to comment.