Skip to content

Commit 545da5c

Browse files
authored
chore: add unit test coverage for icon light client (#851)
1 parent 5bd6c10 commit 545da5c

File tree

3 files changed

+335
-5
lines changed

3 files changed

+335
-5
lines changed

contracts/cosmwasm-vm/cw-icon-light-client/src/contract.rs

+129-3
Original file line numberDiff line numberDiff line change
@@ -539,15 +539,15 @@ mod tests {
539539
use common::icon::icon::types::v1::{BtpHeader, SignedHeader};
540540
use cosmwasm_std::{
541541
testing::{mock_dependencies, mock_env, mock_info, MockApi, MockQuerier, MockStorage},
542-
Addr, OwnedDeps, Response,
542+
to_binary, Addr, OwnedDeps, Response,
543543
};
544544
use cw2::get_contract_version;
545-
use cw_common::raw_types::Any;
545+
use cw_common::{client_msg::QueryMsg, raw_types::Any};
546546
use test_utils::{get_test_headers, get_test_signed_headers, to_attribute_map};
547547

548548
use crate::{
549549
constants::{CLIENT_STATE_HASH, CONSENSUS_STATE_HASH},
550-
contract::to_height_u64,
550+
contract::{ensure_owner, query, to_height_u64},
551551
query_handler::QueryHandler,
552552
ContractError,
553553
};
@@ -878,4 +878,130 @@ mod tests {
878878
Err(ContractError::HeightAlreadyUpdated { height: 82873 })
879879
);
880880
}
881+
882+
#[test]
883+
fn test_query_client_state() {
884+
let start_header = &get_test_headers()[0];
885+
let client_id = "test_client".to_string();
886+
let deps = init_client(&client_id, start_header, None);
887+
888+
let msg = QueryMsg::GetClientState {
889+
client_id: client_id.clone(),
890+
};
891+
let res = query(deps.as_ref(), mock_env(), msg).unwrap();
892+
893+
let state =
894+
QueryHandler::get_client_state_any(deps.as_ref().storage, client_id.as_str()).unwrap();
895+
assert_eq!(res, to_binary(&state).unwrap());
896+
}
897+
898+
#[test]
899+
fn test_query_consensus_state() {
900+
let start_header = &get_test_headers()[0];
901+
let client_id = "test_client".to_string();
902+
let deps = init_client(&client_id, start_header, None);
903+
904+
let msg = QueryMsg::GetConsensusState {
905+
client_id: client_id.clone(),
906+
height: start_header.main_height,
907+
};
908+
let res = query(deps.as_ref(), mock_env(), msg).unwrap();
909+
910+
let state = QueryHandler::get_consensus_state_any(
911+
deps.as_ref().storage,
912+
client_id.as_str(),
913+
start_header.main_height,
914+
)
915+
.unwrap();
916+
assert_eq!(res, to_binary(&state).unwrap());
917+
}
918+
919+
#[test]
920+
fn test_query_latest_height() {
921+
let start_header = &get_test_headers()[0];
922+
let client_id = "test_client".to_string();
923+
let deps = init_client(&client_id, start_header, None);
924+
925+
let msg = QueryMsg::GetLatestHeight {
926+
client_id: client_id.clone(),
927+
};
928+
let res = query(deps.as_ref(), mock_env(), msg).unwrap();
929+
930+
let height =
931+
QueryHandler::get_latest_height(deps.as_ref().storage, client_id.as_str()).unwrap();
932+
assert_eq!(res, to_binary(&height).unwrap());
933+
}
934+
935+
#[test]
936+
fn test_query_latest_consensus_state() {
937+
let start_header = &get_test_headers()[0];
938+
let client_id = "test_client".to_string();
939+
let deps = init_client(&client_id, start_header, None);
940+
941+
let msg = QueryMsg::GetLatestConsensusState {
942+
client_id: client_id.clone(),
943+
};
944+
let res = query(deps.as_ref(), mock_env(), msg).unwrap();
945+
946+
let state =
947+
QueryHandler::get_latest_consensus_state(deps.as_ref().storage, client_id.as_str())
948+
.unwrap();
949+
assert_eq!(res, to_binary(&state).unwrap());
950+
}
951+
952+
#[test]
953+
#[should_panic(expected = "Std(NotFound { kind: \"alloc::vec::Vec<u8>")]
954+
fn test_query_latest_consensus_state_fail() {
955+
let start_header = &get_test_headers()[0];
956+
let client_id = "test_client".to_string();
957+
let deps = init_client(&client_id, start_header, None);
958+
959+
let msg = QueryMsg::GetLatestConsensusState {
960+
client_id: "another_client".to_string(),
961+
};
962+
query(deps.as_ref(), mock_env(), msg).unwrap();
963+
}
964+
965+
#[test]
966+
fn test_query_previous_consensus_state() {
967+
let start_header = &get_test_headers()[0];
968+
let client_id = "test_client".to_string();
969+
let deps = init_client(&client_id, start_header, None);
970+
971+
let msg = QueryMsg::GetPreviousConsensusState {
972+
client_id: client_id.clone(),
973+
height: start_header.main_height,
974+
};
975+
let res = query(deps.as_ref(), mock_env(), msg).unwrap();
976+
977+
let state = QueryHandler::get_previous_consensus(
978+
deps.as_ref().storage,
979+
start_header.main_height,
980+
client_id,
981+
)
982+
.unwrap();
983+
assert_eq!(res, to_binary(&state).unwrap());
984+
}
985+
986+
#[test]
987+
fn test_ensure_owner() {
988+
let start_header = &get_test_headers()[0];
989+
let client_id = "test_client".to_string();
990+
let deps = init_client(&client_id, start_header, None);
991+
let info = mock_info(SENDER, &[]);
992+
993+
let res = ensure_owner(deps.as_ref(), &info);
994+
assert!(res.is_ok())
995+
}
996+
997+
#[test]
998+
#[should_panic(expected = "Unauthorized")]
999+
fn test_ensure_owner_unauthorized() {
1000+
let start_header = &get_test_headers()[0];
1001+
let client_id = "test_client".to_string();
1002+
let deps = init_client(&client_id, start_header, None);
1003+
let info = mock_info("not_owner", &[]);
1004+
1005+
ensure_owner(deps.as_ref(), &info).unwrap()
1006+
}
8811007
}

