Skip to content

Commit f41cbc8

Browse files
committed
Address new mutants from cargo mutants v25.2.2
This commits adds the exclusions and mutant catches for the cargo mutants upgrade to v25.2.2
1 parent be55dca commit f41cbc8

File tree

5 files changed

+63
-5
lines changed

5 files changed

+63
-5
lines changed

.cargo/mutants.toml

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,24 @@ exclude_re = [
1010
".*Error",
1111

1212
# ---------------------Crate-specific exculsions---------------------
13-
# Receive
14-
# src/receive/v1/mod.rs
13+
# Timeout loops
1514
"interleave_shuffle", # Replacing index += 1 with index *= 1 in a loop causes a timeout due to an infinite loop
15+
16+
# Trivial mutations
1617
"replace > with >= in ProvisionalProposal::apply_fee", # allowing 2 code blocks in this function to run when the additional fee = 0 does nothing
1718
"replace < with <= in PsbtContext::check_outputs", # allowing the subtraction of 2 equal values always resulting in a contrib_fee of 0
1819
"replace > with >= in PsbtContext::check_fees", # checking if the feerate is below the minimum when the minimum is allowed to be zero does nothing
20+
"replace < with <= in SenderBuilder<'a>::build_recommended", # clamping the fee contribution when the fee equals to the recommended fee does not do anything
21+
22+
# Async SystemTime comparison
1923
"replace > with >= in Sender<WithReplyKey>::extract_v2", # checking if the system time is equal to the expiry is difficult to reasonably test
2024
"replace < with <= in Receiver<Initialized>::apply_unchecked_from_payload", # checking if the system time is equal to the expiry is difficult to reasonably test
2125
"replace > with >= in Receiver<Initialized>::extract_req", # checking if the system time is equal to the expiry is difficult to reasonably test
2226
"replace > with >= in extract_err_req", # checking if the system time is equal to the expiry is difficult to reasonably test
23-
"replace < with <= in SenderBuilder<'a>::build_recommended", # clamping the fee contribution when the fee equals to the recommended fee does not do anything
27+
"replace > with >= in Receiver<Initialized>::create_poll_request", # checking if the system time is equal to the expiry is difficult to reasonably test
28+
"replace > with >= in Sender<WithReplyKey>::create_v2_post_request", # checking if the system time is equal to the expiry is difficult to reasonably test
29+
30+
# TODO exclusions
2431
"replace match guard with true in PsbtContext::check_outputs", # This non-deterministic mutation has a possible test to catch it
32+
"replace > with >= in WantsInputs::avoid_uih", # This mutation I am unsure about whether or not it is a trivial mutant and have not decided on how the best way to approach testing it is
2533
]

payjoin/src/core/receive/multiparty/mod.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,23 @@ mod test {
355355
Ok(())
356356
}
357357

358+
#[test]
359+
fn test_build_multiparty() -> Result<(), BoxError> {
360+
let proposal_one = v2::UncheckedProposal {
361+
v1: multiparty_proposals()[0].clone(),
362+
context: SHARED_CONTEXT.clone(),
363+
};
364+
let proposal_two = v2::UncheckedProposal {
365+
v1: multiparty_proposals()[1].clone(),
366+
context: SHARED_CONTEXT_TWO.clone(),
367+
};
368+
let mut multiparty = UncheckedProposalBuilder::new();
369+
multiparty.add(v2::Receiver { state: proposal_one })?;
370+
multiparty.add(v2::Receiver { state: proposal_two })?;
371+
assert!(multiparty.build().is_ok());
372+
Ok(())
373+
}
374+
358375
#[test]
359376
fn test_duplicate_context_multiparty() -> Result<(), BoxError> {
360377
let proposal_one = v2::UncheckedProposal {

payjoin/src/core/receive/v1/mod.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -933,6 +933,16 @@ pub(crate) mod test {
933933
},
934934
_ => panic!("Broadcast suitability check should fail due to being below the min fee rate or unexpected error type"),
935935
};
936+
937+
let min_fee_rate = proposal.psbt_fee_rate().expect("Feerate calculation should not fail");
938+
match proposal.clone().check_broadcast_suitability(Some(min_fee_rate), |_| Ok(true)) {
939+
Ok(_) => {
940+
assert_eq!(proposal.clone().psbt_fee_rate().unwrap(), min_fee_rate)
941+
}
942+
Err(_) => {
943+
panic!("Broadcast suitability check should fail due to being below the min fee rate or unexpected error type")
944+
}
945+
};
936946
}
937947

