-
Notifications
You must be signed in to change notification settings - Fork 76
Cargo mutants version update #882
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cargo mutants version update #882
Conversation
4d00cdc to
f41cbc8
Compare
Pull Request Test Coverage Report for Build 16575062311Details
💛 - Coveralls |
b807b4c to
907a9ed
Compare
spacebear21
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I slightly dislike the mutants exclusions by name because they seem vulnerable to regressions (e.g. if the skipped functions get renamed as #884 is likely to do for some of these) or false positives (e.g. what was once a trivial mutation becomes serious after several refactors). Trivial mutations seem like a code smell that the underlying code could be re-written to eliminate ambiguity. I don't have specific suggestions regarding those excluded mutants, but I want to ensure that we're very deliberate about what we choose to exclude.
payjoin/src/core/receive/v1/mod.rs
Outdated
| assert_eq!(proposal.clone().psbt_fee_rate().unwrap(), min_fee_rate) | ||
| } | ||
| Err(_) => { | ||
| panic!("Broadcast suitability check should fail due to being below the min fee rate or unexpected error type") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| panic!("Broadcast suitability check should fail due to being below the min fee rate or unexpected error type") | |
| panic!("Broadcast suitability check with appropriate min_fee_rate should succeed") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, I'd probably re-write the whole match statement:
let min_fee_rate = proposal.psbt_fee_rate().expect("Feerate calculation should not fail");
let _ = proposal.clone().check_broadcast_suitability(Some(min_fee_rate), |_| Ok(true)).expect("Broadcast suitability check with appropriate min_fee_rate should succeed");
assert_eq!(proposal.clone().psbt_fee_rate().unwrap(), min_fee_rate);Re-writing it like that, it's unclear what exactly this assert_eq is testing for? It seems tautological that min_fee_rate == proposal.psbt_fee_rate().unwrap()
payjoin/src/core/receive/v1/mod.rs
Outdated
| assert_eq!(proposal_rate, proposal.clone().psbt_fee_rate().unwrap()); | ||
| assert_eq!(min_rate, min_fee_rate); | ||
| }, | ||
| _ => panic!("Broadcast suitability check should fail due to being below the min fee rate or unexpected error type"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably this match could also be re-written as an expect_err() instead of match/panic.
payjoin/src/core/receive/v1/mod.rs
Outdated
| wants_outputs.clone().replace_receiver_outputs(outputs, script_pubkey.as_script()); | ||
| assert!( | ||
| increased_amount.is_ok(), | ||
| "Not changing the receiver output amount should always be allowed" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| "Not changing the receiver output amount should always be allowed" | |
| "Increasing the receiver output amount is always allowed" |
| fee_contribution.err(), | ||
| Some(InternalBuildSenderError::FeeOutputValueLowerThanFeeContribution) | ||
| ); | ||
| let fee_contribution = determine_fee_contribution( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some explanatory comments on these new edge cases wouldn't hurt. I'm guessing this is testing the maximum allowed fee contribution based on the input value?
payjoin/src/core/send/v1.rs
Outdated
|
|
||
| #[test] | ||
| fn process_response_invalid_utf8() { | ||
| // In UTF-8, 0xF0 represents the start of a 4-byte sequence, so 0xF0 by itself is invalid |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment looks obsolete now.
.cargo/mutants.toml
Outdated
| # Async SystemTime comparison | ||
| "replace > with >= in Sender<WithReplyKey>::extract_v2", # checking if the system time is equal to the expiry is difficult to reasonably test | ||
| "replace < with <= in Receiver<Initialized>::apply_unchecked_from_payload", # checking if the system time is equal to the expiry is difficult to reasonably test | ||
| "replace > with >= in Receiver<Initialized>::extract_req", # checking if the system time is equal to the expiry is difficult to reasonably test | ||
| "replace > with >= in extract_err_req", # checking if the system time is equal to the expiry is difficult to reasonably test | ||
| "replace > with >= in Receiver<Initialized>::create_poll_request", # checking if the system time is equal to the expiry is difficult to reasonably test | ||
| "replace > with >= in Sender<WithReplyKey>::create_v2_post_request", # checking if the system time is equal to the expiry is difficult to reasonably test |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit:
| # Async SystemTime comparison | |
| "replace > with >= in Sender<WithReplyKey>::extract_v2", # checking if the system time is equal to the expiry is difficult to reasonably test | |
| "replace < with <= in Receiver<Initialized>::apply_unchecked_from_payload", # checking if the system time is equal to the expiry is difficult to reasonably test | |
| "replace > with >= in Receiver<Initialized>::extract_req", # checking if the system time is equal to the expiry is difficult to reasonably test | |
| "replace > with >= in extract_err_req", # checking if the system time is equal to the expiry is difficult to reasonably test | |
| "replace > with >= in Receiver<Initialized>::create_poll_request", # checking if the system time is equal to the expiry is difficult to reasonably test | |
| "replace > with >= in Sender<WithReplyKey>::create_v2_post_request", # checking if the system time is equal to the expiry is difficult to reasonably test | |
| # Async SystemTime comparison | |
| # checking if the system time is equal to the expiry is difficult to reasonably test | |
| "replace > with >= in Sender<WithReplyKey>::extract_v2", | |
| "replace < with <= in Receiver<Initialized>::apply_unchecked_from_payload", | |
| "replace > with >= in Receiver<Initialized>::extract_req", | |
| "replace > with >= in extract_err_req", | |
| "replace > with >= in Receiver<Initialized>::create_poll_request", | |
| "replace > with >= in Sender<WithReplyKey>::create_v2_post_request", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tried to to a little further organization
| "replace > with >= in PsbtContext::check_fees", # checking if the feerate is below the minimum when the minimum is allowed to be zero does nothing | ||
| "replace < with <= in SenderBuilder<'a>::build_recommended", # clamping the fee contribution when the fee equals to the recommended fee does not do anything | ||
|
|
||
| # Async SystemTime comparison |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We may want to figure out a way to mock SystemTime in tests. I've used freezegun in Python in the past, I wonder if a similar tool exists the Rust ecosystem. We may even be able to mock it with a Trait, per Claude:
use std::time::SystemTime;
trait TimeProvider {
fn now(&self) -> SystemTime;
}
struct RealTimeProvider;
impl TimeProvider for RealTimeProvider {
fn now(&self) -> SystemTime {
SystemTime::now()
}
}
struct MockTimeProvider {
time: SystemTime,
}
impl TimeProvider for MockTimeProvider {
fn now(&self) -> SystemTime {
self.time
}
}
// Your code uses the trait
fn process_with_timestamp<T: TimeProvider>(time_provider: &T) -> SystemTime {
time_provider.now()
}
#[cfg(test)]
mod tests {
use super::*;
use std::time::{Duration, UNIX_EPOCH};
#[test]
fn test_with_mock_time() {
let mock_time = UNIX_EPOCH + Duration::from_secs(1000);
let provider = MockTimeProvider { time: mock_time };
let result = process_with_timestamp(&provider);
assert_eq!(result, mock_time);
}
}This seems reasonable to leave as a follow-up, maybe to be addressed alongside #893.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh interesting, I got hung up on trying to fit the tokio::test pause() method in but it just wasn't working.
|
Thanks! as for those trivial mutants a good can of axe body spray by just making the code blocks follow the logic path in the inverted operand cases. With the named exclusions I think we might want to consider using diff mutations https://github.com/sourcefrog/cargo-mutants/blob/1481918f377a2e0a86a66185cb536dd292157438/.github/workflows/tests.yml#L234-L277 perhaps we're not quite ready for it in our codebase but it would be nice to keep the mutant coverage more maintainable |
907a9ed to
e306e83
Compare
This updates cargo mutants to 25.2.2 to allow us to catch more mutants and add some more precise exclusions.
d8a5edc to
0b0f758
Compare
This commits adds the exclusions and mutant catches for the cargo mutants upgrade to v25.2.2
0b0f758 to
7a21ab7
Compare
spacebear21
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
utACK 7a21ab7
It would be great to address the exclusions in later follow-ups and remove them from the exclusion list, but these seem reasonable enough for now, and merging this PR will reduce the noise from automated mutants issues.
Closes #872, closes #836, closes #771, closes #890
This addressed #778 for now but I still would like to create a test instead of excluding it
I also added the basic test that should address the mutation from #847 (comment)
The exclusions are catogerized as follows.