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

chore: add unit test coverage for icon light client #851

Merged
merged 1 commit into from
Mar 28, 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
132 changes: 129 additions & 3 deletions contracts/cosmwasm-vm/cw-icon-light-client/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -539,15 +539,15 @@ mod tests {
use common::icon::icon::types::v1::{BtpHeader, SignedHeader};
use cosmwasm_std::{
testing::{mock_dependencies, mock_env, mock_info, MockApi, MockQuerier, MockStorage},
Addr, OwnedDeps, Response,
to_binary, Addr, OwnedDeps, Response,
};
use cw2::get_contract_version;
use cw_common::raw_types::Any;
use cw_common::{client_msg::QueryMsg, raw_types::Any};
use test_utils::{get_test_headers, get_test_signed_headers, to_attribute_map};

use crate::{
constants::{CLIENT_STATE_HASH, CONSENSUS_STATE_HASH},
contract::to_height_u64,
contract::{ensure_owner, query, to_height_u64},
query_handler::QueryHandler,
ContractError,
};
Expand Down Expand Up @@ -878,4 +878,130 @@ mod tests {
Err(ContractError::HeightAlreadyUpdated { height: 82873 })
);
}

#[test]
fn test_query_client_state() {
let start_header = &get_test_headers()[0];
let client_id = "test_client".to_string();
let deps = init_client(&client_id, start_header, None);

let msg = QueryMsg::GetClientState {
client_id: client_id.clone(),
};
let res = query(deps.as_ref(), mock_env(), msg).unwrap();

let state =
QueryHandler::get_client_state_any(deps.as_ref().storage, client_id.as_str()).unwrap();
assert_eq!(res, to_binary(&state).unwrap());
}

#[test]
fn test_query_consensus_state() {
let start_header = &get_test_headers()[0];
let client_id = "test_client".to_string();
let deps = init_client(&client_id, start_header, None);

let msg = QueryMsg::GetConsensusState {
client_id: client_id.clone(),
height: start_header.main_height,
};
let res = query(deps.as_ref(), mock_env(), msg).unwrap();

let state = QueryHandler::get_consensus_state_any(
deps.as_ref().storage,
client_id.as_str(),
start_header.main_height,
)
.unwrap();
assert_eq!(res, to_binary(&state).unwrap());
}

#[test]
fn test_query_latest_height() {
let start_header = &get_test_headers()[0];
let client_id = "test_client".to_string();
let deps = init_client(&client_id, start_header, None);

let msg = QueryMsg::GetLatestHeight {
client_id: client_id.clone(),
};
let res = query(deps.as_ref(), mock_env(), msg).unwrap();

let height =
QueryHandler::get_latest_height(deps.as_ref().storage, client_id.as_str()).unwrap();
assert_eq!(res, to_binary(&height).unwrap());
}

#[test]
fn test_query_latest_consensus_state() {
let start_header = &get_test_headers()[0];
let client_id = "test_client".to_string();
let deps = init_client(&client_id, start_header, None);

let msg = QueryMsg::GetLatestConsensusState {
client_id: client_id.clone(),
};
let res = query(deps.as_ref(), mock_env(), msg).unwrap();

let state =
QueryHandler::get_latest_consensus_state(deps.as_ref().storage, client_id.as_str())
.unwrap();
assert_eq!(res, to_binary(&state).unwrap());
}

#[test]
#[should_panic(expected = "Std(NotFound { kind: \"alloc::vec::Vec<u8>")]
fn test_query_latest_consensus_state_fail() {
let start_header = &get_test_headers()[0];
let client_id = "test_client".to_string();
let deps = init_client(&client_id, start_header, None);

let msg = QueryMsg::GetLatestConsensusState {
client_id: "another_client".to_string(),
};
query(deps.as_ref(), mock_env(), msg).unwrap();
}

