-
Notifications
You must be signed in to change notification settings - Fork 1.9k
[sqllogictest] Read subdirectories in test_files
#5033
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
5d6faf2
a24fbfe
276db16
93f4ffd
f8b9d47
7e08340
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 | ||||
|---|---|---|---|---|---|---|
|
|
@@ -29,7 +29,7 @@ mod engines; | |||||
| mod setup; | ||||||
| mod utils; | ||||||
|
|
||||||
| const TEST_DIRECTORY: &str = "tests/sqllogictests/test_files"; | ||||||
| const TEST_DIRECTORY: &str = "tests/sqllogictests/test_files/"; | ||||||
| const PG_COMPAT_FILE_PREFIX: &str = "pg_compat_"; | ||||||
|
|
||||||
| #[tokio::main] | ||||||
|
|
@@ -47,40 +47,37 @@ pub async fn main() -> Result<(), Box<dyn Error>> { | |||||
|
|
||||||
| let options = Options::new(); | ||||||
|
|
||||||
| let files: Vec<_> = read_test_files(&options); | ||||||
|
|
||||||
| info!("Running test files {:?}", files); | ||||||
|
|
||||||
| for path in files { | ||||||
| let file_name = path.file_name().unwrap().to_str().unwrap().to_string(); | ||||||
|
|
||||||
| for (path, relative_path) in read_test_files(&options) { | ||||||
| if options.complete_mode { | ||||||
| run_complete_file(&path, file_name).await?; | ||||||
| run_complete_file(&path, relative_path).await?; | ||||||
| } else if options.postgres_runner { | ||||||
| run_test_file_with_postgres(&path, file_name).await?; | ||||||
| run_test_file_with_postgres(&path, relative_path).await?; | ||||||
| } else { | ||||||
| run_test_file(&path, file_name).await?; | ||||||
| run_test_file(&path, relative_path).await?; | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| Ok(()) | ||||||
| } | ||||||
|
|
||||||
| async fn run_test_file(path: &PathBuf, file_name: String) -> Result<(), Box<dyn Error>> { | ||||||
| println!("Running with DataFusion runner: {}", path.display()); | ||||||
| let ctx = context_for_test_file(&file_name).await; | ||||||
| let mut runner = sqllogictest::Runner::new(DataFusion::new(ctx, file_name)); | ||||||
| async fn run_test_file( | ||||||
| path: &Path, | ||||||
| relative_path: PathBuf, | ||||||
| ) -> Result<(), Box<dyn Error>> { | ||||||
| info!("Running with DataFusion runner: {}", path.display()); | ||||||
| let ctx = context_for_test_file(&relative_path).await; | ||||||
| let mut runner = sqllogictest::Runner::new(DataFusion::new(ctx, relative_path)); | ||||||
| runner.run_file_async(path).await?; | ||||||
| Ok(()) | ||||||
| } | ||||||
|
|
||||||
| async fn run_test_file_with_postgres( | ||||||
| path: &PathBuf, | ||||||
| file_name: String, | ||||||
| path: &Path, | ||||||
| relative_path: PathBuf, | ||||||
| ) -> Result<(), Box<dyn Error>> { | ||||||
| info!("Running with Postgres runner: {}", path.display()); | ||||||
|
|
||||||
| let postgres_client = Postgres::connect(file_name).await?; | ||||||
| let postgres_client = Postgres::connect(relative_path).await?; | ||||||
|
|
||||||
| sqllogictest::Runner::new(postgres_client) | ||||||
| .run_file_async(path) | ||||||
|
|
@@ -90,17 +87,15 @@ async fn run_test_file_with_postgres( | |||||
| } | ||||||
|
|
||||||
| async fn run_complete_file( | ||||||
| path: &PathBuf, | ||||||
| file_name: String, | ||||||
| path: &Path, | ||||||
| relative_path: PathBuf, | ||||||
| ) -> Result<(), Box<dyn Error>> { | ||||||
| use sqllogictest::{default_validator, update_test_file}; | ||||||
|
|
||||||
| info!("Using complete mode to complete: {}", path.display()); | ||||||
|
|
||||||
| let ctx = context_for_test_file(&file_name).await; | ||||||
| let mut runner = sqllogictest::Runner::new(DataFusion::new(ctx, file_name)); | ||||||
|
|
||||||
| info!("Using complete mode to complete {}", path.display()); | ||||||
| let ctx = context_for_test_file(&relative_path).await; | ||||||
| let mut runner = sqllogictest::Runner::new(DataFusion::new(ctx, relative_path)); | ||||||
| let col_separator = " "; | ||||||
| let validator = default_validator; | ||||||
| update_test_file(path, &mut runner, col_separator, validator) | ||||||
|
|
@@ -110,18 +105,42 @@ async fn run_complete_file( | |||||
| Ok(()) | ||||||
| } | ||||||
|
|
||||||
| fn read_test_files(options: &Options) -> Vec<PathBuf> { | ||||||
| std::fs::read_dir(TEST_DIRECTORY) | ||||||
| .unwrap() | ||||||
| .map(|path| path.unwrap().path()) | ||||||
| .filter(|path| options.check_test_file(path.as_path())) | ||||||
| .filter(|path| options.check_pg_compat_file(path.as_path())) | ||||||
| .collect() | ||||||
| fn read_test_files<'a>( | ||||||
| options: &'a Options, | ||||||
| ) -> Box<dyn Iterator<Item = (PathBuf, PathBuf)> + 'a> { | ||||||
| Box::new( | ||||||
| read_dir_recursive(TEST_DIRECTORY) | ||||||
| .map(|path| { | ||||||
| ( | ||||||
| path.clone(), | ||||||
| PathBuf::from( | ||||||
| path.to_string_lossy().strip_prefix(TEST_DIRECTORY).unwrap(), | ||||||
| ), | ||||||
| ) | ||||||
| }) | ||||||
| .filter(|(_, relative_path)| options.check_test_file(relative_path)) | ||||||
| .filter(|(path, _)| options.check_pg_compat_file(path.as_path())), | ||||||
| ) | ||||||
| } | ||||||
|
|
||||||
| fn read_dir_recursive<P: AsRef<Path>>(path: P) -> Box<dyn Iterator<Item = PathBuf>> { | ||||||
|
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.
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. I agree walkdir is not needed
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. I think you might be able to avoid the Box using something like
Suggested change
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 thing is that the resolved type for the whole implementation inside this function is It is probably possible to apply your suggestion, but my rust skills were not good enough.
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. I think https://docs.rs/itertools/latest/itertools/enum.Either.html# is one way to handle this. However, I don't think it is important to change |
||||||
| Box::new( | ||||||
| std::fs::read_dir(path) | ||||||
| .expect("Readable directory") | ||||||
| .map(|path| path.expect("Readable entry").path()) | ||||||
| .flat_map(|path| { | ||||||
| if path.is_dir() { | ||||||
| read_dir_recursive(path) | ||||||
| } else { | ||||||
| Box::new(std::iter::once(path)) | ||||||
| } | ||||||
| }), | ||||||
| ) | ||||||
| } | ||||||
|
|
||||||
| /// Create a SessionContext, configured for the specific test | ||||||
| async fn context_for_test_file(file_name: &str) -> SessionContext { | ||||||
| match file_name { | ||||||
| async fn context_for_test_file(relative_path: &Path) -> SessionContext { | ||||||
| match relative_path.file_name().unwrap().to_str().unwrap() { | ||||||
| "aggregate.slt" | "select.slt" => { | ||||||
| info!("Registering aggregate tables"); | ||||||
| let ctx = SessionContext::new(); | ||||||
|
|
@@ -185,14 +204,15 @@ impl Options { | |||||
| /// To be compatible with this, treat the command line arguments as a | ||||||
| /// filter and that does a substring match on each input. returns | ||||||
| /// true f this path should be run | ||||||
| fn check_test_file(&self, path: &Path) -> bool { | ||||||
| fn check_test_file(&self, relative_path: &Path) -> bool { | ||||||
| if self.filters.is_empty() { | ||||||
| return true; | ||||||
| } | ||||||
|
|
||||||
| // otherwise check if any filter matches | ||||||
| let path_str = path.to_string_lossy(); | ||||||
| self.filters.iter().any(|filter| path_str.contains(filter)) | ||||||
| self.filters | ||||||
| .iter() | ||||||
| .any(|filter| relative_path.to_string_lossy().contains(filter)) | ||||||
| } | ||||||
|
|
||||||
| /// Postgres runner executes only tests in files with specific names | ||||||
|
|
||||||
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.
Postgres file filter doesn't account for folder names, but it can. For example, instead of expecting a
pg_compatprefix on the file name, the runner could check this prefix on a relative file path.