938948
#[test]
@@ -1140,6 +1150,17 @@ pub(crate) mod test {
11401150
[wants_outputs.change_vout]
11411151
.script_pubkey;
11421152

1153+
let output_value =
1154+
wants_outputs.original_psbt.unsigned_tx.output[wants_outputs.change_vout].value;
1155+
let outputs = vec![TxOut { value: output_value, script_pubkey: script_pubkey.clone() }];
1156+
let increased_amount =
1157+
wants_outputs.clone().replace_receiver_outputs(outputs, script_pubkey.as_script());
1158+
assert!(
1159+
increased_amount.is_ok(),
1160+
"Not changing the receiver output amount should always be allowed"
1161+
);
1162+
assert_ne!(wants_outputs.payjoin_psbt, increased_amount.unwrap().payjoin_psbt);
1163+
11431164
let output_value =
11441165
wants_outputs.original_psbt.unsigned_tx.output[wants_outputs.change_vout].value
11451166
+ Amount::ONE_SAT;

payjoin/src/core/send/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,15 @@ mod test {
543543
fee_contribution.err(),
544544
Some(InternalBuildSenderError::FeeOutputValueLowerThanFeeContribution)
545545
);
546+
let fee_contribution = determine_fee_contribution(
547+
&PARSED_ORIGINAL_PSBT,
548+
Script::from_bytes(&<Vec<u8> as FromHex>::from_hex(
549+
"0014b60943f60c3ee848828bdace7474a92e81f3fcdd",
550+
)?),
551+
Some((Amount::from_sat(95983068), None)),
552+
false,
553+
);
554+
assert!(fee_contribution.is_ok());
546555
Ok(())
547556
}
548557

payjoin/src/core/send/v1.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,7 @@ mod test {
414414
let fee_contribution = sender.fee_contribution.expect("sender should contribute fees");
415415
assert_eq!(fee_contribution.max_amount, Amount::from_sat(91));
416416
assert_eq!(fee_contribution.vout, 0);
417+
assert_eq!(NON_WITNESS_INPUT_WEIGHT, bitcoin::Weight::from_wu(160));
417418
assert_eq!(sender.min_fee_rate, FeeRate::from_sat_per_kwu(250));
418419
// Ensure the receiver's output substitution preference is respected either way
419420
let mut pj_uri = pj_uri();
@@ -480,10 +481,12 @@ mod test {
480481
#[test]
481482
fn process_response_invalid_utf8() {
482483
// In UTF-8, 0xF0 represents the start of a 4-byte sequence, so 0xF0 by itself is invalid
483-
let invalid_utf8 = &[0xF0];
484+
let mut invalid_utf8_padding = PAYJOIN_PROPOSAL.as_bytes().to_vec();
485+
invalid_utf8_padding
486+
.extend(std::iter::repeat(0).take(MAX_CONTENT_LENGTH - invalid_utf8_padding.len()));
484487

485488
let ctx = create_v1_context();
486-
let response = ctx.process_response(invalid_utf8);
489+
let response = ctx.process_response(&invalid_utf8_padding);
487490
match response {
488491
Ok(_) => panic!("Invalid UTF-8 should have caused an error"),
489492
Err(error) => match error {

0 commit comments

Comments
 (0)