diff --git a/.gitignore b/.gitignore index 54ec2a1..e0d01e8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ /target Runehook.toml .DS_Store +/mutants.out +/mutants.out.old diff --git a/Cargo.lock b/Cargo.lock index 2e31044..518456d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2207,6 +2207,12 @@ dependencies = [ "version_check", ] +[[package]] +name = "mutants" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc0287524726960e07b119cebd01678f852f147742ae0d925e6a520dca956126" + [[package]] name = "native-tls" version = "0.2.11" @@ -3069,6 +3075,7 @@ dependencies = [ "hiro-system-kit", "lru", "maplit", + "mutants", "num-traits", "ordinals", "rand", diff --git a/Cargo.toml b/Cargo.toml index 7da812b..db64917 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,6 +36,7 @@ maplit = "1.0.2" [dev-dependencies] test-case = "3.1.0" +mutants = "0.0.3" [features] debug = ["hiro-system-kit/debug"] diff --git a/src/bitcoind/mod.rs b/src/bitcoind/mod.rs index d556f71..a7ac231 100644 --- a/src/bitcoind/mod.rs +++ b/src/bitcoind/mod.rs @@ -5,6 +5,7 @@ use chainhook_sdk::{ use crate::{config::Config, try_error}; +#[cfg_attr(test, mutants::skip)] fn get_client(config: &Config, ctx: &Context) -> Client { loop { let auth = Auth::UserPass( diff --git a/src/config/mod.rs b/src/config/mod.rs index 1dcc315..30f28fa 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -31,6 +31,7 @@ pub struct Config { } impl Config { + #[cfg_attr(test, mutants::skip)] pub fn from_file_path(file_path: &str) -> Result { let file = File::open(file_path) .map_err(|e| format!("unable to read file {}\n{:?}", file_path, e))?; @@ -49,6 +50,7 @@ impl Config { Config::from_config_file(config_file) } + #[cfg_attr(test, mutants::skip)] pub fn from_config_file(config_file: ConfigFile) -> Result { let event_observer = EventObserverConfig::new_using_overrides(config_file.network.as_ref())?; @@ -75,6 +77,7 @@ impl Config { Ok(config) } + #[cfg_attr(test, mutants::skip)] pub fn get_bitcoin_network(&self) -> Network { match self.event_observer.bitcoin_network { BitcoinNetwork::Mainnet => Network::Bitcoin, diff --git a/src/db/cache/input_rune_balance.rs b/src/db/cache/input_rune_balance.rs index be65068..0c63044 100644 --- a/src/db/cache/input_rune_balance.rs +++ b/src/db/cache/input_rune_balance.rs @@ -1,4 +1,4 @@ -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Default)] pub struct InputRuneBalance { /// Previous owner of this balance. If this is `None`, it means the balance was just minted or premined. pub address: Option, diff --git a/src/db/index.rs b/src/db/index.rs index df63041..5ae1375 100644 --- a/src/db/index.rs +++ b/src/db/index.rs @@ -29,6 +29,7 @@ pub fn get_rune_genesis_block_height(network: Network) -> u64 { /// Transforms a Bitcoin transaction from a Chainhook format to a rust bitcoin crate format so it can be parsed by the ord crate /// to look for `Artifact`s. Also, takes all non-OP_RETURN outputs and returns them so they can be used later to receive runes. +#[cfg_attr(test, mutants::skip)] fn bitcoin_tx_from_chainhook_tx( block: &BitcoinBlockData, tx: &BitcoinTransactionData, diff --git a/src/db/mod.rs b/src/db/mod.rs index 7db31ce..a3f466c 100644 --- a/src/db/mod.rs +++ b/src/db/mod.rs @@ -38,6 +38,7 @@ async fn pg_run_migrations(pg_client: &mut Client, ctx: &Context) { try_info!(ctx, "Postgres migrations complete"); } +#[cfg_attr(test, mutants::skip)] pub async fn pg_connect(config: &Config, run_migrations: bool, ctx: &Context) -> Client { let mut pg_config = tokio_postgres::Config::new(); pg_config @@ -441,6 +442,7 @@ pub async fn pg_get_rune_total_mints( /// Retrieves the rune balance for an array of transaction inputs represented by `(vin, tx_id, vout)` where `vin` is the index of /// this transaction input, `tx_id` is the transaction ID that produced this input and `vout` is the output index of this previous /// tx. +#[cfg_attr(test, mutants::skip)] pub async fn pg_get_input_rune_balances( outputs: Vec<(u32, String, u32)>, db_tx: &mut Transaction<'_>, diff --git a/src/db/models/db_balance_change.rs b/src/db/models/db_balance_change.rs index f4ecf01..f92de67 100644 --- a/src/db/models/db_balance_change.rs +++ b/src/db/models/db_balance_change.rs @@ -2,7 +2,7 @@ use crate::db::types::{ pg_bigint_u32::PgBigIntU32, pg_numeric_u128::PgNumericU128, pg_numeric_u64::PgNumericU64, }; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Default)] pub struct DbBalanceChange { pub rune_id: String, pub block_height: PgNumericU64, diff --git a/src/db/models/db_ledger_entry.rs b/src/db/models/db_ledger_entry.rs index ec171bb..a0f7c99 100644 --- a/src/db/models/db_ledger_entry.rs +++ b/src/db/models/db_ledger_entry.rs @@ -8,7 +8,7 @@ use crate::db::types::{ use super::db_ledger_operation::DbLedgerOperation; /// A row in the `ledger` table. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Default)] pub struct DbLedgerEntry { pub rune_id: String, pub block_hash: String, diff --git a/src/db/models/db_ledger_operation.rs b/src/db/models/db_ledger_operation.rs index f0ee1ec..a87c7c3 100644 --- a/src/db/models/db_ledger_operation.rs +++ b/src/db/models/db_ledger_operation.rs @@ -4,8 +4,9 @@ use bytes::BytesMut; use tokio_postgres::types::{to_sql_checked, FromSql, IsNull, ToSql, Type}; /// A value from the `ledger_operation` enum type. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Default)] pub enum DbLedgerOperation { + #[default] Etching, Mint, Burn, @@ -47,6 +48,7 @@ impl std::str::FromStr for DbLedgerOperation { } impl ToSql for DbLedgerOperation { + #[cfg_attr(test, mutants::skip)] fn to_sql( &self, _ty: &Type, diff --git a/src/db/models/db_rune.rs b/src/db/models/db_rune.rs index 561ed05..4e1f489 100644 --- a/src/db/models/db_rune.rs +++ b/src/db/models/db_rune.rs @@ -10,7 +10,7 @@ use crate::db::{ }; /// A row in the `runes` table. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Default)] pub struct DbRune { pub id: String, pub number: PgBigIntU32, diff --git a/src/db/models/db_supply_change.rs b/src/db/models/db_supply_change.rs index 6ea3813..93a9723 100644 --- a/src/db/models/db_supply_change.rs +++ b/src/db/models/db_supply_change.rs @@ -1,7 +1,7 @@ use crate::db::types::{pg_numeric_u128::PgNumericU128, pg_numeric_u64::PgNumericU64}; /// An update to a rune that affects its total counts. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Default)] pub struct DbSupplyChange { pub rune_id: String, pub block_height: PgNumericU64, diff --git a/src/db/types/pg_bigint_u32.rs b/src/db/types/pg_bigint_u32.rs index a0540f5..78f80c8 100644 --- a/src/db/types/pg_bigint_u32.rs +++ b/src/db/types/pg_bigint_u32.rs @@ -1,12 +1,13 @@ -use std::{error::Error, ops::AddAssign}; +use std::{error::Error, ops::{AddAssign, DivAssign, MulAssign, SubAssign}}; use bytes::{BufMut, BytesMut}; use tokio_postgres::types::{to_sql_checked, FromSql, IsNull, ToSql, Type}; -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, Default)] pub struct PgBigIntU32(pub u32); impl ToSql for PgBigIntU32 { + #[cfg_attr(test, mutants::skip)] fn to_sql( &self, _ty: &Type, @@ -41,6 +42,24 @@ impl AddAssign for PgBigIntU32 { } } +impl SubAssign for PgBigIntU32 { + fn sub_assign(&mut self, other: u32) { + self.0 -= other; + } +} + +impl MulAssign for PgBigIntU32 { + fn mul_assign(&mut self, other: u32) { + self.0 *= other; + } +} + +impl DivAssign for PgBigIntU32 { + fn div_assign(&mut self, other: u32) { + self.0 /= other; + } +} + #[cfg(test)] mod test { use chainhook_sdk::utils::Context; diff --git a/src/db/types/pg_numeric_u128.rs b/src/db/types/pg_numeric_u128.rs index b0f271c..242897c 100644 --- a/src/db/types/pg_numeric_u128.rs +++ b/src/db/types/pg_numeric_u128.rs @@ -1,7 +1,7 @@ use std::{ error::Error, io::{Cursor, Read}, - ops::AddAssign, + ops::{AddAssign, DivAssign, MulAssign, SubAssign}, }; use bytes::{BufMut, BytesMut}; @@ -9,6 +9,7 @@ use num_traits::{ToPrimitive, Zero}; use tokio_postgres::types::{to_sql_checked, FromSql, IsNull, ToSql, Type}; /// Transforms a u128 value into postgres' `numeric` wire format. +#[cfg_attr(test, mutants::skip)] pub fn u128_into_pg_numeric_bytes(number: u128, out: &mut BytesMut) { let mut num = number.clone(); let mut digits = vec![]; @@ -64,10 +65,11 @@ pub fn pg_numeric_bytes_to_u128(raw: &[u8]) -> u128 { result } -#[derive(Debug, Clone, Copy, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq, Default)] pub struct PgNumericU128(pub u128); impl ToSql for PgNumericU128 { + #[cfg_attr(test, mutants::skip)] fn to_sql( &self, _ty: &Type, @@ -107,6 +109,42 @@ impl AddAssign for PgNumericU128 { } } +impl SubAssign for PgNumericU128 { + fn sub_assign(&mut self, other: Self) { + self.0 -= other.0; + } +} + +impl SubAssign for PgNumericU128 { + fn sub_assign(&mut self, other: u128) { + self.0 -= other; + } +} + +impl MulAssign for PgNumericU128 { + fn mul_assign(&mut self, other: Self) { + self.0 *= other.0; + } +} + +impl MulAssign for PgNumericU128 { + fn mul_assign(&mut self, other: u128) { + self.0 *= other; + } +} + +impl DivAssign for PgNumericU128 { + fn div_assign(&mut self, other: Self) { + self.0 /= other.0; + } +} + +impl DivAssign for PgNumericU128 { + fn div_assign(&mut self, other: u128) { + self.0 /= other; + } +} + #[cfg(test)] mod test { use chainhook_sdk::utils::Context; diff --git a/src/db/types/pg_numeric_u64.rs b/src/db/types/pg_numeric_u64.rs index 0e66b8b..7835375 100644 --- a/src/db/types/pg_numeric_u64.rs +++ b/src/db/types/pg_numeric_u64.rs @@ -6,10 +6,11 @@ use tokio_postgres::types::{to_sql_checked, FromSql, IsNull, ToSql, Type}; use super::pg_numeric_u128::{pg_numeric_bytes_to_u128, u128_into_pg_numeric_bytes}; -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, Default)] pub struct PgNumericU64(pub u64); impl ToSql for PgNumericU64 { + #[cfg_attr(test, mutants::skip)] fn to_sql( &self, _ty: &Type, diff --git a/src/db/types/pg_smallint_u8.rs b/src/db/types/pg_smallint_u8.rs index e119608..9e93f6c 100644 --- a/src/db/types/pg_smallint_u8.rs +++ b/src/db/types/pg_smallint_u8.rs @@ -3,10 +3,11 @@ use std::error::Error; use bytes::{BufMut, BytesMut}; use tokio_postgres::types::{to_sql_checked, FromSql, IsNull, ToSql, Type}; -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, Default)] pub struct PgSmallIntU8(pub u8); impl ToSql for PgSmallIntU8 { + #[cfg_attr(test, mutants::skip)] fn to_sql( &self, _ty: &Type, diff --git a/src/service.rs b/src/service.rs index 3db43ee..2030ac4 100644 --- a/src/service.rs +++ b/src/service.rs @@ -101,6 +101,7 @@ pub async fn start_service(config: &Config, ctx: &Context) -> Result<(), String> Ok(()) } +#[cfg_attr(test, mutants::skip)] pub async fn set_up_observer_sidecar_runloop( config: &Config, ctx: &Context,