Merge bitcoindevkit/bdk#821: [#344] Add assert_matches

14bc9c0e356ac1c864e7c37aaadfe4696e999693 [#344] Add assert_matches Replace assert!(matches! with assert_matches! everywhere Convert assert! to assert_eq! in 2 places (Jeremy Mawson)

Pull request description:

  [#344] Add assert_matches

ACKs for top commit:
  notmandatory:
    ACK 14bc9c0e356ac1c864e7c37aaadfe4696e999693
  danielabrozzoni:
    utACK 14bc9c0e356ac1c864e7c37aaadfe4696e999693

Tree-SHA512: 730fed9c8c22b0725b1337140636def1a059ac78e4ae16f1abd4c7f379628d9329ccd3ed28e4cbab58e9ace5f349333cb5fa83ec43d507d7a7609601efebc9e1
This commit is contained in:
Steve Myers 2022-12-26 13:38:11 -08:00
commit 5f0870a741
No known key found for this signature in database
GPG Key ID: 8105A46B22C2D051
13 changed files with 152 additions and 228 deletions

View File

@ -109,6 +109,7 @@ env_logger = "0.7"
electrsd = "0.21" electrsd = "0.21"
# Move back to importing from rust-bitcoin once https://github.com/rust-bitcoin/rust-bitcoin/pull/1342 is released # Move back to importing from rust-bitcoin once https://github.com/rust-bitcoin/rust-bitcoin/pull/1342 is released
base64 = "^0.13" base64 = "^0.13"
assert_matches = "1.5.0"
[[example]] [[example]]
name = "compact_filters_balance" name = "compact_filters_balance"

View File

@ -136,7 +136,7 @@ impl CfSync {
let resp = peer.get_cf_headers(0x00, start_height as u32, stop_hash)?; let resp = peer.get_cf_headers(0x00, start_height as u32, stop_hash)?;
assert!(resp.previous_filter_header == checkpoint); assert_eq!(resp.previous_filter_header, checkpoint);
status = status =
self.cf_store self.cf_store
.advance_to_cf_headers(index, checkpoint, resp.filter_hashes)?; .advance_to_cf_headers(index, checkpoint, resp.filter_hashes)?;

View File

@ -1137,12 +1137,10 @@ pub mod test {
let child: u32 = row.get(1).unwrap(); let child: u32 = row.get(1).unwrap();
let count: usize = row.get(2).unwrap(); let count: usize = row.get(2).unwrap();
assert!( assert_eq!(
count == 1, count, 1,
"keychain={}, child={}, count={}", "keychain={}, child={}, count={}",
keychain, keychain, child, count
child,
count
); );
} }
} }

View File

@ -133,6 +133,7 @@ pub fn get_checksum(desc: &str) -> Result<String, DescriptorError> {
mod test { mod test {
use super::*; use super::*;
use crate::descriptor::calc_checksum; use crate::descriptor::calc_checksum;
use assert_matches::assert_matches;
// test calc_checksum() function; it should return the same value as Bitcoin Core // test calc_checksum() function; it should return the same value as Bitcoin Core
#[test] #[test]
@ -155,16 +156,16 @@ mod test {
assert_eq!(calc_checksum(desc).unwrap(), "lasegmfs"); assert_eq!(calc_checksum(desc).unwrap(), "lasegmfs");
let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)#tqz0nc26"; let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)#tqz0nc26";
assert!(matches!( assert_matches!(
calc_checksum(desc).err(), calc_checksum(desc),
Some(DescriptorError::InvalidDescriptorChecksum) Err(DescriptorError::InvalidDescriptorChecksum)
)); );
let desc = "pkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/44'/1'/0'/0/*)#lasegmsf"; let desc = "pkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/44'/1'/0'/0/*)#lasegmsf";
assert!(matches!( assert_matches!(
calc_checksum(desc).err(), calc_checksum(desc),
Some(DescriptorError::InvalidDescriptorChecksum) Err(DescriptorError::InvalidDescriptorChecksum)
)); );
} }
#[test] #[test]
@ -172,9 +173,9 @@ mod test {
let sparkle_heart = unsafe { std::str::from_utf8_unchecked(&[240, 159, 146, 150]) }; let sparkle_heart = unsafe { std::str::from_utf8_unchecked(&[240, 159, 146, 150]) };
let invalid_desc = format!("wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcL{}fjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)", sparkle_heart); let invalid_desc = format!("wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcL{}fjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)", sparkle_heart);
assert!(matches!( assert_matches!(
calc_checksum(&invalid_desc).err(), calc_checksum(&invalid_desc),
Some(DescriptorError::InvalidDescriptorCharacter(invalid_char)) if invalid_char == sparkle_heart.as_bytes()[0] Err(DescriptorError::InvalidDescriptorCharacter(invalid_char)) if invalid_char == sparkle_heart.as_bytes()[0]
)); );
} }
} }

View File

