cw_migratable_contract_std/
test_execute.rs

1#[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}