Skip to content

Extend tests for rest of receive module#632

Merged
DanGould merged 2 commits intopayjoin:masterfrom
benalleng:extend-receive-tests
Apr 14, 2025
Merged

Extend tests for rest of receive module#632
DanGould merged 2 commits intopayjoin:masterfrom
benalleng:extend-receive-tests

Conversation

@benalleng
Copy link
Collaborator

This expands the mutant coverage for the rest of the receive module and expands the mutant job coverage over the entire receive module.

Unfortunately the SHARED_CONTEXT cannot reasonably be moved into test_utils as the external nature of this struct would then cause errors as the type would be of payjoin::SessionContext not SessionContext

@coveralls
Copy link
Collaborator

coveralls commented Apr 2, 2025

Pull Request Test Coverage Report for Build 14390878927

Details

  • 68 of 69 (98.55%) changed or added relevant lines in 3 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+0.2%) to 81.794%

Changes Missing Coverage Covered Lines Changed/Added Lines %
payjoin/src/receive/v2/mod.rs 17 18 94.44%
Totals Coverage Status
Change from base Build 14387071460: 0.2%
Covered Lines: 5324
Relevant Lines: 6509

💛 - Coveralls

@benalleng benalleng force-pushed the extend-receive-tests branch from 85cdc08 to 4fe7eb2 Compare April 2, 2025 20:48
@benalleng benalleng marked this pull request as draft April 2, 2025 20:59
@benalleng

This comment was marked as resolved.

@benalleng benalleng force-pushed the extend-receive-tests branch from 4fe7eb2 to 47d075f Compare April 3, 2025 14:19
@benalleng benalleng marked this pull request as ready for review April 3, 2025 14:29
Copy link
Contributor

@DanGould DanGould left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd want @0xBEEFCAF3 to check out the multiparty before ACK.

I left some comments on one issue that for sure needs fixing and another that'd be nice.

Crushing deez receive mutants 🥾

Comment on lines 712 to 727
fn maximum_expiry() {
let session = NewReceiver::new(
SHARED_CONTEXT.address.clone(),
SHARED_CONTEXT.directory.clone(),
SHARED_CONTEXT.ohttp_keys.clone(),
None,
);
let session_expiry =
session.unwrap().context.expiry.duration_since(SystemTime::now()).unwrap().as_secs();
let maximum_expiry = Duration::from_secs(86400);
if let Some(expected_expiry) = SystemTime::checked_add(&SystemTime::now(), maximum_expiry) {
assert_eq!(TWENTY_FOUR_HOURS_DEFAULT_EXPIRY, maximum_expiry);
assert_eq!(
session_expiry,
expected_expiry.duration_since(SystemTime::now()).unwrap().as_secs()
);
}
}
Copy link
Contributor

@DanGould DanGould Apr 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test does not pass in my environment, perhaps because some time may pass between calls of SystemTime::now().

thread 'receive::v2::test::maximum_expiry' panicked at payjoin/src/receive/v2/mod.rs:724:13:
assertion `left == right` failed
  left: 86399
 right: 86400

I think we can use #[tokio::test(start_paused = true)] to pause time so the test is more consistent.

Next, checked_add call is a bit odd if it's using &self. Prefer SystemTime::now().checked_add(maximum_expiry)

When I tested this I also got an issue compiling with the start_paused change which made me bump tokio. Seems like 1.38.1 is 1.63 MSRV. Turned out the bump wasn't necessary but the tokio/test-util feature was. Not a bad time to bump to 1.38.1 in a separate commit, tho. Don't forget to update lock files in the commit(s) that change(s) Cargo.toml.

Lastly I'm not sure why thi stest is named maximum expiry. Isn't it default? Couldn't it be set to be longer?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok! Need to spend more time learning how to use tokio

