enhance(LargeSmtForest tests): expand LargeSmtForest property test coverage#886
enhance(LargeSmtForest tests): expand LargeSmtForest property test coverage#886AlexWaker wants to merge 5 commits into0xMiden:nextfrom
Conversation
| .operations(unknown_lineage) | ||
| .add_insert(query_key, invalid_value); | ||
| let invalid_result = forest.update_forest(version + 2, invalid_updates); | ||
| prop_assert!(invalid_result.is_err()); |
There was a problem hiding this comment.
Could we also assert metadata is unchanged after this error path? Right now we re-check entries and queries, but a partial apply bug could still move latest_version or create a new root_info at version + 2 and this test would still pass.
There was a problem hiding this comment.
I understand. I'll fix it as soon as possible
| let bad_version = forest.update_tree(lineage, version, extra_entries); | ||
| prop_assert!(bad_version.is_err()); | ||
| prop_assert_eq!( | ||
| bad_version.unwrap_err().to_string(), |
There was a problem hiding this comment.
Would it be safer to assert the error variant instead of exact to_string() text? Matching full message strings can make this test fail on wording-only changes.
|
Resolved the merge conflict by aligning property_tests.rs with the upstream API changes, including the new fallible entries() usage. Also addressed the two review comments:
Finally, ran formatting checks and applied rustfmt fixes (cargo +nightly fmt --all and cargo +nightly fmt --all --check). |
|
Would this PR need a changelog entry? My understanding is that it probably does not, since this change only expands internal test coverage and adapts the tests to upstream API changes, without introducing any user-facing behavior change or public API change. From the current CHANGELOG.md, it also seems like entries are generally reserved for externally visible features, fixes, and breaking changes. That said, if you would still prefer one to be added, I can update the changelog right away. |
huitseeker
left a comment
There was a problem hiding this comment.
This is shaping up nicely! See comments inline.
| TreeId::new(lineage, version), | ||
| &tree_v1, | ||
| &sample_keys, | ||
| false, |
There was a problem hiding this comment.
This helper skips open() on the historical tree by passing false here. Can we also property-test historical open() against the reference Smt? That feels like the trickiest query path in LargeSmtForest, and right now it still looks like it only has the hand-written unit test coverage in tests.rs.
There was a problem hiding this comment.
Yeah this should 100% test historical openings as well.
| @@ -0,0 +1 @@ | |||
| cc abf493f7aece0d6db6c370e3c95651effc9f46f7a2f97e2dccddacfce2afd16d No newline at end of file | |||
There was a problem hiding this comment.
I don't see any behavioral fixes in this PR. We usually only keep regression seeds like this when they allowed us to identify an interesting failure, which required fixing. This seems like it was just a development artifact and so does not need keeping.
iamrecursion
left a comment
There was a problem hiding this comment.
Looks reasonable in general! I've left a few comments in-line.
One thing I would love to see for every single potential modification is that we assert complete correctness with regards to the state change. Some of these—like the one @huitseeker commented on—do not assert the complete soundness of all propertiess should a bug arise.
Perhaps this is out of scope for this PR, but I would also be interested in expanding the FallibleEntriesBackend to be a more general mechanism for testing state coherence in the face of a number of different kinds of failure. @huitseeker, thoughts?
| }; | ||
|
|
||
| // ENTRIES | ||
| // HELPERS |
There was a problem hiding this comment.
All of these helpers should be moved to large_forest::test_utils like the other strategies are. I would also expect them to have doc comments, as that is the first line of understanding for someone reading the property test after a failure.
|
|
||
| fn apply_batch(tree: &mut Smt, batch: SmtUpdateBatch) -> core::result::Result<(), TestCaseError> { | ||
| let mutations = tree | ||
| .compute_mutations(Vec::<(Word, Word)>::from(batch).into_iter()) |
There was a problem hiding this comment.
This should call batch.consume().into_iter() instead. That guarantees the correct deduplication behaviouor.
| } | ||
|
|
||
| fn sorted_forest_entries( | ||
| forest: &LargeSmtForest<ForestInMemoryBackend>, |
There was a problem hiding this comment.
Realistically, this and all subsequent cases that take a forest should be parametric in the backend. While we currently only do these with the in-memory backend, there is no reason that has to remain the case forever.
| .collect::<crate::merkle::smt::large_forest::Result<Vec<_>>>() | ||
| .map_err(to_fail)? | ||
| .into_iter() | ||
| .sorted() |
There was a problem hiding this comment.
What is the purpose of sorting them? Does the default derived Ord implementation order them correctly?
| Ok(()) | ||
| } | ||
|
|
||
| // PROPERTY TESTS |
There was a problem hiding this comment.
In general, please reorder these property tests to match the method order in the large forest itself. It makes for easier code navigation.
| TreeId::new(lineage, version), | ||
| &tree_v1, | ||
| &sample_keys, | ||
| false, |
There was a problem hiding this comment.
Yeah this should 100% test historical openings as well.
This PR expands the property-based test coverage for
LargeSmtForest.Previously, the forest-level property tests were mostly limited to
entries(). This change adds a broader set of reference-model-driven property tests covering core query, mutation, metadata, constructor, and truncation behavior.The new tests now exercise:
get(),entries(), andentry_count()open()consistency checks against a referenceSmtlatest_version(),latest_root(),lineage_roots(),roots(), androot_info()add_lineage(),update_tree(), andupdate_forest()with_config()andtruncate()In addition, the property test helpers and generators were refactored to make the coverage easier to extend and maintain.
Closes #879.