-
Notifications
You must be signed in to change notification settings - Fork 427
Improve test determinism with configurable connect style and deterministic hash maps #4296
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
Improve test determinism with configurable connect style and deterministic hash maps #4296
Conversation
|
👋 I see @valentinewallace was un-assigned. |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #4296 +/- ##
==========================================
- Coverage 89.38% 86.63% -2.75%
==========================================
Files 180 158 -22
Lines 139834 102066 -37768
Branches 139834 102066 -37768
==========================================
- Hits 124985 88422 -36563
+ Misses 12262 11233 -1029
+ Partials 2587 2411 -176
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
| let payment_count = Rc::new(RefCell::new(0)); | ||
| let connect_style = Rc::new(RefCell::new(ConnectStyle::random_style())); | ||
|
|
||
| let connect_style = Rc::new(RefCell::new(match std::env::var("LDK_TEST_CONNECT_STYLE") { |
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'm confused how this works in our no-std tests, like how CI is passing
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.
no-std tests are actually (secretly) built with std enabled. Its useful lol.
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.
Interesting. What was the original reason for that?
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.
IIRC cargo actually forces it on us, but we take advantage of it. Its possible we screwed up our feature flags at some point and accidentally did it, but either way its useful.
| let payment_count = Rc::new(RefCell::new(0)); | ||
| let connect_style = Rc::new(RefCell::new(ConnectStyle::random_style())); | ||
|
|
||
| let connect_style = Rc::new(RefCell::new(match std::env::var("LDK_TEST_CONNECT_STYLE") { |
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.
Is there some way to make this more discoverable? Maybe CONTRIBUTING.md? I think a comment would also be useful to describe why a dev would want to set this.
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.
Good point to add more docs. It is a bit confronting that we add and document an env var that underlines that there are non-deterministic unit tests, instead of making them deterministic.
We could also think about alternatives such as a 'deterministic_test' cfg flag, which we can then also use to add for example sorting when we iterate over hashmap/set keys?
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've added more docs and also added a commit for deterministic hash table iteration.
|
👋 The first review has been submitted! Do you think this PR is ready for a second reviewer? If so, click here to assign a second reviewer. |
6972818 to
eaef28f
Compare
lightning/README.md
Outdated
|
|
||
| ### Environment Variables | ||
|
|
||
| * `LDK_TEST_CONNECT_STYLE` - Override the random block connect style used in tests for deterministic runs. Valid values: |
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 should be in CONTRIBUTING.md, not a README.md. Its useful information that devs working on LDK might want to consider, but its not something that downstream devs using LDK should consider, and it definitely doesn't need to show up on our crates.io page.
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.
Indeed, not something for downstream devs. I've moved it to CONTRIBUTING, but still that doc feels more like process guidance. Maybe at some point we want a new doc that describes design/architecture/internals?
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.
Indeed, not something for downstream devs. I've moved it to CONTRIBUTING, but still that doc feels more like process guidance. Maybe at some point we want a new doc that describes design/architecture/internals?
FWIW, there is ARCH.md, though not sure if it makes sense to extend that to cover stuff like test env variables.
Tests previously selected a random block connect style to improve coverage. However, this randomness made test output non-deterministic and significantly cluttered diffs when comparing logs before and after changes. To address this, an LDK_TEST_CONNECT_STYLE environment variable is added to override the random selection and enable deterministic test runs. Note that broader coverage may be better achieved via targeted tests per connect style or a test matrix cycling through all styles, but this change focuses on improving reproducibility and debuggability.
8da55dd to
ef25534
Compare
| mod hasher { | ||
| pub use std::collections::hash_map::RandomState; | ||
| } | ||
| #[cfg(all(feature = "std", 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.
Hmm, test determinism is great, but test coverage is better. I'm a bit skeptical that the solution to "sometimes my tests are flaky due to hashmap iteration order" is to fix the hashmap iteration order, rather than fixing the tests. Having an option in the env like you do above to fix hashmap iteration order to make debugging easier seems reasonable, however.
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.
Fair enough. It's not about flakey tests btw, but about making test output comparable across runs.
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.
Updated
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.
Heh, I've def had it make tests flaky before :)
Add a `RandomState` hasher implementation for tests that supports deterministic behavior via the `LDK_TEST_DETERMINISTIC_HASHES=1` environment variable. When set, hash maps use fixed keys ensuring consistent iteration order across test runs. By default, tests continue to use std's RandomState for random hashing, keeping test behavior close to production. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
ef25534 to
075bc34
Compare
|
Simple enough, thanks. |
Tests previously selected a random block connect style to improve coverage. However, this randomness made test output non-deterministic and significantly cluttered diffs when comparing logs before and after changes.
To address this, an LDK_TEST_CONNECT_STYLE environment variable is added to override the random selection and enable deterministic test runs.
Note that broader coverage may be better achieved via targeted tests per connect style or a test matrix cycling through all styles, but this change focuses on improving reproducibility and debuggability.
Additionally, this PR makes hash map iteration deterministic in tests by using a fixed-seed hasher, eliminating another source of non-determinism in test output.