use ibc_relayer::chain::handle::ChainHandle;
use ibc_relayer::config::Config;
use ibc_relayer::foreign_client::CreateOptions as ClientOptions;
use tracing::info;
use crate::bootstrap::binary::chain::{bootstrap_chains_with_full_nodes, BootstrapClientOptions};
use crate::error::Error;
use crate::framework::base::{HasOverrides, TestConfigOverride};
use crate::framework::binary::ics::InterchainSecurityChainTest;
use crate::framework::binary::node::{
run_binary_node_test, run_single_node_test, BinaryNodeTest, NodeConfigOverride,
NodeGenesisOverride,
};
use crate::framework::supervisor::{RunWithSupervisor, SupervisorOverride};
use crate::relayer::driver::RelayerDriver;
use crate::types::binary::chains::{ConnectedChains, DropChainHandle};
use crate::types::config::TestConfig;
use crate::types::env::write_env;
use crate::types::single::node::FullNode;
use crate::util::suspend::hang_on_error;
pub fn run_two_way_binary_chain_test<Test, Overrides>(test: &Test) -> Result<(), Error>
where
Test: BinaryChainTest,
Test: HasOverrides<Overrides = Overrides>,
Overrides: NodeConfigOverride
+ NodeGenesisOverride
+ RelayerConfigOverride
+ ClientOptionsOverride
+ SupervisorOverride
+ TestConfigOverride,
{
run_binary_chain_test(&RunTwoWayBinaryChainTest::new(test))
}
pub fn run_binary_chain_test<Test, Overrides>(test: &Test) -> Result<(), Error>
where
Test: BinaryChainTest,
Test: HasOverrides<Overrides = Overrides>,
Overrides: NodeConfigOverride
+ NodeGenesisOverride
+ RelayerConfigOverride
+ ClientOptionsOverride
+ SupervisorOverride
+ TestConfigOverride,
{
run_binary_node_test(&RunBinaryChainTest::new(&RunWithSupervisor::new(test)))
}
pub fn run_self_connected_binary_chain_test<Test, Overrides>(test: &Test) -> Result<(), Error>
where
Test: BinaryChainTest,
Test: HasOverrides<Overrides = Overrides>,
Overrides: NodeConfigOverride
+ NodeGenesisOverride
+ RelayerConfigOverride
+ ClientOptionsOverride
+ TestConfigOverride,
{
run_single_node_test(&RunBinaryChainTest::new(test))
}
pub trait BinaryChainTest {
fn run<ChainA: ChainHandle, ChainB: ChainHandle>(
&self,
config: &TestConfig,
relayer: RelayerDriver,
chains: ConnectedChains<ChainA, ChainB>,
) -> Result<(), Error>;
}
pub trait RelayerConfigOverride {
fn modify_relayer_config(&self, config: &mut Config);
}
pub trait ClientOptionsOverride {
fn client_options_a_to_b(&self) -> ClientOptions {
Default::default()
}
fn client_options_b_to_a(&self) -> ClientOptions {
Default::default()
}
}
pub struct RunBinaryChainTest<'a, Test> {
pub test: &'a Test,
}
pub struct RunTwoWayBinaryChainTest<'a, Test> {
pub test: &'a Test,
}
pub struct RunSelfConnectedBinaryChainTest<'a, Test> {
pub test: &'a Test,
}
impl<'a, Test> RunBinaryChainTest<'a, Test>
where
Test: BinaryChainTest,
{
pub fn new(test: &'a Test) -> Self {
Self { test }
}
}
impl<'a, Test> RunTwoWayBinaryChainTest<'a, Test>
where
Test: BinaryChainTest,
{
pub fn new(test: &'a Test) -> Self {
Self { test }
}
}
impl<'a, Test> RunSelfConnectedBinaryChainTest<'a, Test>
where
Test: BinaryChainTest,
{
pub fn new(test: &'a Test) -> Self {
Self { test }
}
}
impl<'a, Test, Overrides> BinaryNodeTest for RunBinaryChainTest<'a, Test>
where
Test: BinaryChainTest,
Test: HasOverrides<Overrides = Overrides>,
Overrides: RelayerConfigOverride + ClientOptionsOverride,
{
fn run(&self, config: &TestConfig, node_a: FullNode, node_b: FullNode) -> Result<(), Error> {
let overrides = self.test.get_overrides();
let bootstrap_options = BootstrapClientOptions::default()
.client_options_a_to_b(overrides.client_options_a_to_b())
.client_options_b_to_a(overrides.client_options_b_to_a())
.bootstrap_with_random_ids(config.bootstrap_with_random_ids);
let (relayer, chains) = bootstrap_chains_with_full_nodes(
config,
node_a,
node_b,
bootstrap_options,
|config| {
overrides.modify_relayer_config(config);
},
)?;
let env_path = config.chain_store_dir.join("binary-chains.env");
write_env(&env_path, &(&relayer, &chains))?;
info!("written chains environment to {}", env_path.display());
let _drop_handle_a = DropChainHandle(chains.handle_a.clone());
let _drop_handle_b = DropChainHandle(chains.handle_b.clone());
self.test.run(config, relayer, chains)?;
Ok(())
}
}
impl<'a, Test, Overrides> InterchainSecurityChainTest for RunBinaryChainTest<'a, Test>
where
Test: BinaryChainTest,
Test: HasOverrides<Overrides = Overrides>,
Overrides: RelayerConfigOverride + ClientOptionsOverride,
{
fn run(&self, config: &TestConfig, node_a: FullNode, node_b: FullNode) -> Result<(), Error> {
let overrides = self.test.get_overrides();
let bootstrap_options = BootstrapClientOptions::default()
.client_options_a_to_b(overrides.client_options_a_to_b())
.client_options_b_to_a(overrides.client_options_b_to_a())
.bootstrap_with_random_ids(config.bootstrap_with_random_ids);
let (relayer, chains) = bootstrap_chains_with_full_nodes(
config,
node_a,
node_b,
bootstrap_options,
|config| {
overrides.modify_relayer_config(config);
},
)?;
let env_path = config.chain_store_dir.join("binary-chains.env");
write_env(&env_path, &(&relayer, &chains))?;
info!("written chains environment to {}", env_path.display());
let _drop_handle_a = DropChainHandle(chains.handle_a.clone());
let _drop_handle_b = DropChainHandle(chains.handle_b.clone());
self.test.run(config, relayer, chains)?;
Ok(())
}
}
impl<'a, Test: BinaryChainTest> BinaryChainTest for RunTwoWayBinaryChainTest<'a, Test> {
fn run<ChainA: ChainHandle, ChainB: ChainHandle>(
&self,
config: &TestConfig,
relayer: RelayerDriver,
chains: ConnectedChains<ChainA, ChainB>,
) -> Result<(), Error> {
info!(
"running two-way chain test, from {} to {}",
chains.chain_id_a(),
chains.chain_id_b(),
);
self.test.run(config, relayer.clone(), chains.clone())?;
info!(
"running two-way chain test in the opposite direction, from {} to {}",
chains.chain_id_b(),
chains.chain_id_a(),
);
let chains = chains.flip();
self.test.run(config, relayer, chains)?;
Ok(())
}
}
impl<'a, Test, Overrides> BinaryChainTest for RunWithSupervisor<'a, Test>
where
Test: BinaryChainTest,
Test: HasOverrides<Overrides = Overrides>,
Overrides: SupervisorOverride,
{
fn run<ChainA: ChainHandle, ChainB: ChainHandle>(
&self,
config: &TestConfig,
relayer: RelayerDriver,
chains: ConnectedChains<ChainA, ChainB>,
) -> Result<(), Error> {
if self.get_overrides().should_spawn_supervisor() {
relayer
.clone()
.with_supervisor(|| self.test.run(config, relayer, chains))
} else {
hang_on_error(config.hang_on_fail, || {
self.test.run(config, relayer, chains)
})
}
}
}
impl<'a, Test, Overrides> HasOverrides for RunBinaryChainTest<'a, Test>
where
Test: HasOverrides<Overrides = Overrides>,
{
type Overrides = Overrides;
fn get_overrides(&self) -> &Self::Overrides {
self.test.get_overrides()
}
}
impl<'a, Test, Overrides> HasOverrides for RunTwoWayBinaryChainTest<'a, Test>
where
Test: HasOverrides<Overrides = Overrides>,
{
type Overrides = Overrides;
fn get_overrides(&self) -> &Self::Overrides {
self.test.get_overrides()
}
}