-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Improve AggregationFuzzer error reporting #12832
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
Changes from all commits
addd225
61ab262
50c068c
c498e59
601d8b1
005ec14
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,6 +19,7 @@ use std::sync::Arc; | |
|
|
||
| use arrow::util::pretty::pretty_format_batches; | ||
| use arrow_array::RecordBatch; | ||
| use datafusion_common::{DataFusionError, Result}; | ||
| use rand::{thread_rng, Rng}; | ||
| use tokio::task::JoinSet; | ||
|
|
||
|
|
@@ -132,7 +133,20 @@ struct QueryGroup { | |
| } | ||
|
|
||
| impl AggregationFuzzer { | ||
| /// Run the fuzzer, printing an error and panicking if any of the tasks fail | ||
| pub async fn run(&self) { | ||
| let res = self.run_inner().await; | ||
|
|
||
| if let Err(e) = res { | ||
| // Print the error via `Display` so that it displays nicely (the default `unwrap()` | ||
| // prints using `Debug` which escapes newlines, and makes multi-line messages | ||
| // hard to read | ||
| println!("{e}"); | ||
| panic!("Error!"); | ||
| } | ||
| } | ||
|
|
||
| async fn run_inner(&self) -> Result<()> { | ||
| let mut join_set = JoinSet::new(); | ||
| let mut rng = thread_rng(); | ||
|
|
||
|
|
@@ -157,16 +171,20 @@ impl AggregationFuzzer { | |
|
|
||
| let tasks = self.generate_fuzz_tasks(query_groups).await; | ||
| for task in tasks { | ||
| join_set.spawn(async move { | ||
| task.run().await; | ||
| }); | ||
| join_set.spawn(async move { task.run().await }); | ||
| } | ||
| } | ||
|
|
||
| while let Some(join_handle) = join_set.join_next().await { | ||
| // propagate errors | ||
| join_handle.unwrap(); | ||
| join_handle.map_err(|e| { | ||
| DataFusionError::Internal(format!( | ||
| "AggregationFuzzer task error: {:?}", | ||
| e | ||
| )) | ||
| })??; | ||
| } | ||
| Ok(()) | ||
| } | ||
|
|
||
| async fn generate_fuzz_tasks( | ||
|
|
@@ -237,45 +255,53 @@ struct AggregationFuzzTestTask { | |
| } | ||
|
|
||
| impl AggregationFuzzTestTask { | ||
| async fn run(&self) { | ||
| async fn run(&self) -> Result<()> { | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the key change is to return an actual |
||
| let task_result = run_sql(&self.sql, &self.ctx_with_params.ctx) | ||
| .await | ||
| .expect("should success to run sql"); | ||
| self.check_result(&task_result, &self.expected_result); | ||
| .map_err(|e| e.context(self.context_error_report()))?; | ||
| self.check_result(&task_result, &self.expected_result) | ||
| } | ||
|
|
||
| // TODO: maybe we should persist the `expected_result` and `task_result`, | ||
| // because the readability is not so good if we just print it. | ||
| fn check_result(&self, task_result: &[RecordBatch], expected_result: &[RecordBatch]) { | ||
| let result = check_equality_of_batches(task_result, expected_result); | ||
| if let Err(e) = result { | ||
| fn check_result( | ||
| &self, | ||
| task_result: &[RecordBatch], | ||
| expected_result: &[RecordBatch], | ||
| ) -> Result<()> { | ||
| check_equality_of_batches(task_result, expected_result).map_err(|e| { | ||
| // If we found inconsistent result, we print the test details for reproducing at first | ||
| println!( | ||
| "##### AggregationFuzzer error report ##### | ||
| ### Sql:\n{}\n\ | ||
| ### Schema:\n{}\n\ | ||
| ### Session context params:\n{:?}\n\ | ||
| ### Inconsistent row:\n\ | ||
| - row_idx:{}\n\ | ||
| - task_row:{}\n\ | ||
| - expected_row:{}\n\ | ||
| ### Task total result:\n{}\n\ | ||
| ### Expected total result:\n{}\n\ | ||
| ### Input:\n{}\n\ | ||
| ", | ||
| self.sql, | ||
| self.dataset_ref.batches[0].schema_ref(), | ||
| self.ctx_with_params.params, | ||
| let message = format!( | ||
| "{}\n\ | ||
| ### Inconsistent row:\n\ | ||
| - row_idx:{}\n\ | ||
| - task_row:{}\n\ | ||
| - expected_row:{}\n\ | ||
| ### Task total result:\n{}\n\ | ||
| ### Expected total result:\n{}\n\ | ||
| ", | ||
| self.context_error_report(), | ||
| e.row_idx, | ||
| e.lhs_row, | ||
| e.rhs_row, | ||
| pretty_format_batches(task_result).unwrap(), | ||
| pretty_format_batches(expected_result).unwrap(), | ||
| pretty_format_batches(&self.dataset_ref.batches).unwrap(), | ||
| ); | ||
| DataFusionError::Internal(message) | ||
| }) | ||
| } | ||
|
|
||
| // Then we just panic | ||
| panic!(); | ||
| } | ||
| /// Returns a formatted error message | ||
| fn context_error_report(&self) -> String { | ||
| format!( | ||
| "##### AggregationFuzzer error report #####\n\ | ||
| ### Sql:\n{}\n\ | ||
| ### Schema:\n{}\n\ | ||
| ### Session context params:\n{:?}\n\ | ||
|
Comment on lines
+296
to
+298
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we will also care about some information about reproducing like
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that information is already included when inconsistent results are detected (in
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, it is my mistake, I see it now. |
||
| ### Input:\n{}\n\ | ||
| ", | ||
| self.sql, | ||
| self.dataset_ref.batches[0].schema_ref(), | ||
| self.ctx_with_params.params, | ||
| pretty_format_batches(&self.dataset_ref.batches).unwrap(), | ||
| ) | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.