PocketIC Version 5.0.0: Several New Cool Features

Pocket IC

We have released PocketIC server 5.0.0 and its Rust library 4.0.0. This release contains several new cool features requested on the forum or by the SDK team to improve DevX when using PocketIC via DFX (please note that this latest PocketIC release is not yet available in DFX and we’ll follow up with a separate forum post once this is the case).

Changelog

Here’s an overview of the new features included in the latest PocketIC release and their use cases:

  • Non-blocking Rust library: use the PocketIC library in async environments, e.g., tokio::test;
  • Large WASM support: install large WASM transparently (just like small WASM) via the PocketIC library;
  • Mainnet canister IDs: create canisters with user-specified mainnet canister IDs;
  • Canister HTTP outcalls: test canister HTTP outcalls deterministically (mocking HTTP responses and/or failures);
  • State directory: restart a PocketIC instance preserving the state from a past execution;
  • PocketIC dashboard: retrieve a summary (HTML page) of all canisters deployed on a PocketIC instance, analogous to the replica dashboard available in DFX;
  • Non-mainnet features: test IC features that are not yet available on the IC mainnet (e.g., best-effort responses);
  • ECDSA support: use three ECDSA keys with names dfx_test_key1, test_key_1, and key_1 which are available on the II subnet of a PocketIC instance if the PocketIC instance is created with the II subnet.

For a complete list of changes, see the server changelog and the library changelog.

For more details including sketches of canister test code for some of the new features, see HowTo.

Roadmap

The following features are on the roadmap to make PocketIC the ultimate solution for canister testing in DFX:

  • tSchnorr support in the management canister for testing canisters directly integrating with BTC/SOL;
  • query statistics support in the management canister (a.k.a. query call metrics);
  • native bitcoin integration for testing canisters using the Bitcoin management canister API on the IC.

Conclusion

Your feedback helps us improve PocketIC, so please let us know your thoughts and questions in this thread.

Thank you for providing feature requests and feedback on your PocketIC user experience!

17 Likes

Sweet!

Just to clarify: this can only be used to mock responses, not to make actual outcalls, is that correct?

The outcalls are actually made as HTTP requests to a specified URL in the live mode of PocketIC.

1 Like

@ufoscout, you may find this interesting, especially the async library.

Great @mraszyk, especially these two!

:boom:

:boom:

1 Like

Thank you! This looks like a great improvement

@mraszyk
What happens exactly if the nonblocking client is not dropped? For example in case of a test error:

#[tokio::test]
async fn test_counter_canister_async() {
    let pic = pocket_ic::nonblocking::PocketIc::new().await;
    assert!(false);
    pic.drop().await;
}

Then there’s a resource leak and if the PocketIC instance is live, for instance, then a background thread will continue running and submitting operations to that PocketIC instance.

Ok, but when the cargo test process ends all those resources are removed, right? Will this cause the PocketIc Server process to stay alive after the test execution?

Ok, but when the cargo test process ends all those resources are removed, right?

There’s no resource leak in the test driver in any case. The resource leak is on the server side.

Will this cause the PocketIc Server process to stay alive after the test execution?

No, the PocketIC server terminates 60 seconds after receiving the last HTTP request. If you export export RUST_LOG=debug and rerun your experiment, you should see the corresponding log message saying that the server is about to terminate roughly 60 seconds after cargo test terminated.

Same in the live mode:

#[tokio::test]
async fn test_counter_canister_async() {
    let mut pic = pocket_ic::PocketIcBuilder::new().with_nns_subnet().build_async().await;
    pic.make_live(None).await;
    assert!(false);
    pic.drop().await;
}
1 Like