PocketIC: Multi-Subnet Canister Testing
Today, we released PocketIC v2.0.0, which enables canister developers to test in a multi-subnet setting. The new server version comes with matching updates to the Rust library and the Python library.
Multi-subnet testing is a novelty in the ecosystem, so consider this feature slightly experimental. Your feedback will help it mature!
What is PocketIC?
A fast and deterministic canister testing platform. Now with real cross-net calls!
For more general info, see the previous thread.
Multi-Subnet Testing: How?
Here are the key features of multi-subnet PocketIC, as exposed by the PocketIC Rust library:
Create an IC instance with an NNS subnet and two application subnets:
let pic = PocketIcBuilder::new()
.with_nns_subnet()
.with_application_subnet()
.with_application_subnet()
.build();
Target the NNS subnet specifically to create a canister:
let nns_sub = pic.topology().get_nns_subnet().unwrap();
let nns_can_id = pic.create_canister_on_subnet(..., nns_sub);
Target one of the app subnets specifically to install a canister:
let app_sub_2 = pic.topology().get_app_subnets()[1];
let app_can_id = pic.create_canister_on_subnet(..., app_sub_2);
Create a canister with a specific canister_id on a named subnet
I.e., the subnet with the corresponding canister_id range; in this example, the NNS subnet:
let ledger_canister_id = Principal::from_text("ryjl3-tyaaa-aaaaa-aaaba-cai").unwrap();
pic.create_canister_with_id(..., ledger_canister_id);
pic.install_canister(ledger_canister_id, ...);
The subnet types include:
- Generic system subnet
- Generic application subnet
- Named subnet with canister_id range like on mainnet: NNS, SNS, II, Fiduciary, Bitcoin. Only these can be targeted by
install_canister_with_id()
What Breaking Changes Come With v2.0.0?
Very few.
In the Rust client library API:
create_canister()
takes no arguments; to specify a sender, usecreate_canister_with_settings()
call_candid_as()
takes an additional argumentOption<EffectivePrincipal>
A notable difference is that by default, PocketIC used to contain a system subnet, and from v2.0.0 onwards, it defaults to containing an application subnet. Because the message size limits are now smaller by default, some calls with large payloads could now fail. Note, however, that this is more realistic, because on mainnet you install on an app subnet anyway.
Calling Tick
on an IC instance now attempts to make progress on all subnets. This is necessary because that is the only way potential cross-net messages can be processed. Therefore, be extra careful with timers/heartbeats, which are and always have been only tentatively supported by PocketIC.
For details, see the changelogs of the PocketIC server and of the Rust library.
Questions?
Please reach out to us in this thread. We are happy to help with your setup, and are keen to learn about your bug reports and feature requests.