Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: api module overhaul #540

Merged
merged 24 commits into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
158 changes: 158 additions & 0 deletions e2e-tests/src/bin/api.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
use candid::Principal;
use ic_cdk::api::*;

#[export_name = "canister_update call_msg_arg_data"]
fn call_msg_arg_data() {
assert_eq!(msg_arg_data(), vec![42]);
msg_reply(vec![]);
}

#[export_name = "canister_update call_msg_caller"]
fn call_msg_caller() {
assert_eq!(msg_caller(), Principal::anonymous());
msg_reply(vec![]);
}

#[export_name = "canister_update call_msg_reply"]
fn call_msg_reply() {
msg_reply(vec![42]);
}

#[export_name = "canister_update call_msg_reject"]
fn call_msg_reject() {
msg_reject("e2e test reject");
}

#[export_name = "canister_update call_msg_cycles_available"]
fn call_msg_cycles_available() {
assert_eq!(msg_cycles_available(), 0);
msg_reply(vec![]);
}

#[export_name = "canister_update call_msg_cycles_accept"]
fn call_msg_cycles_accept() {
// The available cycles are 0, so the actual cycles accepted are 0.
assert_eq!(msg_cycles_accept(1000), 0);
msg_reply(vec![]);
}

#[export_name = "canister_update call_cycles_burn"]
fn call_cycles_burn() {
assert_eq!(cycles_burn(1000), 1000);
msg_reply(vec![]);
}

#[export_name = "canister_update call_canister_self"]
fn call_canister_self() {
let self_id = canister_self();
// The sender sended canister ID
let data = msg_arg_data();
assert_eq!(self_id.as_slice(), data);
msg_reply(vec![]);
}

#[export_name = "canister_update call_canister_cycle_balance"]
fn call_canister_cycle_balance() {
assert!(canister_cycle_balance() > 0);
msg_reply(vec![]);
}

#[export_name = "canister_update call_canister_status"]
fn call_canister_status() {
assert_eq!(canister_status(), CanisterStatusCode::Running);
assert_eq!(canister_status(), 1);
msg_reply(vec![]);
}

#[export_name = "canister_update call_canister_version"]
fn call_canister_version() {
assert!(canister_version() > 0);
msg_reply(vec![]);
}

#[export_name = "canister_inspect_message"]
fn inspect_message() {
assert!(msg_method_name().starts_with("call_"));
accept_message();
}

#[export_name = "canister_update call_stable"]
fn call_stable() {
assert_eq!(stable_size(), 0);
assert_eq!(stable_grow(1), 0);
let data = vec![42];
stable_write(0, &data);
let mut read_buf = vec![0];
stable_read(0, &mut read_buf);
assert_eq!(read_buf, data);
msg_reply(vec![]);
}

#[export_name = "canister_update call_certified_data_set"]
fn call_certified_data_set() {
certified_data_set(vec![42]);
msg_reply(vec![]);
}

#[export_name = "canister_query call_data_certificate"]
fn call_data_certificate() {
assert!(data_certificate().is_some());
msg_reply(vec![]);
}

#[export_name = "canister_update call_time"]
fn call_time() {
assert!(time() > 0);
msg_reply(vec![]);
}

#[export_name = "canister_update call_performance_counter"]
fn call_performance_counter() {
let t0 = PerformanceCounterType::InstructionCounter;
assert_eq!(t0, 0);
let ic0 = performance_counter(0);
let ic1 = performance_counter(t0);
let ic2 = instruction_counter();
assert!(ic0 < ic1);
assert!(ic1 < ic2);

let t1 = PerformanceCounterType::CallContextInstructionCounter;
assert_eq!(t1, 1);
let ccic0 = performance_counter(1);
let ccic1 = performance_counter(t1);
let ccic2 = call_context_instruction_counter();
assert!(ccic0 < ccic1);
assert!(ccic1 < ccic2);
msg_reply(vec![]);
}

#[export_name = "canister_update call_is_controller"]
fn call_is_controller() {
// The canister was created by the anonymous principal.
assert!(is_controller(&Principal::anonymous()));
msg_reply(vec![]);
}

/// This entry point will be called by both update and query calls.
/// The query call will return 0, and the update call will return 1.
#[export_name = "canister_query call_in_replicated_execution"]
fn call_in_replicated_execution() {
let res = match in_replicated_execution() {
true => 1,
false => 0,
};
msg_reply(vec![res]);
}

#[export_name = "canister_update call_debug_print"]
fn call_debug_print() {
debug_print("Hello, world!");
msg_reply(vec![]);
}

#[export_name = "canister_update call_trap"]
fn call_trap() {
trap("It's a trap!");
}

fn main() {}
14 changes: 9 additions & 5 deletions e2e-tests/src/bin/async.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ async fn panic_after_async() {
let value = *lock;
// Do not drop the lock before the await point.

let _: (u64,) = ic_cdk::call(ic_cdk::api::id(), "inc", (value,))
let _: (u64,) = ic_cdk::call(ic_cdk::api::canister_self(), "inc", (value,))
.await
.expect("failed to call self");
ic_cdk::api::trap("Goodbye, cruel world.")
Expand All @@ -47,7 +47,7 @@ async fn panic_twice() {
}

async fn async_then_panic() {
let _: (u64,) = ic_cdk::call(ic_cdk::api::id(), "on_notify", ())
let _: (u64,) = ic_cdk::call(ic_cdk::api::canister_self(), "on_notify", ())
.await
.expect("Failed to call self");
panic!();
Expand All @@ -66,7 +66,7 @@ fn on_notify() {
#[update]
fn notify(whom: Principal, method: String) {
ic_cdk::notify(whom, method.as_str(), ()).unwrap_or_else(|reject| {
ic_cdk::api::trap(&format!(
ic_cdk::api::trap(format!(
"failed to notify (callee={}, method={}): {:?}",
whom, method, reject
))
Expand All @@ -89,8 +89,12 @@ async fn greet_self(greeter: Principal) -> String {
#[update]
async fn invalid_reply_payload_does_not_trap() -> String {
// We're decoding an integer instead of a string, decoding must fail.
let result: Result<(u64,), _> =
ic_cdk::call(ic_cdk::api::id(), "greet", ("World".to_string(),)).await;
let result: Result<(u64,), _> = ic_cdk::call(
ic_cdk::api::canister_self(),
"greet",
("World".to_string(),),
)
.await;

match result {
Ok((_n,)) => ic_cdk::api::trap("expected the decoding to fail"),
Expand Down
Loading