cw_migratable_contract_std/
test_execute.rs1#[cfg(test)]
2mod tests {
3 use cosmwasm_std::testing::mock_dependencies;
4 use cosmwasm_std::{
5 to_binary, Addr, Binary, ContractInfo, ReplyOn, StdError, StdResult, SubMsg, WasmMsg,
6 };
7
8 use crate::execute::{
9 create_broadcast_migration_complete_notification_msgs,
10 register_to_notify_on_migration_complete, update_migrated_subscriber,
11 };
12 use crate::msg::MigrationListenerExecuteMsg::MigrationCompleteNotification;
13 use crate::state::{
14 canonicalize, MIGRATION_COMPLETE_EVENT_SUBSCRIBERS,
15 REMAINING_MIGRATION_COMPLETE_EVENT_SUB_SLOTS,
16 };
17
18 #[test]
19 fn register_to_notify_on_migration_complete_fails_with_when_no_slots_available() -> StdResult<()>
20 {
21 let mut deps = mock_dependencies();
22 let receiver_address = "addr".to_string();
23 let receiver_code_hash = "code_hash".to_string();
24 REMAINING_MIGRATION_COMPLETE_EVENT_SUB_SLOTS.save(deps.as_mut().storage, &1)?;
25 let res = register_to_notify_on_migration_complete(
26 deps.as_mut(),
27 receiver_address.clone(),
28 receiver_code_hash.clone(),
29 );
30 assert!(res.is_ok(), "execute failed");
31 let res = register_to_notify_on_migration_complete(
32 deps.as_mut(),
33 receiver_address,
34 receiver_code_hash,
35 );
36 assert!(res.is_err(), "execute didn't fail");
37 assert_eq!(
38 res.err().unwrap(),
39 StdError::generic_err("No migration complete notification slots available")
40 );
41 Ok(())
42 }
43
44 #[test]
45 fn register_to_notify_on_migration_complete_saves_contract() -> StdResult<()> {
46 let mut deps = mock_dependencies();
47 let receiver = &ContractInfo {
48 address: Addr::unchecked("receiver_addr"),
49 code_hash: "code_hash".to_string(),
50 };
51 register_to_notify_on_migration_complete(
52 deps.as_mut(),
53 receiver.address.to_string(),
54 receiver.code_hash.to_string(),
55 )?;
56 let saved_contract = MIGRATION_COMPLETE_EVENT_SUBSCRIBERS.load(deps.as_ref().storage)?;
57 assert_eq!(
58 vec![canonicalize(deps.as_ref().api, receiver)?],
59 saved_contract
60 );
61 Ok(())
62 }
63
64 #[test]
65 fn update_migrated_subscriber_updates_storage() -> StdResult<()> {
66 let mut deps = mock_dependencies();
67 let subscriber_contract = canonicalize(
68 deps.as_ref().api,
69 &ContractInfo {
70 address: Addr::unchecked("subscriber_addr"),
71 code_hash: "subscriber_code_hash".to_string(),
72 },
73 )?;
74 let migrated_subscriber_contract = canonicalize(
75 deps.as_ref().api,
76 &ContractInfo {
77 address: Addr::unchecked("migrated_subscriber_addr"),
78 code_hash: "migrated_subscriber_code_hash".to_string(),
79 },
80 )?;
81 MIGRATION_COMPLETE_EVENT_SUBSCRIBERS
82 .save(deps.as_mut().storage, &vec![subscriber_contract.clone()])?;
83
84 update_migrated_subscriber(
85 deps.as_mut().storage,
86 &subscriber_contract.address,
87 &migrated_subscriber_contract,
88 )?;
89
90 assert_eq!(
91 vec![migrated_subscriber_contract],
92 MIGRATION_COMPLETE_EVENT_SUBSCRIBERS.load(deps.as_ref().storage)?
93 );
94
95 Ok(())
96 }
97
98 #[test]
99 fn update_migrated_subscriber_does_not_update_storage_when_sender_does_not_match(
100 ) -> StdResult<()> {
101 let mut deps = mock_dependencies();
102 let subscriber_contract = canonicalize(
103 deps.as_ref().api,
104 &ContractInfo {
105 address: Addr::unchecked("subscriber_addr"),
106 code_hash: "subscriber_code_hash".to_string(),
107 },
108 )?;
109 let random_contract = canonicalize(
110 deps.as_ref().api,
111 &ContractInfo {
112 address: Addr::unchecked("random_addr"),
113 code_hash: "random_code_hash".to_string(),
114 },
115 )?;
116 let migrated_subscriber_contract = canonicalize(
117 deps.as_ref().api,
118 &ContractInfo {
119 address: Addr::unchecked("migrated_subscriber_addr"),
120 code_hash: "migrated_subscriber_code_hash".to_string(),
121 },
122 )?;
123 MIGRATION_COMPLETE_EVENT_SUBSCRIBERS
124 .save(deps.as_mut().storage, &vec![subscriber_contract.clone()])?;
125
126 update_migrated_subscriber(
127 deps.as_mut().storage,
128 &random_contract.address,
129 &migrated_subscriber_contract,
130 )?;
131
132 assert_eq!(
133 vec![subscriber_contract],
134 MIGRATION_COMPLETE_EVENT_SUBSCRIBERS.load(deps.as_ref().storage)?
135 );
136
137 Ok(())
138 }
139
140 #[test]
141 fn broadcast_migration_complete_notification_creates_submsgs_for_all_specified_addresses(
142 ) -> StdResult<()> {
143 let deps = mock_dependencies();
144 let migrated_to = &ContractInfo {
145 address: Addr::unchecked("contract_addr"),
146 code_hash: "contract_v2_code_hash".to_string(),
147 };
148
149 let broadcast_to_contracts = vec![
150 ContractInfo {
151 address: Addr::unchecked("listener_a"),
152 code_hash: "listener_code_hash".to_string(),
153 },
154 ContractInfo {
155 address: Addr::unchecked("listener_b"),
156 code_hash: "listener_code_hash".to_string(),
157 },
158 ];
159 let reply_on = ReplyOn::Error;
160 let reply_id = 11;
161 let messages = create_broadcast_migration_complete_notification_msgs(
162 deps.as_ref(),
163 reply_on.clone(),
164 reply_id,
165 migrated_to,
166 broadcast_to_contracts.clone(),
167 Some(Binary::from(b"payload")),
168 )?;
169
170 assert_eq!(
171 broadcast_to_contracts
172 .into_iter()
173 .map(|contract| {
174 SubMsg::reply_on_error(
175 WasmMsg::Execute {
176 contract_addr: contract.address.to_string(),
177 code_hash: "listener_code_hash".to_string(),
178 msg: to_binary(&MigrationCompleteNotification {
179 to: migrated_to.clone(),
180 data: Some(Binary::from(b"payload")),
181 })
182 .unwrap(),
183 funds: vec![],
184 },
185 reply_id,
186 )
187 })
188 .collect::<Vec<SubMsg>>(),
189 messages
190 );
191
192 Ok(())
193 }
194}