contracts/cosmwasm-vm/cw-icon-light-client/src/light_client.rs

+64-2
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,11 @@ impl<'a> IconClient<'a> {
8585
.get_processed_block_at_height(client_id, height)?;
8686
let current_time = self.context.get_current_block_time();
8787
let current_height = self.context.get_current_block_height();
88-
if !current_time >= (processed_time + delay_time) {
88+
if current_time < (processed_time + delay_time) {
8989
return Err(ContractError::NotEnoughtTimeElapsed);
9090
}
9191

92-
if !current_height >= (processed_height + delay_block) {
92+
if current_height < (processed_height + delay_block) {
9393
return Err(ContractError::NotEnoughtBlocksElapsed);
9494
}
9595

@@ -223,3 +223,65 @@ impl ILightClient for IconClient<'_> {
223223
})
224224
}
225225
}
226+
227+
#[cfg(test)]
228+
mod test {
229+
use super::*;
230+
use cosmwasm_std::testing::{mock_dependencies, mock_env};
231+
use test_utils::get_test_headers;
232+
233+
#[test]
234+
fn test_validate_delay_args() {
235+
let mut deps = mock_dependencies();
236+
let ctx = CwContext::new(deps.as_mut(), mock_env());
237+
let mut icon_client = IconClient::new(ctx);
238+
239+
let height = 12_345;
240+
let client_id = "icon_client";
241+
242+
icon_client
243+
.context
244+
.insert_blocknumber_at_height(client_id, height)
245+
.unwrap();
246+
247+
icon_client
248+
.context
249+
.insert_timestamp_at_height(client_id, height)
250+
.unwrap();
251+
252+
let res = icon_client
253+
.validate_delay_args(client_id, height, 0, 0)
254+
.unwrap();
255+
assert_eq!(res, ());
256+
257+
let err = icon_client
258+
.validate_delay_args(client_id, height, 1, 0)
259+
.unwrap_err();
260+
assert_eq!(err, ContractError::NotEnoughtTimeElapsed);
261+
262+
let err = icon_client
263+
.validate_delay_args(client_id, height, 0, 1)
264+
.unwrap_err();
265+
assert_eq!(err, ContractError::NotEnoughtBlocksElapsed)
266+
}
267+
268+
#[test]
269+
#[should_panic(expected = "InSuffcientQuorum")]
270+
fn check_block_proof_with_empty_validators() {
271+
let header = &get_test_headers()[0];
272+
let mut deps = mock_dependencies();
273+
let ctx = CwContext::new(deps.as_mut(), mock_env());
274+
let mut icon_client = IconClient::new(ctx);
275+
276+
let client_id = "icon_client";
277+
let client_state = ClientState::default();
278+
icon_client
279+
.context
280+
.insert_client_state(client_id, client_state)
281+
.unwrap();
282+
283+
icon_client
284+
.check_block_proof(client_id, header, &Vec::new(), &Vec::new())
285+
.unwrap();
286+
}
287+
}

contracts/cosmwasm-vm/cw-icon-light-client/src/state.rs

+142
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,18 @@ mod tests {
369369
assert_eq!(address, hex::encode(result.unwrap()));
370370
}
371371