#[test]
fn test_query_previous_consensus_state() {
let start_header = &get_test_headers()[0];
let client_id = "test_client".to_string();
let deps = init_client(&client_id, start_header, None);

let msg = QueryMsg::GetPreviousConsensusState {
client_id: client_id.clone(),
height: start_header.main_height,
};
let res = query(deps.as_ref(), mock_env(), msg).unwrap();

let state = QueryHandler::get_previous_consensus(
deps.as_ref().storage,
start_header.main_height,
client_id,
)
.unwrap();
assert_eq!(res, to_binary(&state).unwrap());
}

#[test]
fn test_ensure_owner() {
let start_header = &get_test_headers()[0];
let client_id = "test_client".to_string();
let deps = init_client(&client_id, start_header, None);
let info = mock_info(SENDER, &[]);

let res = ensure_owner(deps.as_ref(), &info);
assert!(res.is_ok())
}

#[test]
#[should_panic(expected = "Unauthorized")]
fn test_ensure_owner_unauthorized() {
let start_header = &get_test_headers()[0];
let client_id = "test_client".to_string();
let deps = init_client(&client_id, start_header, None);
let info = mock_info("not_owner", &[]);

ensure_owner(deps.as_ref(), &info).unwrap()
}
}
66 changes: 64 additions & 2 deletions contracts/cosmwasm-vm/cw-icon-light-client/src/light_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,11 @@ impl<'a> IconClient<'a> {
.get_processed_block_at_height(client_id, height)?;
let current_time = self.context.get_current_block_time();
let current_height = self.context.get_current_block_height();
if !current_time >= (processed_time + delay_time) {
if current_time < (processed_time + delay_time) {
return Err(ContractError::NotEnoughtTimeElapsed);
}

if !current_height >= (processed_height + delay_block) {
if current_height < (processed_height + delay_block) {
return Err(ContractError::NotEnoughtBlocksElapsed);
}

Expand Down Expand Up @@ -223,3 +223,65 @@ impl ILightClient for IconClient<'_> {
})
}
}

#[cfg(test)]
mod test {
use super::*;
use cosmwasm_std::testing::{mock_dependencies, mock_env};
use test_utils::get_test_headers;

#[test]
fn test_validate_delay_args() {
let mut deps = mock_dependencies();
let ctx = CwContext::new(deps.as_mut(), mock_env());
let mut icon_client = IconClient::new(ctx);

let height = 12_345;
let client_id = "icon_client";

icon_client
.context
.insert_blocknumber_at_height(client_id, height)
.unwrap();

icon_client
.context
.insert_timestamp_at_height(client_id, height)
.unwrap();

let res = icon_client
.validate_delay_args(client_id, height, 0, 0)
.unwrap();
assert_eq!(res, ());

let err = icon_client
.validate_delay_args(client_id, height, 1, 0)
.unwrap_err();
assert_eq!(err, ContractError::NotEnoughtTimeElapsed);

let err = icon_client
.validate_delay_args(client_id, height, 0, 1)
.unwrap_err();
assert_eq!(err, ContractError::NotEnoughtBlocksElapsed)
}

#[test]
#[should_panic(expected = "InSuffcientQuorum")]
fn check_block_proof_with_empty_validators() {
let header = &get_test_headers()[0];
let mut deps = mock_dependencies();
let ctx = CwContext::new(deps.as_mut(), mock_env());
let mut icon_client = IconClient::new(ctx);

let client_id = "icon_client";
let client_state = ClientState::default();
icon_client
.context
.insert_client_state(client_id, client_state)
.unwrap();

icon_client
.check_block_proof(client_id, header, &Vec::new(), &Vec::new())
.unwrap();
}
}
142 changes: 142 additions & 0 deletions contracts/cosmwasm-vm/cw-icon-light-client/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,18 @@ mod tests {
assert_eq!(address, hex::encode(result.unwrap()));
}

