Repository navigation
test: Add a shared framework for reproducible fuzz tests - #27048
Conversation
| let suites = [Suite::new( | ||
| &spill_pool, | ||
| RunConfig { | ||
| run_seed: Some(0), |
There was a problem hiding this comment.
This is the existing fuzz config, probably we can use rotating seed (timestamp), and time limit instead of 1000 cases.
alamb
left a comment
There was a problem hiding this comment.
The basic idea looks pretty good to me -- thank you @2010YOUY01
What I don't understand is the new crate structure and then the need to partially expose some of the existing testing code from the physical expr crate
| - name: Run fuzzers with more iterations | ||
| - name: Run fuzz tests | ||
| run: cargo xtask ci step test fuzz | ||
| # Migrate it to the above unified fuzz runner over time |
There was a problem hiding this comment.
Can you please file a ticket that explains the migration plan and has a checklist of tests to run and link it here? So we have the context in the future?
|
|
||
| mod suites; | ||
|
|
||
| /// The single registration point for project-wide fuzz campaigns. |
There was a problem hiding this comment.
what is a fuzz campaign? I am not familar with the campaign terminology
| use datafusion_common::instant::Instant; | ||
| use datafusion_common::{Result, exec_err}; | ||
|
|
||
| /// A component's fuzz experiment, run by the centralized driver. |
There was a problem hiding this comment.
it may help to add a link here to the centralized driver
|
@alamb THanks for the review!
Exposing some testing util was intended to keep the PR small, but this make the structure confusing. This is fixed in dd6f892: the idea is the fuzzing implementation all lives in RE another major concern for this PR:
I think this structure is clearer. Otherwise, integration tests would include regular, extended (slow), and fuzzing tests, making it awkward to maintain or run only a subset of them. Since splitting them doesn't seem to introduce any other issues, I went with the clearer structure. |
alamb
left a comment
There was a problem hiding this comment.
Thanks @2010YOUY01 -- looks good to me
I wonder if we should (as a follow on PR) add a note about fuzz testing to https://datafusion.apache.org/contributor-guide/testing.html
Specifically lay out the rationale / goal of in-project fuzz testing in an attempt to keep the implementations consistent
I'll do it soon, thanks again. |
> [!IMPORTANT] > > **Fork CI setup:** For pull requests from a fork to `main`, enable workflows in your fork's **Actions** tab before you push. > See the [fork CI setup guide](https://datafusion.apache.org/contributor-guide/#pull-requests-from-forks). ## Which issue does this PR close? <!-- We generally require a GitHub issue to be filed for all bug fixes and enhancements and this helps us generate change logs for our releases. You can link an issue to this PR using the GitHub syntax. For example `Closes apache#123` indicates that this PR will close issue apache#123. --> part of apache#27082 Follow up: apache#27048 ## Rationale for this change <!-- Why are you proposing this change? If this is already explained clearly in the issue then this section is not needed. Explaining clearly why changes are proposed helps reviewers understand your changes and offer better suggestions for fixes. Please explain the problem you are trying to solve in terms of the user-visible behavior, rather than the implementation. For example, "The code in `foo.rs` doesn't handle nulls" is a symptom of the implementation. "COUNT(DISTINCT) returns wrong results when the column contains nulls" is the user-visible problem. --> apache#27048 introduced a trait for implementing fuzzing UTs, this PR adds documentation for it. ## What changes are included in this PR? <!-- There is no need to duplicate the description in the issue here, but it is sometimes worth providing a summary of the individual changes in this PR. --> ## What is the testing strategy for this PR? <!-- We typically require tests for all PRs in order to: 1. Prevent the code from being accidentally broken by subsequent changes 2. Serve as another way to document the expected behavior of the code Briefly describe how this PR is tested, and point to the specific tests you added. For example: 'This new feature is covered by the `sqllogictest` cases added in `foo.slt`'. If this PR does not add tests, explain why. For example, if the change is already covered by existing tests, please mention it. You should also check the `codecov` bot reply on this PR to confirm the changed code is exercised. --> ## Are there any user-facing changes? <!-- If there are user-facing changes then we may require documentation to be updated before approving the PR. If there are any breaking changes to public APIs, please add the `api change` label. -->
…ache#27258) ## Which issue does this PR close? Part of apache#27082. ## Rationale for this change The `union_fuzz` test in `key_range_bitmap.rs` previously ran as a standalone `#[test]` using environment variables (`DATAFUSION_KEY_RANGE_UNION_FUZZ_ITERATIONS` and `DATAFUSION_KEY_RANGE_UNION_FUZZ_SEED`) without standardized budget controls or centralized failure reporting. Migrating this suite to the `FuzzTest` framework introduced in apache#27048 makes failures reproducible via seed reporting, connects it to the unified runner in `datafusion-fuzz`, and aligns it with project-wide fuzz testing conventions. ## What changes are included in this PR? - **`datafusion-physical-plan`**: - Expose `KeyRangePart` and `KeyRangeBitmap::union` so `datafusion-fuzz` can construct partitions and test union behavior. - Expose `offset(&self)`, `span(&self)`, `shift(&self)`, and `bits(&self)` getter accessors on `KeyRangeBitmap` for internal invariant checking. - Remove legacy `union_fuzz` and `run_union_scenario` test functions from `key_range_bitmap.rs`. - **`datafusion-fuzz`**: - Implement `KeyRangeBitmapFuzzer` in `tests/suites/key_range_bitmap.rs` implementing the `FuzzTest` trait. - Register `KeyRangeBitmapFuzzer` in `tests/fuzz.rs` and `tests/suites/mod.rs`. - **`xtask`**: - Remove `union_fuzz` from `LEGACY_FUZZ_TESTS` in `ci_steps.rs` and clean up legacy runner configuration and snapshots. ## What is the testing strategy for this PR? - Validated `datafusion-physical-plan` unit tests: - `cargo test -p datafusion-physical-plan --lib -- joins::key_range_bitmap` (all 4 unit tests pass) - Validated unified fuzz runner: - `cargo test -p datafusion-fuzz --test fuzz --features extended_tests` (256 cases pass) - Validated `xtask` legacy fuzz test verification: - `cargo test -p datafusion-xtask -- legacy_fuzz_tests_exist` ## Are there any user-facing changes? No user-facing changes.
Important
Fork CI setup: For pull requests from a fork to
main, enable workflows in your fork's Actions tab before you push.See the fork CI setup guide.
Which issue does this PR close?
Rationale for this change
Fuzz tests should follow these conventions:
the driver can run on a best-effort basis within a budget such as one minute.
Most of the existing implementations don't follow all of these principles, or implemented it with unnecessary complexity:
Refactoring to a shared trait can prevent these issues in the future.
This PR introduces a trait to enforce these conventions and migrates one fuzz unit test to use it. Other existing fuzzers remain available for later migration.
Demo
What changes are included in this PR?
Read the key changes in the following order; the remaining changes are minor.
FuzzTestintest-utils/src/fuzz.rs: a trait that ensures all fuzz testsfollow the intended conventions.
Suiteindatafusion/fuzz/tests/fuzz.rs: a single entry point for all fuzzunit tests in DataFusion.
SpillPoolFuzzerindatafusion/fuzz/tests/suites/spill_pool.rs: the first unittest migrated to the centralized
FuzzTesttrait and unified runner.The key API is introduced in step 1. After implementing several fuzz tests in datafusion, I came up with this design to capture their common patterns. I also asked Codex to check whether all existing fuzz tests can be migrated to this trait.
Step 2: using a unified test entry point make it easier to configure fuzzing time in the future. For example it's possible to deploy a long-running background fuzzing job.
What is the testing strategy for this PR?
Are there any user-facing changes?