372+
#[test]
373+
fn test_recover_signer_for_none_value() {
374+
let mut deps = mock_dependencies();
375+
let context = CwContext::new(deps.as_mut(), mock_env());
376+
377+
let msg = keccak256(b"test message");
378+
let signature = hex!("c8b2b5eeb7b5462ce6d3bdf1648cd8eae2");
379+
380+
let result = context.recover_signer(msg.as_slice(), &signature);
381+
assert!(result.is_none());
382+
}
383+
372384
#[test]
373385
fn test_cwcontext_recover_signer_relay_data() {
374386
let mut deps = mock_dependencies();
@@ -491,4 +503,134 @@ mod tests {
491503
assert_eq!(mock_env().block.height, loaded);
492504
Ok(())
493505
}
506+
507+
#[test]
508+
fn test_ensure_owner() {
509+
let mut deps = mock_dependencies();
510+
let config = Config::default();
511+
let mut contract = CwContext::new(deps.as_mut(), mock_env());
512+
513+
contract.insert_config(&config).unwrap();
514+
515+
let res = contract.ensure_owner(Addr::unchecked("test"));
516+
assert!(res.is_ok())
517+
}
518+
519+
#[test]
520+
#[should_panic(expected = "Unauthorized")]
521+
fn test_ensure_owner_unauthorized() {
522+
let mut deps = mock_dependencies();
523+
let config = Config::default();
524+
let mut contract = CwContext::new(deps.as_mut(), mock_env());
525+
526+
contract.insert_config(&config).unwrap();
527+
528+
contract
529+
.ensure_owner(Addr::unchecked("regular_user"))
530+
.unwrap()
531+
}
532+
533+
#[test]
534+
#[should_panic(expected = "Unauthorized")]
535+
fn test_ensure_host_unauthorized() {
536+
let mut deps = mock_dependencies();
537+
let config = Config::default();
538+
let mut contract = CwContext::new(deps.as_mut(), mock_env());
539+
540+
contract.insert_config(&config).unwrap();
541+
542+
contract
543+
.ensure_ibc_host(Addr::unchecked("regular_host"))
544+
.unwrap()
545+
}
546+
547+
#[test]
548+
fn test_get_current_block_time() {
549+
let mut deps = mock_dependencies();
550+
let contract = CwContext::new(deps.as_mut(), mock_env());
551+
552+
let res = contract.get_current_block_time();
553+
assert_eq!(res, contract.env.block.time.nanos());
554+
}
555+
556+
#[test]
557+
fn test_get_current_block_height() {
558+
let mut deps = mock_dependencies();
559+
let contract = CwContext::new(deps.as_mut(), mock_env());
560+
561+
let res = contract.get_current_block_height();
562+
assert_eq!(res, contract.env.block.height);
563+
}
564+
565+
#[test]
566+
fn test_get_processed_time_at_height() {
567+
let mut deps = mock_dependencies();
568+
let mut contract = CwContext::new(deps.as_mut(), mock_env());
569+
570+
let height = 2;
571+
let client_id = "test_client";
572+
573+
contract
574+
.insert_timestamp_at_height(client_id, height)
575+
.unwrap();
576+
577+
let res = contract
578+
.get_processed_time_at_height(client_id, height)
579+
.unwrap();
580+
581+
assert_eq!(res, contract.env.block.time.nanos())
582+
}
583+
584+
#[test]
585+
#[should_panic(expected = "ProcessedTimeNotFound")]
586+
fn fail_test_get_processed_time_at_height() {
587+
let mut deps = mock_dependencies();
588+
let mut contract = CwContext::new(deps.as_mut(), mock_env());
589+
590+
let height = 2;
591+
let client_id = "test_client";
592+
593+
contract
594+
.insert_timestamp_at_height(client_id, height)
595+
.unwrap();
596+
597+
contract.get_processed_time_at_height(client_id, 3).unwrap();
598+
}
599+
600+
#[test]
601+
fn test_get_processed_block_number_at_height() {
602+
let mut deps = mock_dependencies();
603+
let mut contract = CwContext::new(deps.as_mut(), mock_env());
604+
605+
let height = 2;
606+
let client_id = "test_client";
607+
608+
contract
609+
.insert_blocknumber_at_height(client_id, height)
610+
.unwrap();
611+
612+
let res = contract
613+
.get_processed_block_at_height(client_id, height)
614+
.unwrap();
615+
616+
assert_eq!(res, contract.env.block.height)
617+
}
618+
619+
#[test]
620+
#[should_panic(expected = "ProcessedHeightNotFound")]
621+
fn fail_test_get_processed_block_number_at_height() {
622+
let mut deps = mock_dependencies();
623+
let mut contract = CwContext::new(deps.as_mut(), mock_env());
624+
625+
let height = 2;
626+
let client_id = "test_client";
627+
628+
contract
629+
.insert_blocknumber_at_height(client_id, height)
630+
.unwrap();
631+
632+
contract
633+
.get_processed_block_at_height(client_id, 3)
634+
.unwrap();
635+
}
494636
}

0 commit comments

Comments
 (0)