-
Notifications
You must be signed in to change notification settings - Fork 11
/
lib.rs
108 lines (85 loc) · 2.83 KB
/
lib.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
use ic_canister::PreUpdate;
use ic_exports::ic_cdk::export::candid::{CandidType, Deserialize, Principal};
use ic_storage::{stable::Versioned, IcStorage};
use std::{cell::RefCell, rc::Rc};
use ic_canister::{generate_exports, query, state_getter, update, Canister};
#[derive(Default, CandidType, Deserialize, IcStorage)]
pub struct StateA {
counter: u32,
}
impl Versioned for StateA {
type Previous = ();
fn upgrade((): ()) -> Self {
Self::default()
}
}
pub trait CanisterA: Canister {
#[state_getter]
fn state(&self) -> Rc<RefCell<StateA>>;
#[query(trait = true)]
fn get_counter(&self) -> u32 {
self.state().borrow().counter
}
#[update(trait = true)]
fn inc_counter(&mut self, value: u32) {
RefCell::borrow_mut(&self.state()).counter += value;
}
#[query(trait = true)]
fn caller(&self) -> Principal {
ic_exports::ic_kit::ic::caller()
}
#[query(trait = true)]
fn id(&self) -> Principal {
ic_exports::ic_kit::ic::id()
}
}
generate_exports!(CanisterA, CanisterAImpl);
#[cfg(test)]
mod tests {
use super::*;
use ic_canister::{canister_call, Canister};
use ic_exports::ic_kit::MockContext;
#[test]
fn independent_states() {
let ctx = MockContext::new().inject();
let mut canister1 = CanisterAImpl::init_instance();
let mut canister2 = CanisterAImpl::init_instance();
ctx.update_id(canister1.principal());
canister1.inc_counter(3);
ctx.update_id(canister2.principal());
canister2.inc_counter(5);
ctx.update_id(canister1.principal());
assert_eq!(canister1.get_counter(), 3);
ctx.update_id(canister2.principal());
assert_eq!(canister2.get_counter(), 5);
ctx.update_id(canister1.principal());
assert_eq!(
CanisterAImpl::from_principal(canister1.principal()).get_counter(),
3
);
ctx.update_id(canister2.principal());
assert_eq!(
CanisterAImpl::from_principal(canister2.principal()).get_counter(),
5
);
}
#[tokio::test]
async fn execution_context_with_canister_call() {
let id = ic_exports::ic_kit::mock_principals::alice();
let caller = ic_exports::ic_kit::mock_principals::bob();
MockContext::new().with_id(id).with_caller(caller).inject();
let canister = CanisterAImpl::init_instance();
assert_eq!(
canister_call!(canister.caller(), Principal).await.unwrap(),
id,
"wrong caller"
);
assert_eq!(
canister_call!(canister.id(), Principal).await.unwrap(),
canister.principal(),
"wrong canister id"
);
assert_eq!(ic_exports::ic_kit::ic::id(), id);
assert_eq!(ic_exports::ic_kit::ic::caller(), caller);
}
}