Skip to content

Commit

Permalink
Integration tests for receiving packets
Browse files Browse the repository at this point in the history
  • Loading branch information
ethanfrey committed Jan 14, 2021
1 parent 31aa9ba commit b87385f
Show file tree
Hide file tree
Showing 2 changed files with 136 additions and 12 deletions.
6 changes: 1 addition & 5 deletions contracts/ibc-reflect/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -448,10 +448,6 @@ mod tests {
// receive a packet for an unregistered channel returns app-level error (not Result::Err)
let packet = mock_ibc_packet(channel_id, &ibc_msg);
let res = ibc_packet_receive(deps.as_mut(), mock_env(), packet.clone()).unwrap();
println!(
"{}",
String::from_utf8(res.acknowledgement.0.clone()).unwrap()
);

// TODO: blocked on serde-json-wasm fix
// see: https://github.com/CosmWasm/serde-json-wasm/issues/27
Expand All @@ -471,7 +467,7 @@ mod tests {
assert_eq!(account, contract_addr.as_str());
assert_eq!(0, send.len());
// parse the message - should callback with proper channel_id
let rmsg: ReflectHandleMsg = from_binary(&msg).unwrap();
let rmsg: ReflectHandleMsg = from_slice(&msg).unwrap();
assert_eq!(
rmsg,
ReflectHandleMsg::ReflectMsg {
Expand Down
142 changes: 135 additions & 7 deletions contracts/ibc-reflect/tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,22 @@
//! 4. Anywhere you see query(&deps, ...) you must replace it with query(&mut deps, ...)
use cosmwasm_std::{
ContractResult, CosmosMsg, HandleResponse, HumanAddr, IbcBasicResponse, IbcChannel,
IbcEndpoint, IbcOrder, InitResponse, WasmMsg,
coins, BankMsg, ContractResult, CosmosMsg, HandleResponse, HumanAddr, IbcBasicResponse,
IbcChannel, IbcEndpoint, IbcOrder, IbcPacket, IbcReceiveResponse, IbcTimeoutHeight,
InitResponse, WasmMsg,
};
use cosmwasm_vm::testing::{
handle, ibc_channel_connect, ibc_channel_open, init, mock_env, mock_info, mock_instance, query,
MockApi, MockQuerier, MockStorage,
handle, ibc_channel_connect, ibc_channel_open, ibc_packet_receive, init, mock_env, mock_info,
mock_instance, query, MockApi, MockQuerier, MockStorage,
};
use cosmwasm_vm::{from_slice, Instance};
use cosmwasm_vm::{from_slice, to_vec, Instance};

use ibc_reflect::contract::IBC_VERSION;
use ibc_reflect::msg::{
AccountInfo, AccountResponse, HandleMsg, InitMsg, ListAccountsResponse, QueryMsg,
ReflectInitMsg,
AccountInfo, AccountResponse, AcknowledgementMsg, HandleMsg, InitMsg, ListAccountsResponse,
PacketMsg, QueryMsg, ReflectHandleMsg, ReflectInitMsg,
};
use serde::Serialize;

// This line will test the output of cargo wasm
static WASM: &[u8] = include_bytes!("../target/wasm32-unknown-unknown/release/ibc_reflect.wasm");
Expand Down Expand Up @@ -75,6 +77,55 @@ fn mock_channel(order: IbcOrder, version: &str) -> IbcChannel {
}
}

// this provides a minimal packet around custom data, which can be modified to set certain fields
// TODO: something similar should be a helper in ibc.rs
fn mock_ibc_packet<T: Serialize>(channel_id: &str, data: &T) -> IbcPacket {
IbcPacket {
data: to_vec(data).unwrap().into(),
src: IbcEndpoint {
port_id: "their-port".to_string(),
channel_id: "channel-1234".to_string(),
},
dest: IbcEndpoint {
port_id: "our-port".to_string(),
channel_id: channel_id.into(),
},
sequence: 27,
timeout_height: IbcTimeoutHeight {
revision_number: 1,
timeout_height: 12345678,
},
timeout_timestamp: 0,
version: 1,
}
}

// connect will run through the entire handshake to set up a proper connect and
// save the account (tested in detail in `proper_handshake_flow`)
fn connect<T: Into<HumanAddr>>(
deps: &mut Instance<MockApi, MockStorage, MockQuerier>,
channel_id: &str,
account: T,
) {
let account = account.into();
// first we try to open with a valid handshake
let mut valid_handshake = mock_channel(IbcOrder::Ordered, IBC_VERSION);
valid_handshake.endpoint.channel_id = channel_id.into();
ibc_channel_open(deps, mock_env(), valid_handshake.clone()).unwrap();

// then we connect (with counter-party version set)
valid_handshake.counterparty_version = Some(IBC_VERSION.to_string());
let _: IbcBasicResponse = ibc_channel_connect(deps, mock_env(), valid_handshake).unwrap();

// which creates a reflect account. here we get the callback
let handle_msg = HandleMsg::InitCallback {
id: channel_id.into(),
contract_addr: account.clone(),
};
let info = mock_info(account, &[]);
let _: HandleResponse = handle(deps, mock_env(), info, handle_msg).unwrap();
}

#[test]
fn init_works() {
let mut deps = mock_instance(WASM, &[]);
Expand Down Expand Up @@ -172,3 +223,80 @@ fn proper_handshake_flow() {
let res: AccountResponse = from_slice(&raw).unwrap();
assert_eq!(res.account.unwrap(), HumanAddr::from(REFLECT_ADDR));
}

#[test]
fn handle_packet() {
let mut deps = setup();

let channel_id: &str = "channel-123";
let account: &str = "acct-123";

// receive a packet for an unregistered channel returns app-level error (not Result::Err)
let ibc_msg = PacketMsg {
msgs: vec![BankMsg::Send {
to_address: "my-friend".into(),
amount: coins(123456789, "uatom"),
}
.into()],
};
let packet = mock_ibc_packet(channel_id, &ibc_msg);
let res: IbcReceiveResponse =
ibc_packet_receive(&mut deps, mock_env(), packet.clone()).unwrap();
// we didn't dispatch anything
assert_eq!(0, res.messages.len());
// acknowledgement is an error
let ack: AcknowledgementMsg = from_slice(&res.acknowledgement).unwrap();
assert_eq!(ack.unwrap_err(), "invalid packet");

// register the channel
connect(&mut deps, channel_id, account);

// receive a packet for an unregistered channel returns app-level error (not Result::Err)
let packet = mock_ibc_packet(channel_id, &ibc_msg);
let res: IbcReceiveResponse =
ibc_packet_receive(&mut deps, mock_env(), packet.clone()).unwrap();
println!(
"{}",
String::from_utf8(res.acknowledgement.0.clone()).unwrap()
);

// assert app-level success
let ack: AcknowledgementMsg = from_slice(&res.acknowledgement).unwrap();
ack.unwrap();

// and we dispatch the BankMsg
assert_eq!(1, res.messages.len());
// parse the output, ensuring it matches
if let CosmosMsg::Wasm(WasmMsg::Execute {
contract_addr,
msg,
send,
}) = &res.messages[0]
{
assert_eq!(account, contract_addr.as_str());
assert_eq!(0, send.len());
// parse the message - should callback with proper channel_id
let rmsg: ReflectHandleMsg = from_slice(&msg).unwrap();
assert_eq!(
rmsg,
ReflectHandleMsg::ReflectMsg {
msgs: ibc_msg.msgs.clone()
}
);
} else {
panic!("invalid return message: {:?}", res.messages[0]);
}

// invalid packet format on registered channel also returns app-level error
let bad_data = InitMsg {
reflect_code_id: 12345,
};
let packet = mock_ibc_packet(channel_id, &bad_data);
let res: IbcReceiveResponse =
ibc_packet_receive(&mut deps, mock_env(), packet.clone()).unwrap();
// we didn't dispatch anything
assert_eq!(0, res.messages.len());
// acknowledgement is an error
let ack: AcknowledgementMsg = from_slice(&res.acknowledgement).unwrap();
assert_eq!(ack.unwrap_err(), "invalid packet");
}

0 comments on commit b87385f

Please sign in to comment.