ibc-test-framework 0.32.1

Framework for writing integration tests for IBC relayers
//! Error type used for the tests.

use std::io::{Error as IoError, ErrorKind as IoErrorKind};

use eyre::Report;
use flex_error::{define_error, TraceError};

use ibc_relayer::channel::error::ChannelError;
use ibc_relayer::connection::ConnectionError;
use ibc_relayer::error::Error as RelayerError;
use ibc_relayer::foreign_client::ForeignClientError;
use ibc_relayer::link::error::LinkError;
use ibc_relayer::supervisor::error::Error as SupervisorError;
use ibc_relayer::transfer::TransferError;
use ibc_relayer::upgrade_chain::UpgradeChainError;

define_error! {
    Error {
        Generic
            [ TraceError<Report> ]
            | _ | { "generic error" },

        Assertion
            { message: String }
            | e | { format_args!("assertion failure: {}", e.message) },

        Io
            [ TraceError<IoError> ]
            | _ | { "io error"},

        CommandNotFound
            { command: String }
            [ TraceError<IoError> ]
            | e | { format_args!("failed to execute command: {}. make sure it is available in $PATH", e.command) },

        Relayer
            [ RelayerError ]
            | _ | { "relayer error"},

        Supervisor
            [ SupervisorError ]
            | _ | { "supervisor error"},

        Channel
            [ ChannelError ]
            | _ | { "channel error"},

        Connection
            [ ConnectionError ]
            | _ | { "connection error"},

        Transfer
            [ TransferError ]
            | _ | { "transfer error"},

        Link
            [ LinkError ]
            | _ | { "link error" },

        Retry
            {
                task_name: String,
                attempts: u16,
            }
            | e | {
                format_args!(
                    "Expected task to eventually succeed, but failed after {} attempts: {}",
                    e.attempts,
                    e.task_name
                )
            },

        UpgradeChain
            [ UpgradeChainError ]
            | _ | { "upgrade chain error" },

        ForeignClient
            [ ForeignClientError ]
            | _ | { "foreign client error" },

        QueryClient
            | _ | { "error querying client" },

        IncorrectProposal
            | _ | { "error decoding the Proposal to an UpgradeProposal" },

        IncorrectProposalTypeUrl
            { type_url: String }
            | e | format_args!("expected /ibc.core.client.v1.UpgradeProposal or /ibc.core.client.v1.MsgIBCSoftwareUpgrade but got {}", e.type_url),

        EmptyProposal
            | _ | { "the Proposal content is empty" },

        EmptyPlan
            | _ | { "The plan in the UpgradeProposal is empty" },
    }
}

pub fn handle_generic_error(e: impl Into<Report>) -> Error {
    Error::generic(e.into())
}

pub fn handle_exec_error(command: &str) -> impl FnOnce(IoError) -> Error + '_ {
    |e| match e.kind() {
        IoErrorKind::NotFound => Error::command_not_found(command.to_string(), e),
        _ => Error::io(e),
    }
}

impl From<Report> for Error {
    fn from(e: Report) -> Self {
        Error::generic(e)
    }
}

impl From<IoError> for Error {
    fn from(e: IoError) -> Self {
        Error::io(e)
    }
}

impl From<RelayerError> for Error {
    fn from(e: RelayerError) -> Self {
        Error::relayer(e)
    }
}

impl From<SupervisorError> for Error {
    fn from(e: SupervisorError) -> Self {
        Error::supervisor(e)
    }
}

impl From<ChannelError> for Error {
    fn from(e: ChannelError) -> Self {
        Error::channel(e)
    }
}

impl From<ConnectionError> for Error {
    fn from(e: ConnectionError) -> Self {
        Error::connection(e)
    }
}

impl From<TransferError> for Error {
    fn from(e: TransferError) -> Self {
        Error::transfer(e)
    }
}

impl From<LinkError> for Error {
    fn from(e: LinkError) -> Self {
        Error::link(e)
    }
}