#[test]
fn test_recover_signer_for_none_value() {
let mut deps = mock_dependencies();
let context = CwContext::new(deps.as_mut(), mock_env());

let msg = keccak256(b"test message");
let signature = hex!("c8b2b5eeb7b5462ce6d3bdf1648cd8eae2");

let result = context.recover_signer(msg.as_slice(), &signature);
assert!(result.is_none());
}

#[test]
fn test_cwcontext_recover_signer_relay_data() {
let mut deps = mock_dependencies();
Expand Down Expand Up @@ -491,4 +503,134 @@ mod tests {
assert_eq!(mock_env().block.height, loaded);
Ok(())
}

#[test]
fn test_ensure_owner() {
let mut deps = mock_dependencies();
let config = Config::default();
let mut contract = CwContext::new(deps.as_mut(), mock_env());

contract.insert_config(&config).unwrap();

let res = contract.ensure_owner(Addr::unchecked("test"));
assert!(res.is_ok())
}

#[test]
#[should_panic(expected = "Unauthorized")]
fn test_ensure_owner_unauthorized() {
let mut deps = mock_dependencies();
let config = Config::default();
let mut contract = CwContext::new(deps.as_mut(), mock_env());

contract.insert_config(&config).unwrap();

contract
.ensure_owner(Addr::unchecked("regular_user"))
.unwrap()
}

#[test]
#[should_panic(expected = "Unauthorized")]
fn test_ensure_host_unauthorized() {
let mut deps = mock_dependencies();
let config = Config::default();
let mut contract = CwContext::new(deps.as_mut(), mock_env());

contract.insert_config(&config).unwrap();

contract
.ensure_ibc_host(Addr::unchecked("regular_host"))
.unwrap()
}

#[test]
fn test_get_current_block_time() {
let mut deps = mock_dependencies();
let contract = CwContext::new(deps.as_mut(), mock_env());

let res = contract.get_current_block_time();
assert_eq!(res, contract.env.block.time.nanos());
}

#[test]
fn test_get_current_block_height() {
let mut deps = mock_dependencies();
let contract = CwContext::new(deps.as_mut(), mock_env());

let res = contract.get_current_block_height();
assert_eq!(res, contract.env.block.height);
}

#[test]
fn test_get_processed_time_at_height() {
let mut deps = mock_dependencies();
let mut contract = CwContext::new(deps.as_mut(), mock_env());

let height = 2;
let client_id = "test_client";

contract
.insert_timestamp_at_height(client_id, height)
.unwrap();

let res = contract
.get_processed_time_at_height(client_id, height)
.unwrap();

assert_eq!(res, contract.env.block.time.nanos())
}

#[test]
#[should_panic(expected = "ProcessedTimeNotFound")]
fn fail_test_get_processed_time_at_height() {
let mut deps = mock_dependencies();
let mut contract = CwContext::new(deps.as_mut(), mock_env());

let height = 2;
let client_id = "test_client";

contract
.insert_timestamp_at_height(client_id, height)
.unwrap();

contract.get_processed_time_at_height(client_id, 3).unwrap();
}

#[test]
fn test_get_processed_block_number_at_height() {
let mut deps = mock_dependencies();
let mut contract = CwContext::new(deps.as_mut(), mock_env());

let height = 2;
let client_id = "test_client";

contract
.insert_blocknumber_at_height(client_id, height)
.unwrap();

let res = contract
.get_processed_block_at_height(client_id, height)
.unwrap();

assert_eq!(res, contract.env.block.height)
}

#[test]
#[should_panic(expected = "ProcessedHeightNotFound")]
fn fail_test_get_processed_block_number_at_height() {
let mut deps = mock_dependencies();
let mut contract = CwContext::new(deps.as_mut(), mock_env());

let height = 2;
let client_id = "test_client";

contract
.insert_blocknumber_at_height(client_id, height)
.unwrap();

contract
.get_processed_block_at_height(client_id, 3)
.unwrap();
}
}
Loading