@ -581,6 +581,7 @@ impl DescriptorMeta for ExtendedDescriptor {
mod test { mod test {
use std::str::FromStr; use std::str::FromStr;
use assert_matches::assert_matches;
use bitcoin::consensus::encode::deserialize; use bitcoin::consensus::encode::deserialize;
use bitcoin::hashes::hex::FromHex; use bitcoin::hashes::hex::FromHex;
use bitcoin::secp256k1::Secp256k1; use bitcoin::secp256k1::Secp256k1;
@ -763,17 +764,11 @@ mod test {
let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)#67ju93jw" let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)#67ju93jw"
.into_wallet_descriptor(&secp, Network::Testnet); .into_wallet_descriptor(&secp, Network::Testnet);
assert!(matches!( assert_matches!(desc, Err(DescriptorError::InvalidDescriptorChecksum));
desc.err(),
Some(DescriptorError::InvalidDescriptorChecksum)
));
let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)#67ju93jw" let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)#67ju93jw"
.into_wallet_descriptor(&secp, Network::Testnet); .into_wallet_descriptor(&secp, Network::Testnet);
assert!(matches!( assert_matches!(desc, Err(DescriptorError::InvalidDescriptorChecksum));
desc.err(),
Some(DescriptorError::InvalidDescriptorChecksum)
));
} }
// test IntoWalletDescriptor trait from &str with keys from right and wrong network // test IntoWalletDescriptor trait from &str with keys from right and wrong network
@ -807,17 +802,11 @@ mod test {
let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)" let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)"
.into_wallet_descriptor(&secp, Network::Bitcoin); .into_wallet_descriptor(&secp, Network::Bitcoin);
assert!(matches!( assert_matches!(desc, Err(DescriptorError::Key(KeyError::InvalidNetwork)));
desc.err(),
Some(DescriptorError::Key(KeyError::InvalidNetwork))
));
let desc = "wpkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/1/2/*)" let desc = "wpkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/1/2/*)"
.into_wallet_descriptor(&secp, Network::Bitcoin); .into_wallet_descriptor(&secp, Network::Bitcoin);
assert!(matches!( assert_matches!(desc, Err(DescriptorError::Key(KeyError::InvalidNetwork)));
desc.err(),
Some(DescriptorError::Key(KeyError::InvalidNetwork))
));
} }
// test IntoWalletDescriptor trait from the output of the descriptor!() macro // test IntoWalletDescriptor trait from the output of the descriptor!() macro
@ -851,11 +840,7 @@ mod test {
let descriptor = "wpkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/0'/1/2/*)"; let descriptor = "wpkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/0'/1/2/*)";
let result = into_wallet_descriptor_checked(descriptor, &secp, Network::Testnet); let result = into_wallet_descriptor_checked(descriptor, &secp, Network::Testnet);
assert!(result.is_err()); assert_matches!(result, Err(DescriptorError::HardenedDerivationXpub));
assert!(matches!(
result.unwrap_err(),
DescriptorError::HardenedDerivationXpub
));
let descriptor = "wsh(multi(2,tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/0/*,tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/0/*))"; let descriptor = "wsh(multi(2,tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/0/*,tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/0/*))";
let result = into_wallet_descriptor_checked(descriptor, &secp, Network::Testnet); let result = into_wallet_descriptor_checked(descriptor, &secp, Network::Testnet);

View File

@ -1139,6 +1139,7 @@ mod test {
use crate::descriptor::policy::SatisfiableItem::{EcdsaSignature, Multisig, Thresh}; use crate::descriptor::policy::SatisfiableItem::{EcdsaSignature, Multisig, Thresh};
use crate::keys::{DescriptorKey, IntoDescriptorKey}; use crate::keys::{DescriptorKey, IntoDescriptorKey};
use crate::wallet::signer::SignersContainer; use crate::wallet::signer::SignersContainer;
use assert_matches::assert_matches;
use bitcoin::secp256k1::Secp256k1; use bitcoin::secp256k1::Secp256k1;
use bitcoin::util::bip32; use bitcoin::util::bip32;
use bitcoin::Network; use bitcoin::Network;
@ -1182,8 +1183,8 @@ mod test {
.unwrap() .unwrap()
.unwrap(); .unwrap();
assert!(matches!(&policy.item, EcdsaSignature(PkOrF::Fingerprint(f)) if f == &fingerprint)); assert_matches!(&policy.item, EcdsaSignature(PkOrF::Fingerprint(f)) if f == &fingerprint);
assert!(matches!(&policy.contribution, Satisfaction::None)); assert_matches!(&policy.contribution, Satisfaction::None);
let desc = descriptor!(wpkh(prvkey)).unwrap(); let desc = descriptor!(wpkh(prvkey)).unwrap();
let (wallet_desc, keymap) = desc let (wallet_desc, keymap) = desc
@ -1195,10 +1196,8 @@ mod test {
.unwrap() .unwrap()
.unwrap(); .unwrap();
assert!(matches!(&policy.item, EcdsaSignature(PkOrF::Fingerprint(f)) if f == &fingerprint)); assert_matches!(&policy.item, EcdsaSignature(PkOrF::Fingerprint(f)) if f == &fingerprint);
assert!( assert_matches!(&policy.contribution, Satisfaction::Complete {condition} if condition.csv == None && condition.timelock == None);
matches!(&policy.contribution, Satisfaction::Complete {condition} if condition.csv == None && condition.timelock == None)
);
} }
// 2 pub keys descriptor, required 2 prv keys // 2 pub keys descriptor, required 2 prv keys
@ -1217,19 +1216,16 @@ mod test {
.unwrap() .unwrap()
.unwrap(); .unwrap();
assert!( assert_matches!(&policy.item, Multisig { keys, threshold } if threshold == &2usize
matches!(&policy.item, Multisig { keys, threshold } if threshold == &2usize
&& keys[0] == PkOrF::Fingerprint(fingerprint0) && keys[0] == PkOrF::Fingerprint(fingerprint0)
&& keys[1] == PkOrF::Fingerprint(fingerprint1)) && keys[1] == PkOrF::Fingerprint(fingerprint1)
); );
// TODO should this be "Satisfaction::None" since we have no prv keys? // TODO should this be "Satisfaction::None" since we have no prv keys?
// TODO should items and conditions not be empty? // TODO should items and conditions not be empty?
assert!( assert_matches!(&policy.contribution, Satisfaction::Partial { n, m, items, conditions, ..} if n == &2usize
matches!(&policy.contribution, Satisfaction::Partial { n, m, items, conditions, ..} if n == &2usize
&& m == &2usize && m == &2usize
&& items.is_empty() && items.is_empty()
&& conditions.is_empty() && conditions.is_empty()
)
); );
} }
@ -1248,18 +1244,15 @@ mod test {
.extract_policy(&signers_container, BuildSatisfaction::None, &secp) .extract_policy(&signers_container, BuildSatisfaction::None, &secp)
.unwrap() .unwrap()
.unwrap(); .unwrap();
assert!( assert_matches!(&policy.item, Multisig { keys, threshold } if threshold == &2usize
matches!(&policy.item, Multisig { keys, threshold } if threshold == &2usize
&& keys[0] == PkOrF::Fingerprint(fingerprint0) && keys[0] == PkOrF::Fingerprint(fingerprint0)
&& keys[1] == PkOrF::Fingerprint(fingerprint1)) && keys[1] == PkOrF::Fingerprint(fingerprint1)
); );
assert!( assert_matches!(&policy.contribution, Satisfaction::Partial { n, m, items, conditions, ..} if n == &2usize
matches!(&policy.contribution, Satisfaction::Partial { n, m, items, conditions, ..} if n == &2usize
&& m == &2usize && m == &2usize
&& items.len() == 1 && items.len() == 1
&& conditions.contains_key(&0) && conditions.contains_key(&0)
)
); );
} }
@ -1281,18 +1274,15 @@ mod test {
.unwrap() .unwrap()
.unwrap(); .unwrap();
assert!( assert_matches!(&policy.item, Multisig { keys, threshold } if threshold == &1
matches!(&policy.item, Multisig { keys, threshold } if threshold == &1
&& keys[0] == PkOrF::Fingerprint(fingerprint0) && keys[0] == PkOrF::Fingerprint(fingerprint0)
&& keys[1] == PkOrF::Fingerprint(fingerprint1)) && keys[1] == PkOrF::Fingerprint(fingerprint1)
); );
assert!( assert_matches!(&policy.contribution, Satisfaction::PartialComplete { n, m, items, conditions, .. } if n == &2
matches!(&policy.contribution, Satisfaction::PartialComplete { n, m, items, conditions, .. } if n == &2
&& m == &1 && m == &1
&& items.len() == 2 && items.len() == 2
&& conditions.contains_key(&vec![0]) && conditions.contains_key(&vec![0])
&& conditions.contains_key(&vec![1]) && conditions.contains_key(&vec![1])
)
); );
} }
@ -1313,18 +1303,15 @@ mod test {
.unwrap() .unwrap()
.unwrap(); .unwrap();
assert!( assert_matches!(&policy.item, Multisig { keys, threshold } if threshold == &2
matches!(&policy.item, Multisig { keys, threshold } if threshold == &2
&& keys[0] == PkOrF::Fingerprint(fingerprint0) && keys[0] == PkOrF::Fingerprint(fingerprint0)
&& keys[1] == PkOrF::Fingerprint(fingerprint1)) && keys[1] == PkOrF::Fingerprint(fingerprint1)
); );
assert!( assert_matches!(&policy.contribution, Satisfaction::PartialComplete { n, m, items, conditions, .. } if n == &2
matches!(&policy.contribution, Satisfaction::PartialComplete { n, m, items, conditions, .. } if n == &2
&& m == &2 && m == &2
&& items.len() == 2 && items.len() == 2
&& conditions.contains_key(&vec![0,1]) && conditions.contains_key(&vec![0,1])
)
); );
} }
@ -1345,8 +1332,8 @@ mod test {
.unwrap() .unwrap()
.unwrap(); .unwrap();
assert!(matches!(&policy.item, EcdsaSignature(PkOrF::Fingerprint(f)) if f == &fingerprint)); assert_matches!(&policy.item, EcdsaSignature(PkOrF::Fingerprint(f)) if f == &fingerprint);
assert!(matches!(&policy.contribution, Satisfaction::None)); assert_matches!(&policy.contribution, Satisfaction::None);
let desc = descriptor!(wpkh(prvkey)).unwrap(); let desc = descriptor!(wpkh(prvkey)).unwrap();
let (wallet_desc, keymap) = desc let (wallet_desc, keymap) = desc
@ -1358,10 +1345,8 @@ mod test {
.unwrap() .unwrap()
.unwrap(); .unwrap();
assert!(matches!(policy.item, EcdsaSignature(PkOrF::Fingerprint(f)) if f == fingerprint)); assert_matches!(policy.item, EcdsaSignature(PkOrF::Fingerprint(f)) if f == fingerprint);
assert!( assert_matches!(policy.contribution, Satisfaction::Complete {condition} if condition.csv == None && condition.timelock == None);
matches!(policy.contribution, Satisfaction::Complete {condition} if condition.csv == None && condition.timelock == None)
);
} }
// single key, 1 prv and 1 pub key descriptor, required 1 prv keys // single key, 1 prv and 1 pub key descriptor, required 1 prv keys
@ -1382,18 +1367,15 @@ mod test {
.unwrap() .unwrap()
.unwrap(); .unwrap();
assert!( assert_matches!(policy.item, Multisig { keys, threshold } if threshold == 1
matches!(policy.item, Multisig { keys, threshold } if threshold == 1
&& keys[0] == PkOrF::Fingerprint(fingerprint0) && keys[0] == PkOrF::Fingerprint(fingerprint0)
&& keys[1] == PkOrF::Fingerprint(fingerprint1)) && keys[1] == PkOrF::Fingerprint(fingerprint1)
); );
assert!( assert_matches!(policy.contribution, Satisfaction::PartialComplete { n, m, items, conditions, .. } if n == 2
matches!(policy.contribution, Satisfaction::PartialComplete { n, m, items, conditions, .. } if n == 2
&& m == 1 && m == 1
&& items.len() == 2 && items.len() == 2
&& conditions.contains_key(&vec![0]) && conditions.contains_key(&vec![0])
&& conditions.contains_key(&vec![1]) && conditions.contains_key(&vec![1])
)
); );
} }
@ -1425,18 +1407,14 @@ mod test {
.unwrap() .unwrap()
.unwrap(); .unwrap();
assert!( assert_matches!(&policy.item, Thresh { items, threshold } if items.len() == 3 && threshold == &2);
matches!(&policy.item, Thresh { items, threshold } if items.len() == 3 && threshold == &2)
);
assert!( assert_matches!(&policy.contribution, Satisfaction::PartialComplete { n, m, items, conditions, .. } if n == &3
matches!(&policy.contribution, Satisfaction::PartialComplete { n, m, items, conditions, .. } if n == &3
&& m == &2 && m == &2
&& items.len() == 3 && items.len() == 3
&& conditions.get(&vec![0,1]).unwrap().iter().next().unwrap().csv.is_none() && conditions.get(&vec![0,1]).unwrap().iter().next().unwrap().csv.is_none()
&& conditions.get(&vec![0,2]).unwrap().iter().next().unwrap().csv == Some(Sequence(sequence)) && conditions.get(&vec![0,2]).unwrap().iter().next().unwrap().csv == Some(Sequence(sequence))
&& conditions.get(&vec![1,2]).unwrap().iter().next().unwrap().csv == Some(Sequence(sequence)) && conditions.get(&vec![1,2]).unwrap().iter().next().unwrap().csv == Some(Sequence(sequence))
)
); );
} }
@ -1599,11 +1577,9 @@ mod test {
.unwrap(); .unwrap();
//println!("{}", serde_json::to_string(&policy_alice_psbt).unwrap()); //println!("{}", serde_json::to_string(&policy_alice_psbt).unwrap());
assert!( assert_matches!(&policy_alice_psbt.satisfaction, Satisfaction::Partial { n, m, items, .. } if n == &2
matches!(&policy_alice_psbt.satisfaction, Satisfaction::Partial { n, m, items, .. } if n == &2
&& m == &2 && m == &2
&& items == &vec![0] && items == &vec![0]
)
); );
let psbt = Psbt::from_str(BOB_SIGNED_PSBT).unwrap(); let psbt = Psbt::from_str(BOB_SIGNED_PSBT).unwrap();
@ -1613,11 +1589,9 @@ mod test {
.unwrap(); .unwrap();
//println!("{}", serde_json::to_string(&policy_bob_psbt).unwrap()); //println!("{}", serde_json::to_string(&policy_bob_psbt).unwrap());
assert!( assert_matches!(&policy_bob_psbt.satisfaction, Satisfaction::Partial { n, m, items, .. } if n == &2
matches!(&policy_bob_psbt.satisfaction, Satisfaction::Partial { n, m, items, .. } if n == &2
&& m == &2 && m == &2
&& items == &vec![1] && items == &vec![1]
)
); );
let psbt = Psbt::from_str(ALICE_BOB_SIGNED_PSBT).unwrap(); let psbt = Psbt::from_str(ALICE_BOB_SIGNED_PSBT).unwrap();
@ -1625,11 +1599,9 @@ mod test {
.extract_policy(&signers_container, BuildSatisfaction::Psbt(&psbt), &secp) .extract_policy(&signers_container, BuildSatisfaction::Psbt(&psbt), &secp)
.unwrap() .unwrap()
.unwrap(); .unwrap();
assert!( assert_matches!(&policy_alice_bob_psbt.satisfaction, Satisfaction::PartialComplete { n, m, items, .. } if n == &2
matches!(&policy_alice_bob_psbt.satisfaction, Satisfaction::PartialComplete { n, m, items, .. } if n == &2
&& m == &2 && m == &2
&& items == &vec![0, 1] && items == &vec![0, 1]
)
); );
} }
@ -1673,11 +1645,9 @@ mod test {
.extract_policy(&signers_container, build_sat, &secp) .extract_policy(&signers_container, build_sat, &secp)
.unwrap() .unwrap()
.unwrap(); .unwrap();
assert!( assert_matches!(&policy.satisfaction, Satisfaction::Partial { n, m, items, .. } if n == &3
matches!(&policy.satisfaction, Satisfaction::Partial { n, m, items, .. } if n == &3
&& m == &2 && m == &2
&& items.is_empty() && items.is_empty()
)
); );
//println!("{}", serde_json::to_string(&policy).unwrap()); //println!("{}", serde_json::to_string(&policy).unwrap());
@ -1691,11 +1661,9 @@ mod test {
.extract_policy(&signers_container, build_sat_expired, &secp) .extract_policy(&signers_container, build_sat_expired, &secp)
.unwrap() .unwrap()
.unwrap(); .unwrap();
assert!( assert_matches!(&policy_expired.satisfaction, Satisfaction::Partial { n, m, items, .. } if n == &3
matches!(&policy_expired.satisfaction, Satisfaction::Partial { n, m, items, .. } if n == &3
&& m == &2 && m == &2
&& items == &vec![0] && items == &vec![0]
)
); );
//println!("{}", serde_json::to_string(&policy_expired).unwrap()); //println!("{}", serde_json::to_string(&policy_expired).unwrap());
@ -1711,11 +1679,9 @@ mod test {
.extract_policy(&signers_container, build_sat_expired_signed, &secp) .extract_policy(&signers_container, build_sat_expired_signed, &secp)
.unwrap() .unwrap()
.unwrap(); .unwrap();
assert!( assert_matches!(&policy_expired_signed.satisfaction, Satisfaction::PartialComplete { n, m, items, .. } if n == &3
matches!(&policy_expired_signed.satisfaction, Satisfaction::PartialComplete { n, m, items, .. } if n == &3
&& m == &2 && m == &2
&& items == &vec![0, 1] && items == &vec![0, 1]
)
); );
//println!("{}", serde_json::to_string(&policy_expired_signed).unwrap()); //println!("{}", serde_json::to_string(&policy_expired_signed).unwrap());
} }
@ -1790,12 +1756,8 @@ mod test {
.unwrap() .unwrap()
.unwrap(); .unwrap();
assert!( assert_matches!(policy.item, SatisfiableItem::Thresh { ref items, threshold: 1 } if items.len() == 2);
matches!(policy.item, SatisfiableItem::Thresh { ref items, threshold: 1 } if items.len() == 2) assert_matches!(policy.contribution, Satisfaction::PartialComplete { n: 2, m: 1, items, .. } if items == vec![1]);
);
assert!(
matches!(policy.contribution, Satisfaction::PartialComplete { n: 2, m: 1, items, .. } if items == vec![1])
);
let alice_sig = SatisfiableItem::SchnorrSignature(PkOrF::Fingerprint(alice_fing)); let alice_sig = SatisfiableItem::SchnorrSignature(PkOrF::Fingerprint(alice_fing));
let bob_sig = SatisfiableItem::SchnorrSignature(PkOrF::Fingerprint(bob_fing)); let bob_sig = SatisfiableItem::SchnorrSignature(PkOrF::Fingerprint(bob_fing));
@ -1887,19 +1849,11 @@ mod test {
.unwrap() .unwrap()
.unwrap(); .unwrap();
assert!( assert_matches!(policy_unsigned.item, SatisfiableItem::Thresh { ref items, threshold: 1 } if items.len() == 2);
matches!(policy_unsigned.item, SatisfiableItem::Thresh { ref items, threshold: 1 } if items.len() == 2) assert_matches!(policy_unsigned.satisfaction, Satisfaction::Partial { n: 2, m: 1, items, .. } if items.is_empty());
);
assert!(
matches!(policy_unsigned.satisfaction, Satisfaction::Partial { n: 2, m: 1, items, .. } if items.is_empty())
);
assert!( assert_matches!(policy_signed.item, SatisfiableItem::Thresh { ref items, threshold: 1 } if items.len() == 2);
matches!(policy_signed.item, SatisfiableItem::Thresh { ref items, threshold: 1 } if items.len() == 2) assert_matches!(policy_signed.satisfaction, Satisfaction::PartialComplete { n: 2, m: 1, items, .. } if items == vec![0, 1]);
);
assert!(
matches!(policy_signed.satisfaction, Satisfaction::PartialComplete { n: 2, m: 1, items, .. } if items == vec![0, 1])
);
let satisfied_items = match policy_signed.item { let satisfied_items = match policy_signed.item {
SatisfiableItem::Thresh { items, .. } => items, SatisfiableItem::Thresh { items, .. } => items,

View File

@ -483,6 +483,7 @@ mod test {
use super::*; use super::*;
use crate::descriptor::{DescriptorError, DescriptorMeta}; use crate::descriptor::{DescriptorError, DescriptorMeta};
use crate::keys::ValidNetworks; use crate::keys::ValidNetworks;
use assert_matches::assert_matches;
use bitcoin::network::constants::Network::Regtest; use bitcoin::network::constants::Network::Regtest;
use miniscript::descriptor::{DescriptorPublicKey, KeyMap}; use miniscript::descriptor::{DescriptorPublicKey, KeyMap};
use miniscript::Descriptor; use miniscript::Descriptor;
@ -501,9 +502,9 @@ mod test {
if let ExtendedDescriptor::Pkh(pkh) = xdesc.0 { if let ExtendedDescriptor::Pkh(pkh) = xdesc.0 {
let path: Vec<ChildNumber> = pkh.into_inner().full_derivation_path().into(); let path: Vec<ChildNumber> = pkh.into_inner().full_derivation_path().into();
let purpose = path.get(0).unwrap(); let purpose = path.get(0).unwrap();
assert!(matches!(purpose, Hardened { index: 44 })); assert_matches!(purpose, Hardened { index: 44 });
let coin_type = path.get(1).unwrap(); let coin_type = path.get(1).unwrap();
assert!(matches!(coin_type, Hardened { index: 0 })); assert_matches!(coin_type, Hardened { index: 0 });
} }
let tprvkey = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap(); let tprvkey = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
@ -515,9 +516,9 @@ mod test {
if let ExtendedDescriptor::Pkh(pkh) = tdesc.0 { if let ExtendedDescriptor::Pkh(pkh) = tdesc.0 {
let path: Vec<ChildNumber> = pkh.into_inner().full_derivation_path().into(); let path: Vec<ChildNumber> = pkh.into_inner().full_derivation_path().into();
let purpose = path.get(0).unwrap(); let purpose = path.get(0).unwrap();
assert!(matches!(purpose, Hardened { index: 44 })); assert_matches!(purpose, Hardened { index: 44 });
let coin_type = path.get(1).unwrap(); let coin_type = path.get(1).unwrap();
assert!(matches!(coin_type, Hardened { index: 1 })); assert_matches!(coin_type, Hardened { index: 1 });
} }
} }

View File

@ -256,6 +256,9 @@ pub extern crate rusqlite;
#[macro_use] #[macro_use]
pub mod testutils; pub mod testutils;
#[cfg(test)]
extern crate assert_matches;
#[allow(unused_imports)] #[allow(unused_imports)]
#[macro_use] #[macro_use]
pub(crate) mod error; pub(crate) mod error;

View File

@ -23,7 +23,7 @@ pub trait ConfigurableBlockchainTester<B: ConfigurableBlockchain>: Sized {
None None
} }
/// Runs all avaliable tests. /// Runs all available tests.
fn run(&self) { fn run(&self) {
let test_client = &mut TestClient::default(); let test_client = &mut TestClient::default();

View File

@ -102,11 +102,11 @@ use crate::{error::Error, Utxo};
use bitcoin::consensus::encode::serialize; use bitcoin::consensus::encode::serialize;
use bitcoin::Script; use bitcoin::Script;
#[cfg(test)]
use assert_matches::assert_matches;
use rand::seq::SliceRandom; use rand::seq::SliceRandom;
#[cfg(not(test))] #[cfg(not(test))]
use rand::thread_rng; use rand::thread_rng;
#[cfg(test)]
use rand::{rngs::StdRng, SeedableRng};
use std::collections::HashMap; use std::collections::HashMap;
use std::convert::TryInto; use std::convert::TryInto;
@ -671,6 +671,7 @@ impl BranchAndBoundCoinSelection {
optional_utxos.shuffle(&mut thread_rng()); optional_utxos.shuffle(&mut thread_rng());
#[cfg(test)] #[cfg(test)]
{ {
use rand::{rngs::StdRng, SeedableRng};
let seed = [0; 32]; let seed = [0; 32];
let mut rng: StdRng = SeedableRng::from_seed(seed); let mut rng: StdRng = SeedableRng::from_seed(seed);
optional_utxos.shuffle(&mut rng); optional_utxos.shuffle(&mut rng);
@ -1522,24 +1523,22 @@ mod test {
let database = MemoryDatabase::default(); let database = MemoryDatabase::default();
let drain_script = Script::default(); let drain_script = Script::default();
let err = BranchAndBoundCoinSelection::default() let selection = BranchAndBoundCoinSelection::default().coin_select(
.coin_select( &database,
&database, vec![],
vec![], utxos,
utxos, FeeRate::from_sat_per_vb(10.0),
FeeRate::from_sat_per_vb(10.0), 500_000,
500_000, &drain_script,
&drain_script, );
)
.unwrap_err();
assert!(matches!( assert_matches!(
err, selection,
Error::InsufficientFunds { Err(Error::InsufficientFunds {
available: 300_000, available: 300_000,
.. ..
} })
)); );
} }
#[test] #[test]
@ -1552,24 +1551,22 @@ mod test {
.into_iter() .into_iter()
.partition(|u| matches!(u, WeightedUtxo { utxo, .. } if utxo.txout().value < 1000)); .partition(|u| matches!(u, WeightedUtxo { utxo, .. } if utxo.txout().value < 1000));
let err = BranchAndBoundCoinSelection::default() let selection = BranchAndBoundCoinSelection::default().coin_select(
.coin_select( &database,
&database, required,
required, optional,
optional, FeeRate::from_sat_per_vb(10.0),
FeeRate::from_sat_per_vb(10.0), 500_000,
500_000, &drain_script,
&drain_script, );
)
.unwrap_err();
assert!(matches!( assert_matches!(
err, selection,
Error::InsufficientFunds { Err(Error::InsufficientFunds {
available: 300_010, available: 300_010,
.. ..
} })
)); );
} }
#[test] #[test]
@ -1578,23 +1575,21 @@ mod test {
let database = MemoryDatabase::default(); let database = MemoryDatabase::default();
let drain_script = Script::default(); let drain_script = Script::default();
let err = BranchAndBoundCoinSelection::default() let selection = BranchAndBoundCoinSelection::default().coin_select(
.coin_select( &database,
&database, utxos,
utxos, vec![],
vec![], FeeRate::from_sat_per_vb(10_000.0),
FeeRate::from_sat_per_vb(10_000.0), 500_000,
500_000, &drain_script,
&drain_script, );
)
.unwrap_err();
assert!(matches!( assert_matches!(
err, selection,
Error::InsufficientFunds { Err(Error::InsufficientFunds {
available: 300_010, available: 300_010,
.. ..
} })
)); );
} }
} }

View File

@ -1851,6 +1851,7 @@ pub fn get_funded_wallet(
#[cfg(test)] #[cfg(test)]
pub(crate) mod test { pub(crate) mod test {
use assert_matches::assert_matches;
use bitcoin::{util::psbt, Network, PackedLockTime, Sequence}; use bitcoin::{util::psbt, Network, PackedLockTime, Sequence};
use crate::database::Database; use crate::database::Database;
@ -4425,11 +4426,9 @@ pub(crate) mod test {
result.is_err(), result.is_err(),
"Signing should have failed because the TX uses non-standard sighashes" "Signing should have failed because the TX uses non-standard sighashes"
); );
assert!( assert_matches!(
matches!( result,
result.unwrap_err(), Err(Error::Signer(SignerError::NonStandardSighash)),
Error::Signer(SignerError::NonStandardSighash)
),
"Signing failed with the wrong error type" "Signing failed with the wrong error type"
); );
@ -4912,16 +4911,10 @@ pub(crate) mod test {
..Default::default() ..Default::default()
}, },
); );
assert!( assert_matches!(
result.is_err(), result,
"Signing should have failed because the witness_utxo is missing" Err(Error::Signer(SignerError::MissingWitnessUtxo)),
); "Signing should have failed with the correct error because the witness_utxo is missing"
assert!(
matches!(
result.unwrap_err(),
Error::Signer(SignerError::MissingWitnessUtxo)
),
"Signing failed with the wrong error type"
); );
// restore the witness_utxo // restore the witness_utxo
@ -4935,9 +4928,9 @@ pub(crate) mod test {
}, },
); );
assert!(result.is_ok(), "Signing should have worked"); assert_matches!(
assert!( result,
result.unwrap(), Ok(true),
"Should finalize the input since we can produce signatures" "Should finalize the input since we can produce signatures"
); );
} }
@ -5262,11 +5255,9 @@ pub(crate) mod test {
result.is_err(), result.is_err(),
"Signing should have failed because the TX uses non-standard sighashes" "Signing should have failed because the TX uses non-standard sighashes"
); );
assert!( assert_matches!(
matches!( result,
result.unwrap_err(), Err(Error::Signer(SignerError::NonStandardSighash)),
Error::Signer(SignerError::NonStandardSighash)
),
"Signing failed with the wrong error type" "Signing failed with the wrong error type"
); );
@ -5282,11 +5273,9 @@ pub(crate) mod test {
result.is_err(), result.is_err(),
"Signing should have failed because the witness_utxo is missing" "Signing should have failed because the witness_utxo is missing"
); );
assert!( assert_matches!(
matches!( result,
result.unwrap_err(), Err(Error::Signer(SignerError::MissingWitnessUtxo)),
Error::Signer(SignerError::MissingWitnessUtxo)
),
"Signing failed with the wrong error type" "Signing failed with the wrong error type"
); );
@ -5367,26 +5356,26 @@ pub(crate) mod test {
builder builder
.add_recipient(addr.script_pubkey(), balance.immature / 2) .add_recipient(addr.script_pubkey(), balance.immature / 2)
.current_height(confirmation_time); .current_height(confirmation_time);
assert!(matches!( assert_matches!(
builder.finish().unwrap_err(), builder.finish(),
Error::InsufficientFunds { Err(Error::InsufficientFunds {
needed: _, needed: _,
available: 0 available: 0
} })
)); );
// Still unspendable... // Still unspendable...
let mut builder = wallet.build_tx(); let mut builder = wallet.build_tx();
builder builder
.add_recipient(addr.script_pubkey(), balance.immature / 2) .add_recipient(addr.script_pubkey(), balance.immature / 2)
.current_height(not_yet_mature_time); .current_height(not_yet_mature_time);
assert!(matches!( assert_matches!(
builder.finish().unwrap_err(), builder.finish(),
Error::InsufficientFunds { Err(Error::InsufficientFunds {
needed: _, needed: _,
available: 0 available: 0
} })
)); );
// ...Now the coinbase is mature :) // ...Now the coinbase is mature :)
let sync_time = SyncTime { let sync_time = SyncTime {
@ -5428,10 +5417,7 @@ pub(crate) mod test {
builder.add_recipient(addr.script_pubkey(), 0); builder.add_recipient(addr.script_pubkey(), 0);
assert!(matches!( assert_matches!(builder.finish(), Err(Error::OutputBelowDustLimit(0)));
builder.finish().unwrap_err(),
Error::OutputBelowDustLimit(0)
));
let mut builder = wallet.build_tx(); let mut builder = wallet.build_tx();

View File

@ -998,6 +998,7 @@ mod signers_container_tests {
use crate::descriptor; use crate::descriptor;
use crate::descriptor::IntoWalletDescriptor; use crate::descriptor::IntoWalletDescriptor;
use crate::keys::{DescriptorKey, IntoDescriptorKey}; use crate::keys::{DescriptorKey, IntoDescriptorKey};
use assert_matches::assert_matches;
use bitcoin::secp256k1::{All, Secp256k1}; use bitcoin::secp256k1::{All, Secp256k1};
use bitcoin::util::bip32; use bitcoin::util::bip32;
use bitcoin::Network; use bitcoin::Network;
@ -1067,17 +1068,17 @@ mod signers_container_tests {
signers.add_external(id2.clone(), SignerOrdering(2), signer2.clone()); signers.add_external(id2.clone(), SignerOrdering(2), signer2.clone());
signers.add_external(id3.clone(), SignerOrdering(3), signer3.clone()); signers.add_external(id3.clone(), SignerOrdering(3), signer3.clone());
assert!(matches!(signers.find(id1), Some(signer) if is_equal(signer, &signer1))); assert_matches!(signers.find(id1), Some(signer) if is_equal(signer, &signer1));
assert!(matches!(signers.find(id2), Some(signer) if is_equal(signer, &signer2))); assert_matches!(signers.find(id2), Some(signer) if is_equal(signer, &signer2));
assert!(matches!(signers.find(id3.clone()), Some(signer) if is_equal(signer, &signer3))); assert_matches!(signers.find(id3.clone()), Some(signer) if is_equal(signer, &signer3));
// The `signer4` has the same ID as `signer3` but lower ordering. // The `signer4` has the same ID as `signer3` but lower ordering.
// It should be found by `id3` instead of `signer3`. // It should be found by `id3` instead of `signer3`.
signers.add_external(id3.clone(), SignerOrdering(2), signer4.clone()); signers.add_external(id3.clone(), SignerOrdering(2), signer4.clone());
assert!(matches!(signers.find(id3), Some(signer) if is_equal(signer, &signer4))); assert_matches!(signers.find(id3), Some(signer) if is_equal(signer, &signer4));
// Can't find anything with ID that doesn't exist // Can't find anything with ID that doesn't exist
assert!(matches!(signers.find(id_nonexistent), None)); assert_matches!(signers.find(id_nonexistent), None);
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]

View File

@ -108,6 +108,7 @@ impl_error!(bitcoinconsensus::Error, Consensus, VerifyError);
mod test { mod test {
use super::*; use super::*;
use crate::database::{BatchOperations, MemoryDatabase}; use crate::database::{BatchOperations, MemoryDatabase};
use assert_matches::assert_matches;
use bitcoin::consensus::encode::deserialize; use bitcoin::consensus::encode::deserialize;
use bitcoin::hashes::hex::FromHex; use bitcoin::hashes::hex::FromHex;
use bitcoin::{Transaction, Txid}; use bitcoin::{Transaction, Txid};
@ -137,9 +138,7 @@ mod test {
} }
let result = verify_tx(&signed_tx, &database, &blockchain); let result = verify_tx(&signed_tx, &database, &blockchain);
assert!(result.is_err(), "Should fail with missing input tx"); assert_matches!(result, Err(VerifyError::MissingInputTx(txid)) if txid == prev_tx.txid(),
assert!(
matches!(result, Err(VerifyError::MissingInputTx(txid)) if txid == prev_tx.txid()),
"Error should be a `MissingInputTx` error" "Error should be a `MissingInputTx` error"
); );
@ -147,9 +146,9 @@ mod test {
database.set_raw_tx(&prev_tx).unwrap(); database.set_raw_tx(&prev_tx).unwrap();
let result = verify_tx(&unsigned_tx, &database, &blockchain); let result = verify_tx(&unsigned_tx, &database, &blockchain);
assert!(result.is_err(), "Should fail since the TX is unsigned"); assert_matches!(
assert!( result,
matches!(result, Err(VerifyError::Consensus(_))), Err(VerifyError::Consensus(_)),
"Error should be a `Consensus` error" "Error should be a `Consensus` error"
); );