fn multiparty_proposal_from_test_vector() -> v1::UncheckedProposal {
let pairs = url::form_urlencoded::parse("v=2&optimisticmerge=true".as_bytes());
let params =
Params::from_query_pairs(pairs, &[2]).expect("Could not parse from query pairs");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I stared at this &[2] for a while wondering what it was. Makes me wonder if we ought to have a Version enum.


use std::any::{Any, TypeId};

use payjoin_test_utils::{BoxError, PARSED_ORIGINAL_PSBT};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't seem like a big reason to import and use BoxError or results if the functions return Ok(()) and the ? isn't used anywhere.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

going to keep these in favor of using some ? instead of only expect()

Copy link
Collaborator

@arminsabouri arminsabouri left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack on the multi party front. 47d075f
Just had a couple small comments, no show stoppers.

Its great to see some test coverage on the proposal builders. The tests added are actually testing what I would classify as an edge case where we are building multi party proposal with duplicate inner proposals. In a follow up PR we should fix this and then follow up with some tests on the happy path as well (unique proposals with different hpke sessions).

Thanks for adding these 🚀

let unchecked_proposal = multiparty.build();
assert!(
unchecked_proposal.expect("Could not build multiparty proposal").contexts.len() == 2
);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is working as expected but I do wonder if contexts here should be len == 1. Since both the hpke context and the proposal is the same it would make sense to me that UncheckedProposalBuilder.add() would disallow the caller to add duplicate sessions. I still think the ns1r session would succeed bc only one PSBT ends up on the directory for this hpke session but it still seems wrong and error prone. This is outside the scope of this PR.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue created: #640

.expect("Could not add propsal to multiparty");

finalized_multiparty.add(proposal_two).expect("Could not add propsal to multiparty");
assert_eq!(finalized_multiparty.v2()[0].type_id(), TypeId::of::<v2::UncheckedProposal>());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mind as well check the second proposal as well.

Suggested change
assert_eq!(finalized_multiparty.v2()[0].type_id(), TypeId::of::<v2::UncheckedProposal>());
assert_eq!(finalized_multiparty.v2()[0].type_id(), TypeId::of::<v2::UncheckedProposal>());
assert_eq!(finalized_multiparty.v2()[1].type_id(), TypeId::of::<v2::UncheckedProposal>());

assert!(
unchecked_proposal.expect("Could not build multiparty proposal").contexts.len() == 2
);
Ok(())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It any case we should also have a test where we add different PSBTs with different sessions as this is the happy path. This can also be a follow up!

Comment on lines 281 to 282
multiparty.add(proposal_one).expect("Could not add proposal to multiparty");
multiparty.add(proposal_two).expect("Could not add proposal to multiparty");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use ? here instead of expect?

@benalleng
Copy link
Collaborator Author

In a follow up PR we should fix this and then follow up with some tests on the happy path as well (unique proposals with different hpke sessions).

Yeah that's definitely something I am trying to keep in mind, Mutant catches rarely seem to be easily tested with the happy path when they can't be caught with a simple assert.

Copy link
Contributor

@DanGould DanGould left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice changes, But the feature addition needs to be fixup!ed into the first commit or else the first commit will not compile

Please also change the second commit to change all tokio = <version> definitions to match the update.

@benalleng benalleng force-pushed the extend-receive-tests branch from c0a9e16 to 77fd801 Compare April 10, 2025 18:07
@DanGould
Copy link
Contributor

DanGould commented Apr 10, 2025

I'm still getting the local failure despite CI passing and tokio start_paused. Going to have to troubleshoot hmm

running 1 test
test receive::v2::test::default_expiry ... FAILED

successes:

successes:

failures:

---- receive::v2::test::default_expiry stdout ----

thread 'receive::v2::test::default_expiry' panicked at payjoin/src/receive/v2/mod.rs:725:13:
assertion `left == right` failed
  left: 86399
 right: 86400

@benalleng benalleng force-pushed the extend-receive-tests branch from 77fd801 to cbd6f3a Compare April 10, 2025 19:04
@benalleng
Copy link
Collaborator Author

benalleng commented Apr 10, 2025

@DanGould give this recent one a shot, I tried just initializing let now = SystemTime::now() once and call it several times so maybe this will be more consistent

@DanGould
Copy link
Contributor

This works! However it no longer depends on tokio::test(start_paused = true), so please one more change to switch back to #[test] and shut the tokio feature off. The tokio should stay, good to bring deps up to date.

This expands the coverage for the rest of the receive module and
gives full mutant coverage for all the functions inside of receive.
@benalleng benalleng force-pushed the extend-receive-tests branch from cbd6f3a to 9be9dc2 Compare April 10, 2025 21:42
Copy link
Contributor

@DanGould DanGould left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 180f3084d2666fff6a6c0500063bb28266e6a80b

whoops, that's the rebase on master

ACK 9be9dc2

@DanGould DanGould merged commit 361c31e into payjoin:master Apr 14, 2025
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants