From ba0e12303bb92c524b36da0c263f96f88bcc9626 Mon Sep 17 00:00:00 2001 From: Roy Yang Date: Wed, 19 Feb 2025 16:45:34 +1300 Subject: [PATCH] Added a new "assert_matches" utility macro that can be used to replace `assert!(matches!())` --- Cargo.lock | 2 + .../src/client/ceremony_manager/tests.rs | 6 +- .../src/client/ceremony_runner/tests.rs | 5 +- .../src/client/multisig_client_tests.rs | 6 +- engine/src/common.rs | 5 +- .../client/error_decoder.rs | 4 +- .../solana/sol-prim/src/tests/pda.rs | 13 +++-- state-chain/amm/src/limit_orders/tests.rs | 24 ++++---- .../cf-integration-tests/src/authorities.rs | 53 +++++++++-------- .../cf-integration-tests/src/new_epoch.rs | 7 ++- .../cf-integration-tests/src/solana.rs | 10 ++-- state-chain/chains/src/btc.rs | 4 +- state-chain/chains/src/eth.rs | 4 +- state-chain/chains/src/evm/api/all_batch.rs | 3 +- state-chain/pallets/cf-funding/Cargo.toml | 1 + state-chain/pallets/cf-funding/src/tests.rs | 5 +- .../pallets/cf-ingress-egress/Cargo.toml | 1 + .../pallets/cf-ingress-egress/src/tests.rs | 16 ++++-- .../src/benchmarking.rs | 13 +++-- .../cf-threshold-signature/src/mock.rs | 13 +++-- .../src/response_status.rs | 57 ++++++++++--------- .../cf-threshold-signature/src/tests.rs | 57 ++++++++++--------- .../pallets/cf-validator/src/benchmarking.rs | 21 +++---- state-chain/pallets/cf-validator/src/tests.rs | 18 +++--- state-chain/pallets/cf-vaults/src/tests.rs | 13 +++-- utilities/src/lib.rs | 27 +++++++++ utilities/src/with_std/dynamic_events.rs | 6 +- 27 files changed, 220 insertions(+), 174 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0187d45d030..8a77d28b582 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8363,6 +8363,7 @@ dependencies = [ "sp-io 38.0.0", "sp-runtime 39.0.0", "sp-std 14.0.0 (git+https://github.com/chainflip-io/polkadot-sdk.git?tag=chainflip-substrate-1.15.2%2B2)", + "utilities", ] [[package]] @@ -8409,6 +8410,7 @@ dependencies = [ "sp-std 14.0.0 (git+https://github.com/chainflip-io/polkadot-sdk.git?tag=chainflip-substrate-1.15.2%2B2)", "strum 0.26.3", "strum_macros 0.26.4", + "utilities", ] [[package]] diff --git a/engine/multisig/src/client/ceremony_manager/tests.rs b/engine/multisig/src/client/ceremony_manager/tests.rs index 58b4b3a5d74..e09dc40870e 100644 --- a/engine/multisig/src/client/ceremony_manager/tests.rs +++ b/engine/multisig/src/client/ceremony_manager/tests.rs @@ -23,7 +23,7 @@ use crate::{ }; use anyhow::Result; use cf_primitives::{AccountId, CeremonyId}; -use cf_utilities::{task_scope::task_scope, threshold_from_share_count}; +use cf_utilities::{assert_matches, task_scope::task_scope, threshold_from_share_count}; use client::MultisigMessage; use futures::{Future, FutureExt}; use rand::SeedableRng; @@ -453,8 +453,8 @@ async fn should_route_p2p_message() { // Check that a broadcast was sent out. Meaning that the ceremony received the message and moved // to stage 2. - assert!(matches!( + assert_matches!( outgoing_p2p_receiver.try_recv().unwrap(), OutgoingMultisigStageMessages::Broadcast(..) - )) + ); } diff --git a/engine/multisig/src/client/ceremony_runner/tests.rs b/engine/multisig/src/client/ceremony_runner/tests.rs index eb570502285..96af48f169c 100644 --- a/engine/multisig/src/client/ceremony_runner/tests.rs +++ b/engine/multisig/src/client/ceremony_runner/tests.rs @@ -15,6 +15,7 @@ use crate::{ Rng, }; +use cf_utilities::assert_matches; use rand::SeedableRng; use sp_runtime::AccountId32; use tokio::sync::mpsc; @@ -169,7 +170,7 @@ async fn should_process_delayed_messages_after_finishing_a_stage() { // Process a stage 1 message. This will cause the ceremony to progress to stage 2 and process // the delayed message. The processing of the delayed message will cause the completion of stage // 2 and therefore fail with BroadcastFailure because the data we used was invalid. - assert!(matches!( + assert_matches!( ceremony_runner .process_or_delay_message(sender_account_id.clone(), gen_signing_data_stage1(1)) .await, @@ -180,7 +181,7 @@ async fn should_process_delayed_messages_after_finishing_a_stage() { SigningStageName::VerifyCommitmentsBroadcast2 ) ))) - )); + ); } // Note: Clippy seems to throw a false positive without this. diff --git a/engine/multisig/src/client/multisig_client_tests.rs b/engine/multisig/src/client/multisig_client_tests.rs index a0cfaf4998c..301fc97d9c4 100644 --- a/engine/multisig/src/client/multisig_client_tests.rs +++ b/engine/multisig/src/client/multisig_client_tests.rs @@ -16,7 +16,7 @@ use mockall::predicate; use crate::client::key_store_api::MockKeyStoreAPI; use cf_primitives::GENESIS_EPOCH; -use cf_utilities::{assert_err, assert_ok, testing::assert_future_can_complete}; +use cf_utilities::{assert_err, assert_matches, assert_ok, testing::assert_future_can_complete}; use client::MultisigClient; #[tokio::test] @@ -47,10 +47,10 @@ async fn should_ignore_rts_for_unknown_key() { // Check that the signing request fails immediately with an "unknown key" error let (_, failure_reason) = assert_err!(assert_future_can_complete(signing_request_fut)); assert_eq!(failure_reason, SigningFailureReason::UnknownKey); - assert!(matches!( + assert_matches!( assert_ok!(assert_future_can_complete(ceremony_request_receiver.recv())), CeremonyRequest { ceremony_id: DEFAULT_SIGNING_CEREMONY_ID, details: None } - )); + ); } #[tokio::test] diff --git a/engine/src/common.rs b/engine/src/common.rs index a8db032dfd3..366636f9a5a 100644 --- a/engine/src/common.rs +++ b/engine/src/common.rs @@ -1,3 +1,4 @@ +use cf_utilities::assert_matches; use std::ops::{Deref, DerefMut}; struct MutexStateAndPoisonFlag { @@ -93,10 +94,10 @@ pub struct Signaller { } impl Signaller { pub fn signal(self, t: T) { - assert!(matches!( + assert_matches!( self.sender.try_broadcast(t), Ok(None) | Err(async_broadcast::TrySendError::Closed(_)) - )); + ); } } diff --git a/engine/src/state_chain_observer/client/error_decoder.rs b/engine/src/state_chain_observer/client/error_decoder.rs index 163e7bec849..530798dd5b8 100644 --- a/engine/src/state_chain_observer/client/error_decoder.rs +++ b/engine/src/state_chain_observer/client/error_decoder.rs @@ -136,10 +136,10 @@ mod tests { let dispatch_error = sp_runtime::DispatchError::decode(&mut &encoded_error[..]).unwrap(); // Message should be erased. - assert!(matches!( + cf_utilities::assert_matches!( dispatch_error, sp_runtime::DispatchError::Module(ModuleError { message: None, .. }) - )); + ); match ErrorDecoder::default().decode_dispatch_error(dispatch_error) { super::DispatchError::KnownModuleError { pallet, name, error } => { diff --git a/foreign-chains/solana/sol-prim/src/tests/pda.rs b/foreign-chains/solana/sol-prim/src/tests/pda.rs index 28d4cfc92d2..e2aeadab224 100644 --- a/foreign-chains/solana/sol-prim/src/tests/pda.rs +++ b/foreign-chains/solana/sol-prim/src/tests/pda.rs @@ -7,12 +7,13 @@ mod failures { pda::{Pda, PdaError}, Address, PdaAndBump, }; + use cf_utilities::assert_matches; #[test] fn seed_too_long() { let public_key: Address = "J4mK4RXAuizk5aMZw8Vz8W3y7mrCy6dcgniZ4qwZimZE".parse().expect("public key"); - assert!(matches!( + assert_matches!( Pda::from_address(public_key) .expect("derive") .chain_seed("01234567890123456789012345678912") @@ -20,7 +21,7 @@ mod failures { .chain_seed("012345678901234567890123456789123") .expect_err("33 should be too much"), PdaError::SeedTooLarge - )); + ); } #[test] @@ -31,13 +32,13 @@ mod failures { .map(|i| [i]) .try_fold(Pda::from_address(public_key).expect("derive"), Pda::chain_seed) .expect("15 should be okay"); - assert!(matches!( + assert_matches!( (1..=consts::SOLANA_PDA_MAX_SEEDS) .map(|i| [i]) .try_fold(Pda::from_address(public_key).expect("derive"), Pda::chain_seed) .expect_err("16 should be too many"), PdaError::TooManySeeds - )); + ); } #[test] @@ -46,10 +47,10 @@ mod failures { "J4mK4RXAuizk5aMZw8Vz8W3y7mrCy6dcgniZ4qwZimZE".parse().expect("public key"); let PdaAndBump { address, .. } = Pda::from_address(public_key).expect("derive").finish().expect("finish"); - assert!(matches!( + assert_matches!( Pda::from_address(address).expect_err("PDA can't be a valid point on a curve"), PdaError::NotAValidPoint, - )) + ); } } diff --git a/state-chain/amm/src/limit_orders/tests.rs b/state-chain/amm/src/limit_orders/tests.rs index 80fe21f797c..59ff1932506 100644 --- a/state-chain/amm/src/limit_orders/tests.rs +++ b/state-chain/amm/src/limit_orders/tests.rs @@ -6,7 +6,7 @@ use cf_amm_math::{ use super::*; -use cf_utilities::{assert_ok, assert_panics}; +use cf_utilities::{assert_matches, assert_ok, assert_panics}; use rand::{Rng, SeedableRng}; type LiquidityProvider = cf_primitives::AccountId; @@ -276,7 +276,7 @@ fn test_float() { #[test] fn fee_hundredth_pips() { for bad in [u32::MAX, ONE_IN_HUNDREDTH_PIPS, (ONE_IN_HUNDREDTH_PIPS / 2) + 1] { - assert!(matches!(PoolState::new(bad), Err(NewError::InvalidFeeAmount))); + assert_matches!(PoolState::new(bad), Err(NewError::InvalidFeeAmount)); } for good in [0, 1, ONE_IN_HUNDREDTH_PIPS / 2] { @@ -390,14 +390,14 @@ fn mint() { for bad in [MIN_TICK - 1, MAX_TICK + 1] { let mut pool_state = PoolState::new(0).unwrap(); - assert!(matches!( + assert_matches!( pool_state.collect_and_mint::( &LiquidityProvider::from([0; 32]), bad, 1000.into() ), Err(PositionError::InvalidTick) - )); + ); } for good in [MAX_FIXED_POOL_LIQUIDITY, MAX_FIXED_POOL_LIQUIDITY - 1, 1.into()] { @@ -414,10 +414,10 @@ fn mint() { for bad in [MAX_FIXED_POOL_LIQUIDITY + 1, MAX_FIXED_POOL_LIQUIDITY + 2] { let mut pool_state = PoolState::new(0).unwrap(); - assert!(matches!( + assert_matches!( pool_state.collect_and_mint::(&LiquidityProvider::from([0; 32]), 0, bad), Err(PositionError::Other(MintError::MaximumLiquidity)) - )); + ); } } @@ -430,33 +430,33 @@ fn burn() { fn inner() { { let mut pool_state = PoolState::new(0).unwrap(); - assert!(matches!( + assert_matches!( pool_state.collect_and_burn::( &LiquidityProvider::from([0; 32]), MIN_TICK - 1, 1000.into() ), Err(PositionError::InvalidTick) - )); - assert!(matches!( + ); + assert_matches!( pool_state.collect_and_burn::( &LiquidityProvider::from([0; 32]), MAX_TICK + 1, 1000.into() ), Err(PositionError::InvalidTick) - )); + ); } { let mut pool_state = PoolState::new(0).unwrap(); - assert!(matches!( + assert_matches!( pool_state.collect_and_burn::( &LiquidityProvider::from([0; 32]), 120, 1000.into() ), Err(PositionError::NonExistent) - )); + ); } { let mut pool_state = PoolState::new(0).unwrap(); diff --git a/state-chain/cf-integration-tests/src/authorities.rs b/state-chain/cf-integration-tests/src/authorities.rs index e27af1d5cf3..7fd461ccbf5 100644 --- a/state-chain/cf-integration-tests/src/authorities.rs +++ b/state-chain/cf-integration-tests/src/authorities.rs @@ -11,6 +11,8 @@ use std::collections::{BTreeSet, HashMap}; use cf_primitives::{AuthorityCount, FlipBalance, GENESIS_EPOCH}; use cf_traits::{AsyncResult, EpochInfo, KeyRotationStatusOuter, KeyRotator}; +use cf_utilities::assert_matches; + use pallet_cf_environment::{PolkadotVaultAccountId, SafeModeUpdate}; use pallet_cf_validator::{CurrentRotationPhase, RotationPhase}; use state_chain_runtime::{ @@ -74,7 +76,7 @@ fn authority_rotates_with_correct_sequence() { testnet.move_to_the_next_epoch(); witness_ethereum_rotation_broadcast(1); - assert!(matches!(Validator::current_rotation_phase(), RotationPhase::Idle)); + assert_matches!(Validator::current_rotation_phase(), RotationPhase::Idle); assert_eq!( AllVaults::status(), AsyncResult::Ready(KeyRotationStatusOuter::RotationComplete) @@ -86,10 +88,10 @@ fn authority_rotates_with_correct_sequence() { // Start the Authority and Vault rotation // idle -> Keygen testnet.move_forward_blocks(4); - assert!(matches!( + assert_matches!( Validator::current_rotation_phase(), RotationPhase::KeygensInProgress(..) - )); + ); // NOTE: This happens due to a bug in `move_forward_blocks`: keygen completes in the // same block in which is was requested. assert_eq!( @@ -99,10 +101,10 @@ fn authority_rotates_with_correct_sequence() { // Key Handover complete. testnet.move_forward_blocks(4); - assert!(matches!( + assert_matches!( Validator::current_rotation_phase(), RotationPhase::KeyHandoversInProgress(..) - )); + ); // NOTE: See above, we skip the pending state. assert_eq!( AllVaults::status(), @@ -112,10 +114,7 @@ fn authority_rotates_with_correct_sequence() { // Activate new key. // The key is immediately activated in the next block testnet.move_forward_blocks(1); - assert!(matches!( - Validator::current_rotation_phase(), - RotationPhase::ActivatingKeys(..) - )); + assert_matches!(Validator::current_rotation_phase(), RotationPhase::ActivatingKeys(..)); // Wait for an extra block to allow TSS to complete, we switch to RotationComplete once // that's done @@ -129,10 +128,10 @@ fn authority_rotates_with_correct_sequence() { // Rotating session testnet.move_forward_blocks(1); - assert!(matches!( + assert_matches!( Validator::current_rotation_phase(), RotationPhase::SessionRotating(..) - )); + ); assert_eq!( AllVaults::status(), AsyncResult::Ready(KeyRotationStatusOuter::RotationComplete) @@ -140,7 +139,7 @@ fn authority_rotates_with_correct_sequence() { // Rotation Completed. testnet.move_forward_blocks(1); - assert!(matches!(Validator::current_rotation_phase(), RotationPhase::Idle)); + assert_matches!(Validator::current_rotation_phase(), RotationPhase::Idle); assert_eq!( AllVaults::status(), AsyncResult::Ready(KeyRotationStatusOuter::RotationComplete) @@ -357,10 +356,10 @@ fn authority_rotation_cannot_be_aborted_after_key_handover_and_completes_even_on // Authority rotation is stalled while in Code Red because of disabling dispatching // witness extrinsics and so witnessing vault rotation will be stalled. - assert!(matches!( + assert_matches!( AllVaults::status(), AsyncResult::Ready(KeyRotationStatusOuter::RotationComplete) - )); + ); testnet.move_forward_blocks(3); assert_eq!(GENESIS_EPOCH + 1, Validator::epoch_index(), "We should be in a new epoch"); }); @@ -383,10 +382,10 @@ fn authority_rotation_can_recover_after_keygen_fails() { testnet.move_to_the_end_of_epoch(); testnet.move_forward_blocks(1); - assert!(matches!( + assert_matches!( Validator::current_rotation_phase(), RotationPhase::KeygensInProgress(..) - )); + ); assert_eq!(AllVaults::status(), AsyncResult::Pending); backup_nodes.iter().for_each(|validator| { assert_ok!(EvmThresholdSigner::report_keygen_outcome( @@ -477,10 +476,10 @@ fn authority_rotation_can_recover_after_key_handover_fails() { }); testnet.move_forward_blocks(1); - assert!(matches!( + assert_matches!( Validator::current_rotation_phase(), RotationPhase::KeyHandoversInProgress(..) - )); + ); assert_eq!( AllVaults::status(), AsyncResult::Ready(KeyRotationStatusOuter::Failed(BTreeSet::default())) @@ -577,31 +576,31 @@ fn waits_for_governance_when_apicall_fails() { // we are still in old epoch assert_eq!(Validator::epoch_index(), epoch_index); // rotation has not completed - assert!(matches!( + assert_matches!( CurrentRotationPhase::::get(), RotationPhase::ActivatingKeys(..) - )); + ); - assert!(matches!( + assert_matches!( PendingVaultActivation::::get().unwrap(), VaultActivationStatus::ActivationFailedAwaitingGovernance { .. } - )); + ); // move forward a few blocks testnet.move_forward_blocks(10); - assert!(matches!( + assert_matches!( PendingVaultActivation::::get().unwrap(), VaultActivationStatus::ActivationFailedAwaitingGovernance { .. } - )); + ); // we are still in old epoch assert_eq!(Validator::epoch_index(), epoch_index); // rotation is still stalled - assert!(matches!( + assert_matches!( CurrentRotationPhase::::get(), RotationPhase::ActivatingKeys(..) - )); + ); // manually setting the activation status to complete completes the rotation. PendingVaultActivation::::put( @@ -611,6 +610,6 @@ fn waits_for_governance_when_apicall_fails() { // we have moved to the new epoch assert_eq!(Validator::epoch_index(), epoch_index + 1); - assert!(matches!(CurrentRotationPhase::::get(), RotationPhase::Idle)); + assert_matches!(CurrentRotationPhase::::get(), RotationPhase::Idle); }); } diff --git a/state-chain/cf-integration-tests/src/new_epoch.rs b/state-chain/cf-integration-tests/src/new_epoch.rs index 27a0eefc4c2..0ff24866125 100644 --- a/state-chain/cf-integration-tests/src/new_epoch.rs +++ b/state-chain/cf-integration-tests/src/new_epoch.rs @@ -8,6 +8,7 @@ use cf_chains::btc::{ }; use cf_primitives::{AccountRole, GENESIS_EPOCH}; use cf_traits::{EpochInfo, KeyProvider}; +use cf_utilities::assert_matches; use frame_support::traits::UnfilteredDispatchable; use pallet_cf_environment::BitcoinAvailableUtxos; use pallet_cf_validator::RotationPhase; @@ -165,14 +166,14 @@ fn epoch_rotates() { testnet.move_to_the_end_of_epoch(); testnet.move_forward_blocks(1); - assert!(matches!( + assert_matches!( Validator::current_rotation_phase(), RotationPhase::KeygensInProgress(..) - )); + ); testnet.move_forward_blocks(VAULT_ROTATION_BLOCKS); - assert!(matches!(Validator::current_rotation_phase(), RotationPhase::Idle)); + assert_matches!(Validator::current_rotation_phase(), RotationPhase::Idle); assert_eq!( GENESIS_EPOCH + 1, diff --git a/state-chain/cf-integration-tests/src/solana.rs b/state-chain/cf-integration-tests/src/solana.rs index 9f4a05d3e73..504fadf3f68 100644 --- a/state-chain/cf-integration-tests/src/solana.rs +++ b/state-chain/cf-integration-tests/src/solana.rs @@ -20,7 +20,7 @@ use cf_chains::{ }; use cf_primitives::{AccountRole, AuthorityCount, ForeignChain, SwapRequestId}; use cf_test_utilities::{assert_events_match, assert_has_matching_event}; -use cf_utilities::bs58_array; +use cf_utilities::{assert_matches, bs58_array}; use codec::Encode; use frame_support::{ assert_err, @@ -257,10 +257,10 @@ fn can_rotate_solana_vault() { testnet.move_forward_blocks(10); // Assert the RotateKey call is built, signed and broadcasted. - assert!(matches!( + assert_matches!( Validator::current_rotation_phase(), RotationPhase::ActivatingKeys(..) - )); + ); System::assert_has_event(RuntimeEvent::SolanaThresholdSigner( pallet_cf_threshold_signature::Event::::ThresholdSignatureSuccess { request_id: 3, @@ -763,14 +763,14 @@ fn solana_ccm_execution_error_can_trigger_fallback() { // on_finalize: reach consensus on the egress vote and trigger the fallback mechanism. SolanaElections::on_finalize(System::block_number() + 1); assert_eq!(pallet_cf_ingress_egress::ScheduledEgressFetchOrTransfer::::decode_len(), Some(1)); - assert!(matches!(pallet_cf_ingress_egress::ScheduledEgressFetchOrTransfer::::get()[0], + assert_matches!(pallet_cf_ingress_egress::ScheduledEgressFetchOrTransfer::::get()[0], FetchOrTransfer::Transfer { egress_id: (ForeignChain::Solana, 2), asset: SolAsset::SolUsdc, destination_address: FALLBACK_ADDRESS, .. } - )); + ); // Ensure the previous broadcast data has been cleaned up. assert!(!pallet_cf_broadcast::PendingBroadcasts::::get().contains(&ccm_broadcast_id)); diff --git a/state-chain/chains/src/btc.rs b/state-chain/chains/src/btc.rs index c4b58b27f17..bdf276a5383 100644 --- a/state-chain/chains/src/btc.rs +++ b/state-chain/chains/src/btc.rs @@ -1298,10 +1298,10 @@ mod test { ]; for (invalid_address, intended_btc_net) in invalid_addresses { - assert!(matches!( + cf_utilities::assert_matches!( ScriptPubkey::try_from_address(invalid_address, &intended_btc_net,), Err(Error::InvalidAddress) - )); + ); } // Test cases from: https://rosettacode.org/wiki/Bitcoin/address_validation diff --git a/state-chain/chains/src/eth.rs b/state-chain/chains/src/eth.rs index c0bf5a35b67..43e7b527acb 100644 --- a/state-chain/chains/src/eth.rs +++ b/state-chain/chains/src/eth.rs @@ -240,7 +240,7 @@ mod lifecycle_tests { macro_rules! expect_deposit_state { ( $state:expr, $asset:expr, $pat:pat ) => { - assert!(matches!( + cf_utilities::assert_matches!( DepositChannel:: { channel_id: Default::default(), address: Default::default(), @@ -249,7 +249,7 @@ mod lifecycle_tests { } .fetch_id(), $pat - )); + ); }; } #[test] diff --git a/state-chain/chains/src/evm/api/all_batch.rs b/state-chain/chains/src/evm/api/all_batch.rs index 7e43ee493ee..7a38d474d4d 100644 --- a/state-chain/chains/src/evm/api/all_batch.rs +++ b/state-chain/chains/src/evm/api/all_batch.rs @@ -61,6 +61,7 @@ mod test_all_batch { AllBatch, FetchAssetParams, }; use cf_primitives::chains::assets; + use cf_utilities::assert_matches; use eth::api::EthereumApi; @@ -225,7 +226,7 @@ mod test_all_batch { .unwrap(); assert_eq!(all_batch.len(), 1usize); - assert!(matches!(all_batch[0].0, EthereumApi::AllBatch(..))); + assert_matches!(all_batch[0].0, EthereumApi::AllBatch(..)); let tx_builder = match &all_batch[0].0 { EthereumApi::AllBatch(tx_builder) => tx_builder.clone(), _ => unreachable!(), diff --git a/state-chain/pallets/cf-funding/Cargo.toml b/state-chain/pallets/cf-funding/Cargo.toml index c35a1c982ce..b8e84838fe5 100644 --- a/state-chain/pallets/cf-funding/Cargo.toml +++ b/state-chain/pallets/cf-funding/Cargo.toml @@ -38,6 +38,7 @@ serde = { workspace = true, features = ["derive", "alloc"] } [dev-dependencies] pallet-cf-flip = { workspace = true, default-features = true } cf-test-utilities = { workspace = true, default-features = true } +cf-utilities = { workspace = true, default-features = true } sp-runtime = { workspace = true, default-features = true } sp-core = { workspace = true, default-features = true } sp-io = { workspace = true, default-features = true } diff --git a/state-chain/pallets/cf-funding/src/tests.rs b/state-chain/pallets/cf-funding/src/tests.rs index ac1970e55ff..6067a132ad7 100644 --- a/state-chain/pallets/cf-funding/src/tests.rs +++ b/state-chain/pallets/cf-funding/src/tests.rs @@ -1013,6 +1013,7 @@ fn redeem_funds_to_restricted_address_overrides_bound_and_executor_restrictions( #[cfg(test)] mod test_restricted_balances { + use cf_utilities::assert_matches; use sp_core::H160; use super::*; @@ -1070,13 +1071,13 @@ mod test_restricted_balances { )); let expected_redeemed_amount = initial_balance - Flip::balance(&ALICE) - RedemptionTax::::get(); - assert!(matches!( + assert_matches!( cf_test_utilities::last_event::(), RuntimeEvent::Funding(Event::RedemptionRequested { account_id, amount, .. - }) if account_id == ALICE && amount == expected_redeemed_amount)); + }) if account_id == ALICE && amount == expected_redeemed_amount); }, Some(e) => { assert_noop!( diff --git a/state-chain/pallets/cf-ingress-egress/Cargo.toml b/state-chain/pallets/cf-ingress-egress/Cargo.toml index 23433b6e87d..ee737bb926d 100644 --- a/state-chain/pallets/cf-ingress-egress/Cargo.toml +++ b/state-chain/pallets/cf-ingress-egress/Cargo.toml @@ -41,6 +41,7 @@ sp-core = { workspace = true, default-features = true } sp-io = { workspace = true, default-features = true } pallet-cf-governance = { workspace = true, default-features = true } cf-test-utilities = { workspace = true, default-features = true } +cf-utilities = { workspace = true, default-features = true } [features] default = ["std"] diff --git a/state-chain/pallets/cf-ingress-egress/src/tests.rs b/state-chain/pallets/cf-ingress-egress/src/tests.rs index 94175a5e4d8..d443693de29 100644 --- a/state-chain/pallets/cf-ingress-egress/src/tests.rs +++ b/state-chain/pallets/cf-ingress-egress/src/tests.rs @@ -43,6 +43,10 @@ use cf_traits::{ BalanceApi, DepositApi, EgressApi, EpochInfo, FetchesTransfersLimitProvider, FundingInfo, GetBlockHeight, SafeMode, ScheduledEgressDetails, SwapOutputAction, SwapRequestType, }; + +#[cfg(test)] +use cf_utilities::assert_matches; + use frame_support::{ assert_err, assert_noop, assert_ok, traits::{Hooks, OriginTrait}, @@ -267,14 +271,14 @@ fn can_schedule_deposit_fetch() { request_address_and_deposit(2u64, EthAsset::Eth); request_address_and_deposit(3u64, EthAsset::Flip); - assert!(matches!( + assert_matches!( &ScheduledEgressFetchOrTransfer::::get()[..], &[ FetchOrTransfer::::Fetch { asset: ETH_ETH, .. }, FetchOrTransfer::::Fetch { asset: ETH_ETH, .. }, FetchOrTransfer::::Fetch { asset: ETH_FLIP, .. }, ] - )); + ); assert_has_event::(RuntimeEvent::IngressEgress(Event::DepositFetchesScheduled { channel_id: 1, @@ -283,7 +287,7 @@ fn can_schedule_deposit_fetch() { request_address_and_deposit(4u64, EthAsset::Eth); - assert!(matches!( + assert_matches!( &ScheduledEgressFetchOrTransfer::::get()[..], &[ FetchOrTransfer::::Fetch { asset: ETH_ETH, .. }, @@ -291,7 +295,7 @@ fn can_schedule_deposit_fetch() { FetchOrTransfer::::Fetch { asset: ETH_FLIP, .. }, FetchOrTransfer::::Fetch { asset: ETH_ETH, .. }, ] - )); + ); }); } @@ -771,10 +775,10 @@ fn multi_use_deposit_same_block() { "Expected one AllBatch apicall to be scheduled for address deployment, got {:?}.", pending_api_calls ); - assert!(matches!( + assert_matches!( pending_callbacks.last().unwrap(), RuntimeCall::IngressEgress(PalletCall::finalise_ingress { .. }) - )); + ); }) .then_execute_at_next_block(|ctx| { MockEgressBroadcaster::dispatch_all_success_callbacks(); diff --git a/state-chain/pallets/cf-threshold-signature/src/benchmarking.rs b/state-chain/pallets/cf-threshold-signature/src/benchmarking.rs index 941b32547fd..b00e2394af5 100644 --- a/state-chain/pallets/cf-threshold-signature/src/benchmarking.rs +++ b/state-chain/pallets/cf-threshold-signature/src/benchmarking.rs @@ -8,6 +8,7 @@ use cf_runtime_utilities::StorageDecodeVariant; use cf_traits::{ AccountRoleRegistry, Chainflip, CurrentEpochIndex, KeyRotationStatusOuter, ThresholdSigner, }; +use cf_utilities::assert_matches; use frame_benchmarking::{account, v2::*, whitelist_account, whitelisted_caller}; use frame_support::{ assert_ok, @@ -163,10 +164,10 @@ mod benchmarks { Pallet::::on_initialize(5u32.into()); } - assert!(matches!( + assert_matches!( as KeyRotator>::status(), AsyncResult::Ready(KeyRotationStatusOuter::Failed(..)) - )); + ); } #[benchmark] @@ -288,11 +289,11 @@ mod benchmarks { KeygenOutcomeFor::::Ok(AggKeyFor::::benchmark_value()), ); - assert!(matches!( + assert_matches!( PendingKeyRotation::::get().unwrap(), KeyRotationStatus::AwaitingKeygen { response_status, .. } if response_status.remaining_candidate_count() == 149 - )) + ); } #[benchmark] @@ -322,11 +323,11 @@ mod benchmarks { assert_ok!(call.dispatch_bypass_filter(origin.into())); } - assert!(matches!( + assert_matches!( PendingKeyRotation::::get().unwrap(), KeyRotationStatus::KeygenVerificationComplete { new_public_key } if new_public_key == agg_key - )) + ); } // NOTE: Test suite not included because of dependency mismatch between benchmarks and mocks. diff --git a/state-chain/pallets/cf-threshold-signature/src/mock.rs b/state-chain/pallets/cf-threshold-signature/src/mock.rs index 0e018f26f45..5864ef307a4 100644 --- a/state-chain/pallets/cf-threshold-signature/src/mock.rs +++ b/state-chain/pallets/cf-threshold-signature/src/mock.rs @@ -15,6 +15,7 @@ use cf_traits::{ AccountRoleRegistry, AsyncResult, KeyProvider, Slashing, StartKeyActivationResult, ThresholdSigner, VaultActivator, }; +use cf_utilities::assert_matches; use codec::{Decode, Encode}; use frame_support::dispatch::DispatchResultWithPostInfo; pub use frame_support::{ @@ -71,10 +72,10 @@ impl MockCallback { pub fn call(self) { match self { Self::Regular(request_id, _) => { - assert!(matches!( + assert_matches!( >::signature_result(request_id).1, AsyncResult::Ready(..) - )); + ); CALL_DISPATCHED.with(|cell| *(cell.borrow_mut()) = Some(request_id)); }, Self::Keygen(call) => { @@ -285,10 +286,10 @@ impl TestHelper for TestRunner<()> { assert_eq!(current_ceremony_id(), initial_ceremony_id); } - assert!(matches!( + assert_matches!( EvmThresholdSigner::signer_and_signature(request_id).unwrap().signature_result, AsyncResult::Pending - )); + ); }) } @@ -307,10 +308,10 @@ impl TestHelper for TestRunner<()> { pending.remaining_respondents, BTreeSet::from_iter(MockNominator::get_nominees().unwrap_or_default()) ); - assert!(matches!( + assert_matches!( EvmThresholdSigner::signer_and_signature(request_id).unwrap().signature_result, AsyncResult::Pending - )); + ); assert!(EvmThresholdSigner::request_callback(request_id).is_some()); }) } diff --git a/state-chain/pallets/cf-threshold-signature/src/response_status.rs b/state-chain/pallets/cf-threshold-signature/src/response_status.rs index 0ec5c8e8802..f16c8def60a 100644 --- a/state-chain/pallets/cf-threshold-signature/src/response_status.rs +++ b/state-chain/pallets/cf-threshold-signature/src/response_status.rs @@ -147,6 +147,7 @@ mod tests { AggKeyFor, KeygenOutcomeFor, }; use cf_chains::mocks::MockAggKey; + use cf_utilities::assert_matches; use frame_support::assert_ok; use sp_std::collections::btree_set::BTreeSet; @@ -368,16 +369,16 @@ mod tests { // A keygen where more than `threshold` nodes have reported failure, but there is no // final agreement on the guilty parties. Only unresponsive nodes will be reported. - assert!(matches!( + assert_matches!( get_outcome( &n_times([(17, ReportedOutcome::Failure), (7, ReportedOutcome::Timeout)]), |id| if id < 16 { [17] } else { [16] } ), Err(blamed) if blamed == BTreeSet::from_iter(18..=24) - )); + ); // As above, but some nodes have reported the wrong outcome. - assert!(matches!( + assert_matches!( get_outcome( &n_times([ (17, ReportedOutcome::Failure), @@ -388,10 +389,10 @@ mod tests { |id| if id < 16 { [17] } else { [16] } ), Err(blamed) if blamed == BTreeSet::from_iter(18..=24) - )); + ); // As above, but some nodes have additionally been voted on. - assert!(matches!( + assert_matches!( get_outcome( &n_times([ (18, ReportedOutcome::Failure), @@ -402,7 +403,7 @@ mod tests { |id| if id > 16 { [1, 2] } else { [17, 18] } ), Err(blamed) if blamed == BTreeSet::from_iter(17..=24) - )); + ); }); } @@ -420,30 +421,30 @@ mod tests { ); // First five candidates all report candidate 6, candidate 6 reports 1. - assert!(matches!( + assert_matches!( get_outcome(&reported_outcomes(b"ffffft"), |id| if id == 6 { [1] } else { [6] }), Err(blamed) if blamed == BTreeSet::from_iter([6]) - )); + ); // First five candidates all report nobody, candidate 6 unresponsive. - assert!(matches!( + assert_matches!( get_outcome(&reported_outcomes(b"ffffft"), |_| []), Err(blamed) if blamed == BTreeSet::from_iter([6]) - )); + ); // Candidates 3 and 6 unresponsive. - assert!(matches!( + assert_matches!( get_outcome(&reported_outcomes(b"fftfft"), |_| []), Err(blamed) if blamed == BTreeSet::from_iter([3, 6]) - )); + ); // One candidate unresponsive, one blamed by majority. - assert!(matches!( + assert_matches!( get_outcome(&reported_outcomes(b"ffffftf"), |id| if id != 3 { [3] } else { [4] }), Err(blamed) if blamed == BTreeSet::from_iter([3, 6]) - )); + ); // One candidate unresponsive, one rogue blames everyone else. - assert!(matches!( + assert_matches!( get_outcome(&reported_outcomes(b"ffffftf"), |id| { if id != 3 { vec![3, 6] @@ -452,37 +453,37 @@ mod tests { } }), Err(blamed) if blamed == BTreeSet::from_iter([3, 6]) - )); + ); let failures = |n| n_times([(n, ReportedOutcome::Failure)]); // Candidates don't agree. - assert!(matches!( + assert_matches!( get_outcome(&failures(6), |id| [(id + 1) % 6]), Err(blamed) if blamed.is_empty() - )); + ); // Candidate agreement is below reporting threshold. - assert!(matches!( + assert_matches!( get_outcome(&failures(6), |id| if id < 4 { [6] } else { [2] }), Err(blamed) if blamed.is_empty() - )); + ); // Candidates agreement just above threshold. - assert!(matches!( + assert_matches!( get_outcome(&failures(6), |id| if id == 6 { [1] } else { [6] }), Err(blamed) if blamed == BTreeSet::from_iter([6]) - )); + ); // Candidates agree on multiple offenders. - assert!(matches!( + assert_matches!( get_outcome(&failures(12), |id| if id < 9 { [11, 12] } else { [1, 2] }), Err(blamed) if blamed == BTreeSet::from_iter([11, 12]) - )); + ); // Overlapping agreement - no agreement on the entire set but in aggregate we can // determine offenders. - assert!(matches!( + assert_matches!( get_outcome(&failures(12), |id| { if id < 5 { [11, 12] @@ -493,13 +494,13 @@ mod tests { } }), Err(blamed) if blamed == BTreeSet::from_iter([1, 11]) - )); + ); // Unresponsive and dissenting nodes are reported. - assert!(matches!( + assert_matches!( get_outcome(&reported_outcomes(b"tfffsfffbffft"), |_| []), Err(blamed) if blamed == BTreeSet::from_iter([1, 5, 9, 13]) - )); + ); }); } } diff --git a/state-chain/pallets/cf-threshold-signature/src/tests.rs b/state-chain/pallets/cf-threshold-signature/src/tests.rs index 597b41e575b..4c6013d0708 100644 --- a/state-chain/pallets/cf-threshold-signature/src/tests.rs +++ b/state-chain/pallets/cf-threshold-signature/src/tests.rs @@ -20,6 +20,7 @@ use cf_traits::{ AccountRoleRegistry, AsyncResult, Chainflip, EpochInfo, EpochKey, KeyProvider, KeyRotationStatusOuter, KeyRotator, SetSafeMode, VaultActivator, }; +use cf_utilities::assert_matches; pub use frame_support::traits::Get; use cfe_events::{KeyHandoverRequest, KeygenRequest, ThresholdSignatureRequest}; @@ -179,12 +180,12 @@ fn happy_path_no_callback() { assert!(EvmThresholdSigner::pending_ceremonies(ceremony_id).is_none()); // Signature is available - assert!(matches!( + assert_matches!( EvmThresholdSigner::signer_and_signature(request_context.request_id) .unwrap() .signature_result, AsyncResult::Ready(..) - )); + ); // No callback was provided. assert!(!MockCallback::has_executed(request_context.request_id)); @@ -873,10 +874,10 @@ fn keygen_success_triggers_keygen_verification() { >>::on_initialize(1); - assert!(matches!( + assert_matches!( PendingKeyRotation::::get().unwrap(), KeyRotationStatus::AwaitingKeygenVerification { .. } - )); + ); }); } @@ -909,10 +910,10 @@ fn handover_success_triggers_handover_verification() { >>::on_initialize(1); - assert!(matches!( + assert_matches!( PendingKeyRotation::::get().unwrap(), KeyRotationStatus::AwaitingKeyHandoverVerification { .. } - )); + ); }); } @@ -1312,10 +1313,10 @@ fn do_full_key_rotation() { } >>::on_initialize(1); - assert!(matches!( + assert_matches!( PendingKeyRotation::::get().unwrap(), KeyRotationStatus::AwaitingKeygenVerification { .. } - )); + ); let cfes = [ALICE] .iter() @@ -1328,10 +1329,10 @@ fn do_full_key_rotation() { AsyncResult::Ready(KeyRotationStatusOuter::KeygenComplete) ); - assert!(matches!( + assert_matches!( PendingKeyRotation::::get().unwrap(), KeyRotationStatus::KeygenVerificationComplete { .. } - )); + ); const SHARING_PARTICIPANTS: [u64; 2] = [ALICE, BOB]; EvmThresholdSigner::key_handover( @@ -1355,10 +1356,10 @@ fn do_full_key_rotation() { assert_last_events!(Event::ThresholdSignatureRequest { .. }, Event::KeyHandoverSuccess { .. }); - assert!(matches!( + assert_matches!( PendingKeyRotation::::get().unwrap(), KeyRotationStatus::AwaitingKeyHandoverVerification { .. } - )); + ); run_cfes_on_sc_events(&cfes); @@ -1372,10 +1373,10 @@ fn do_full_key_rotation() { Event::KeyHandoverVerificationSuccess { .. } ); - assert!(matches!( + assert_matches!( PendingKeyRotation::::get().unwrap(), KeyRotationStatus::KeyHandoverComplete { .. } - )); + ); // Called by validator pallet EvmThresholdSigner::activate_keys(); @@ -1628,10 +1629,10 @@ mod key_rotation { EvmThresholdSigner::activate_keys(); EvmThresholdSigner::status(); - assert!(matches!( + assert_matches!( PendingKeyRotation::::get().unwrap(), KeyRotationStatus::Complete, - )); + ); }); final_checks(ext); } @@ -1639,10 +1640,10 @@ mod key_rotation { #[test] fn can_recover_after_handover_failure() { let ext = setup(Err(Default::default())).execute_with(|| { - assert!(matches!( + assert_matches!( PendingKeyRotation::::get().unwrap(), KeyRotationStatus::KeyHandoverFailed { .. } - )); + ); // Start handover again, but successful this time. let btree_candidates = BTreeSet::from_iter(ALL_CANDIDATES.iter().cloned()); @@ -1678,10 +1679,10 @@ mod key_rotation { #[test] fn key_handover_success_triggers_key_handover_verification() { setup(Ok(NEW_AGG_PUB_KEY_POST_HANDOVER)).execute_with(|| { - assert!(matches!( + assert_matches!( PendingKeyRotation::::get(), Some(KeyRotationStatus::AwaitingKeyHandoverVerification { .. }) - )); + ); }); } @@ -1689,10 +1690,10 @@ mod key_rotation { fn key_handover_fails_on_key_mismatch() { setup(Ok(BAD_AGG_KEY_POST_HANDOVER)).execute_with(|| { assert_last_events!(Event::KeyHandoverFailure { .. }); - assert!(matches!( + assert_matches!( PendingKeyRotation::::get(), Some(KeyRotationStatus::KeyHandoverFailed { .. }) - )); + ); }); } @@ -1819,10 +1820,10 @@ fn can_recover_from_abort_key_rotation_after_failed_key_gen() { Err(Default::default()) )); >>::on_initialize(2); - assert!(matches!( + assert_matches!( PendingKeyRotation::::get(), Some(KeyRotationStatus::Failed { .. }) - )); + ); // Abort by resetting key rotation state EvmThresholdSigner::reset_key_rotation(); @@ -1862,10 +1863,10 @@ fn can_recover_from_abort_key_rotation_after_key_verification() { .collect::>(); run_cfes_on_sc_events(&cfes); - assert!(matches!( + assert_matches!( PendingKeyRotation::::get(), Some(KeyRotationStatus::KeygenVerificationComplete { .. }) - )); + ); // Abort the key rotation now EvmThresholdSigner::reset_key_rotation(); @@ -1923,10 +1924,10 @@ fn can_recover_from_abort_key_rotation_after_key_handover_failed() { } >>::on_initialize(2); - assert!(matches!( + assert_matches!( PendingKeyRotation::::get(), Some(KeyRotationStatus::KeyHandoverFailed { .. }) - )); + ); // Abort by resetting key rotation state EvmThresholdSigner::reset_key_rotation(); diff --git a/state-chain/pallets/cf-validator/src/benchmarking.rs b/state-chain/pallets/cf-validator/src/benchmarking.rs index 9cb59c58b7d..54d8cf58a14 100644 --- a/state-chain/pallets/cf-validator/src/benchmarking.rs +++ b/state-chain/pallets/cf-validator/src/benchmarking.rs @@ -8,6 +8,7 @@ use pallet_session::Config as SessionConfig; use cf_primitives::AccountRole; use cf_traits::{AccountRoleRegistry, KeyRotationStatusOuter, SafeMode, SetSafeMode}; +use cf_utilities::assert_matches; use frame_benchmarking::v2::*; use frame_support::{ assert_ok, @@ -98,7 +99,7 @@ pub fn try_start_keygen( bond: 100u32.into(), })); - assert!(matches!(CurrentRotationPhase::::get(), RotationPhase::KeygensInProgress(..))); + assert_matches!(CurrentRotationPhase::::get(), RotationPhase::KeygensInProgress(..)); } #[allow(clippy::multiple_bound_locations)] @@ -243,7 +244,7 @@ mod benchmarks { Pallet::::start_authority_rotation(); } - assert!(matches!(CurrentRotationPhase::::get(), RotationPhase::KeygensInProgress(..))); + assert_matches!(CurrentRotationPhase::::get(), RotationPhase::KeygensInProgress(..)); } #[benchmark] @@ -255,8 +256,8 @@ mod benchmarks { Pallet::::start_authority_rotation(); } - assert!(matches!(::SafeMode::get(), SafeMode::CODE_RED)); - assert!(matches!(CurrentRotationPhase::::get(), RotationPhase::Idle)); + assert_matches!(::SafeMode::get(), SafeMode::CODE_RED); + assert_matches!(CurrentRotationPhase::::get(), RotationPhase::Idle); } /**** 2. RotationPhase::KeygensInProgress *** */ @@ -288,10 +289,10 @@ mod benchmarks { Pallet::::on_initialize(1u32.into()); } - assert!(matches!( + assert_matches!( CurrentRotationPhase::::get(), RotationPhase::KeyHandoversInProgress(..) - )); + ); } #[benchmark] @@ -302,16 +303,16 @@ mod benchmarks { let block = frame_system::Pallet::::current_block_number(); - assert!(matches!(CurrentRotationPhase::::get(), RotationPhase::KeygensInProgress(..))); + assert_matches!(CurrentRotationPhase::::get(), RotationPhase::KeygensInProgress(..)); T::KeyRotator::set_status(AsyncResult::Ready(KeyRotationStatusOuter::KeygenComplete)); Pallet::::on_initialize(block); - assert!(matches!( + assert_matches!( CurrentRotationPhase::::get(), RotationPhase::KeyHandoversInProgress(..) - )); + ); T::KeyRotator::set_status(AsyncResult::Ready(KeyRotationStatusOuter::KeyHandoverComplete)); @@ -324,7 +325,7 @@ mod benchmarks { Pallet::::on_initialize(1u32.into()); } - assert!(matches!(CurrentRotationPhase::::get(), RotationPhase::NewKeysActivated(..))); + assert_matches!(CurrentRotationPhase::::get(), RotationPhase::NewKeysActivated(..)); } #[benchmark] diff --git a/state-chain/pallets/cf-validator/src/tests.rs b/state-chain/pallets/cf-validator/src/tests.rs index 6204c5e4110..912cfee5ef4 100644 --- a/state-chain/pallets/cf-validator/src/tests.rs +++ b/state-chain/pallets/cf-validator/src/tests.rs @@ -13,7 +13,7 @@ use cf_traits::{ }, AccountRoleRegistry, SafeMode, SetSafeMode, }; -use cf_utilities::success_threshold_from_share_count; +use cf_utilities::{assert_matches, success_threshold_from_share_count}; use frame_support::{ assert_noop, assert_ok, error::BadOrigin, @@ -131,24 +131,24 @@ fn should_retry_rotation_until_success_with_failing_auctions() { }) // Now that we have bidders, we should succeed the auction, and complete the rotation .then_advance_n_blocks_and_execute_with_checks(1, || { - assert!(matches!( + assert_matches!( CurrentRotationPhase::::get(), RotationPhase::::KeygensInProgress(..) - )); + ); MockKeyRotatorA::keygen_success(); }) .then_advance_n_blocks_and_execute_with_checks(2, || { - assert!(matches!( + assert_matches!( CurrentRotationPhase::::get(), RotationPhase::::KeyHandoversInProgress(..) - )); + ); MockKeyRotatorA::key_handover_success(); }) .then_advance_n_blocks_and_execute_with_checks(2, || { - assert!(matches!( + assert_matches!( CurrentRotationPhase::::get(), RotationPhase::::ActivatingKeys(..) - )); + ); MockKeyRotatorA::keys_activated(); }) .then_advance_n_blocks_and_execute_with_checks(2, || { @@ -721,10 +721,10 @@ fn auction_params_must_be_valid_when_set() { } )); // Confirm we have an event - assert!(matches!( + assert_matches!( last_event::(), mock::RuntimeEvent::ValidatorPallet(Event::PalletConfigUpdated { .. }), - )); + ); }); } diff --git a/state-chain/pallets/cf-vaults/src/tests.rs b/state-chain/pallets/cf-vaults/src/tests.rs index a37df8800c2..e2b1aed903b 100644 --- a/state-chain/pallets/cf-vaults/src/tests.rs +++ b/state-chain/pallets/cf-vaults/src/tests.rs @@ -9,6 +9,7 @@ use cf_traits::{ mocks::block_height_provider::BlockHeightProvider, AsyncResult, EpochInfo, EpochTransitionHandler, VaultActivator, }; +use cf_utilities::assert_matches; use frame_support::assert_noop; use std::collections::BTreeSet; @@ -45,10 +46,10 @@ fn when_set_agg_key_with_agg_key_not_required_we_skip_to_completion() { VaultsPallet::start_key_activation(NEW_AGG_PUBKEY, Some(Default::default())); - assert!(matches!( + assert_matches!( PendingVaultActivation::::get().unwrap(), VaultActivationStatus::Complete - )) + ); }); } @@ -66,10 +67,10 @@ fn vault_start_block_number_is_set_correctly() { .unwrap(), 1001 ); - assert!(matches!( + assert_matches!( PendingVaultActivation::::get().unwrap(), VaultActivationStatus::Complete - )); + ); assert_last_event!(Event::VaultActivationCompleted); }); } @@ -83,10 +84,10 @@ fn vault_start_block_number_not_set_when_chain_not_initialized() { VaultsPallet::start_key_activation(NEW_AGG_PUBKEY, Some(Default::default())); VaultsPallet::activate_key(); assert!(VaultStartBlockNumbers::::iter_keys().next().is_none()); - assert!(matches!( + assert_matches!( PendingVaultActivation::::get().unwrap(), VaultActivationStatus::Complete - )); + ); }); } diff --git a/utilities/src/lib.rs b/utilities/src/lib.rs index 1b24c4d29b1..61ae1e548c1 100644 --- a/utilities/src/lib.rs +++ b/utilities/src/lib.rs @@ -33,6 +33,13 @@ macro_rules! assert_err { }; } +#[macro_export] +macro_rules! assert_matches { + ($left:expr, $pattern:pat $(if $guard:expr)?$(,)?) => { + assert!(matches!($left, $pattern $(if $guard)?)) + }; +} + /// Note that the resulting `threshold` is the maximum number of parties *not* enough to generate a /// signature, /// @@ -295,4 +302,24 @@ mod test_asserts { fn test_assert_ok_err() { assert_panics!(assert_ok!(Err::(1))); } + + #[test] + fn test_assert_matches() { + #[allow(dead_code)] + struct Foo { + pub a: u8, + pub b: u8, + } + #[allow(dead_code)] + enum Bar { + A(u8), + B(String), + } + assert_panics!(assert_matches!(Some(Bar::A(6u8)), Some(Bar::B(..)))); + assert_panics!(assert_matches!(Some(Bar::A(6u8)), Some(Bar::A(value)) if value == 5u8)); + + assert_matches!(Some(vec![0x01]), Some(..)); + + assert_matches!(Some(Foo { a: 1u8, b: 2u8 }), Some(Foo { a: 1u8, .. })); + } } diff --git a/utilities/src/with_std/dynamic_events.rs b/utilities/src/with_std/dynamic_events.rs index 24d9b7e33da..132dc1c8047 100644 --- a/utilities/src/with_std/dynamic_events.rs +++ b/utilities/src/with_std/dynamic_events.rs @@ -430,13 +430,13 @@ mod test { raw_error, outcome(failed_1), ); - assert!(matches!( + crate::assert_matches!( outcome(failed_2).unwrap_err(), DispatchError::KnownModuleError { pallet, name, - error + error, } if pallet == ERROR_PALLET && name == ERROR_NAME && error == ERROR - )); + ); } }