Skip to content

Commit

Permalink
test all Call struct variants and rename ArgDecoderConfig to DecoderC…
Browse files Browse the repository at this point in the history
…onfig
  • Loading branch information
lwshang committed Dec 11, 2024
1 parent d70eb01 commit 31bebf4
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 22 deletions.
77 changes: 69 additions & 8 deletions e2e-tests/src/bin/call_struct.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,78 @@
use candid::Principal;
use ic_cdk::api::management_canister::main::{CanisterIdRecord, CreateCanisterArgument};
use ic_cdk::prelude::*;
use candid::Encode;
use ic_cdk::{call::DecoderConfig, prelude::*};

/// This endpoint is to be called by the following Call struct invocation.
#[update]
async fn create_canister_via_struct() -> Principal {
let res: (CanisterIdRecord,) = Call::new(Principal::management_canister(), "create_canister")
.with_args((CreateCanisterArgument::default(),))
.with_cycles(1_000_000_000_000)
async fn echo(arg: u32) -> u32 {
arg
}

#[update]
async fn call_struct() {
let num = 1u32;
let bytes: Vec<u8> = Encode!(&num).unwrap();

// 1. Various ways to call*
// 1.1 call()
let res: (u32,) = Call::new(id(), "echo")
.with_args((num,))
.call()
.await
.unwrap();
assert_eq!(res.0, num);
// 1.2 call_raw()
let res = Call::new(id(), "echo")
.with_args((num,))
.call_raw()
.await
.unwrap();
assert_eq!(res, bytes);
// 1.3 call_with_decoder_config()
let config = DecoderConfig::default();
let res: (u32,) = Call::new(id(), "echo")
.with_args((num,))
.call_with_decoder_config(&config)
.await
.unwrap();
assert_eq!(res.0, num);
// 1.4 call_raw_with_decoder_config()
Call::new(id(), "echo")
.with_args((num,))
.call_and_forget()
.unwrap();

// 2. Various ways to config the call
// 2.1 with_raw_args()
let res: (u32,) = Call::new(id(), "echo")
.with_raw_args(&bytes)
.call()
.await
.unwrap();
assert_eq!(res.0, num);
// 2.2 with_guaranteed_response()
let res: (u32,) = Call::new(id(), "echo")
.with_args((num,))
.with_guaranteed_response()
.call()
.await
.unwrap();
res.0.canister_id
assert_eq!(res.0, num);
// 2.3 change_timeout()
let res: (u32,) = Call::new(id(), "echo")
.with_args((num,))
.change_timeout(5)
.call()
.await
.unwrap();
assert_eq!(res.0, num);
// 2.4 with_cycles()
let res: (u32,) = Call::new(id(), "echo")
.with_args((num,))
.with_cycles(100_000)
.call()
.await
.unwrap();
assert_eq!(res.0, num);
}

fn main() {}
14 changes: 8 additions & 6 deletions e2e-tests/tests/call_struct.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
use candid::Principal;
use ic_cdk_e2e_tests::cargo_build_canister;
use pocket_ic::common::rest::RawEffectivePrincipal;
use pocket_ic::{call_candid, PocketIc};
use pocket_ic::{call_candid, PocketIcBuilder};

#[test]
fn call_struct() {
let pic = PocketIc::new();
let pic = PocketIcBuilder::new()
.with_application_subnet()
.with_nonmainnet_features(true)
.build();
let wasm = cargo_build_canister("call_struct");
let canister_id = pic.create_canister();
pic.add_cycles(canister_id, 100_000_000_000_000);
pic.install_canister(canister_id, wasm, vec![], None);
let _: (Principal,) = call_candid(
let _: () = call_candid(
&pic,
canister_id,
RawEffectivePrincipal::None,
"create_canister_via_struct",
"call_struct",
(),
)
.expect("Error calling create_canister_via_struct");
.expect("Error calling call_struct");
}
20 changes: 12 additions & 8 deletions ic-cdk/src/call.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! APIs to make and manage calls in the canister.
use crate::api::{msg_arg_data, msg_reject_code, msg_reject_msg};
use candid::utils::{decode_args_with_config_debug, ArgumentDecoder, ArgumentEncoder};
use candid::{decode_args, encode_args, CandidType, DecoderConfig, Deserialize, Principal};
use candid::{decode_args, encode_args, CandidType, Deserialize, Principal};
use std::future::Future;
use std::pin::Pin;
use std::sync::atomic::Ordering;
Expand Down Expand Up @@ -403,7 +403,7 @@ pub trait SendableCall {
/// Sends the call and decodes the reply to a Candid type with a decoding quota.
fn call_with_decoder_config<R: for<'b> ArgumentDecoder<'b>>(
self,
decoder_config: &ArgDecoderConfig,
decoder_config: &DecoderConfig,
) -> impl Future<Output = CallResult<R>> + Send + Sync
where
Self: Sized,
Expand Down Expand Up @@ -586,7 +586,11 @@ fn add_payment(payment: u128) {
}
}

fn print_decoding_debug_info(title: &str, cost: &DecoderConfig, pre_cycles: Option<u64>) {
fn print_decoding_debug_info(
title: &str,
cost: &candid::de::DecoderConfig,
pre_cycles: Option<u64>,
) {
use crate::api::{performance_counter, print};
let pre_cycles = pre_cycles.unwrap_or(0);
let instrs = performance_counter(0) - pre_cycles;
Expand All @@ -601,7 +605,7 @@ fn print_decoding_debug_info(title: &str, cost: &DecoderConfig, pre_cycles: Opti

#[derive(Debug)]
/// Config to control the behavior of decoding canister endpoint arguments.
pub struct ArgDecoderConfig {
pub struct DecoderConfig {
/// Limit the total amount of work the deserializer can perform. See [docs on the Candid library](https://docs.rs/candid/latest/candid/de/struct.DecoderConfig.html#method.set_decoding_quota) to understand the cost model.
pub decoding_quota: Option<usize>,
/// Limit the total amount of work for skipping unneeded data on the wire. See [docs on the Candid library](https://docs.rs/candid/latest/candid/de/struct.DecoderConfig.html#method.set_skipping_quota) to understand the skipping cost.
Expand All @@ -610,9 +614,9 @@ pub struct ArgDecoderConfig {
pub debug: bool,
}

impl ArgDecoderConfig {
fn to_candid_config(&self) -> DecoderConfig {
let mut config = DecoderConfig::new();
impl DecoderConfig {
fn to_candid_config(&self) -> candid::de::DecoderConfig {
let mut config = candid::de::DecoderConfig::new();
if let Some(n) = self.decoding_quota {
config.set_decoding_quota(n);
}
Expand All @@ -626,7 +630,7 @@ impl ArgDecoderConfig {
}
}

impl Default for ArgDecoderConfig {
impl Default for DecoderConfig {
fn default() -> Self {
Self {
decoding_quota: None,
Expand Down

0 comments on commit 31bebf4

Please sign in to comment.