Skip to content
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

feat(bin): support --fail-fast #246

Merged
merged 2 commits into from
Jan 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

## [0.26.2] - 2025-01-08

* bin: support `--fail-fast`, and add env vars `SLT_FAIL_FAST` and `SLT_KEEP_DB_ON_FAILURE`

## [0.26.1] - 2025-01-08

* parser/runner: support `system ok retry`
Expand Down
6 changes: 3 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ resolver = "2"
members = ["sqllogictest", "sqllogictest-bin", "sqllogictest-engines", "tests"]

[workspace.package]
version = "0.26.1"
version = "0.26.2"
edition = "2021"
homepage = "https://github.com/risinglightdb/sqllogictest-rs"
keywords = ["sql", "database", "parser", "cli"]
Expand Down
53 changes: 50 additions & 3 deletions sqllogictest-bin/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,13 @@ struct Opt {
#[clap(long, short)]
jobs: Option<usize>,
/// When using `-j`, whether to keep the temporary database when a test case fails.
#[clap(long, default_value = "false")]
#[clap(long, default_value = "false", env = "SLT_KEEP_DB_ON_FAILURE")]
keep_db_on_failure: bool,

/// Whether to exit immediately when a test case fails.
#[clap(long, default_value = "false", env = "SLT_FAIL_FAST")]
fail_fast: bool,

/// Report to junit XML.
#[clap(long)]
junit: Option<String>,
Expand Down Expand Up @@ -150,6 +154,7 @@ pub async fn main() -> Result<()> {
color,
jobs,
keep_db_on_failure,
fail_fast,
junit,
host,
port,
Expand Down Expand Up @@ -239,6 +244,7 @@ pub async fn main() -> Result<()> {
config,
&labels,
junit.clone(),
fail_fast,
)
.await
} else {
Expand All @@ -249,6 +255,7 @@ pub async fn main() -> Result<()> {
config,
&labels,
junit.clone(),
fail_fast,
)
.await
};
Expand All @@ -272,6 +279,7 @@ async fn run_parallel(
config: DBConfig,
labels: &[String],
junit: Option<String>,
fail_fast: bool,
) -> Result<()> {
let mut create_databases = BTreeMap::new();
let mut filenames = BTreeSet::new();
Expand Down Expand Up @@ -332,11 +340,14 @@ async fn run_parallel(

let mut failed_case = vec![];
let mut failed_db: HashSet<String> = HashSet::new();
let mut remaining_files: HashSet<String> = HashSet::from_iter(filenames.clone());

let start = Instant::now();

while let Some((db_name, file, res, mut buf)) = stream.next().await {
remaining_files.remove(&file);
let test_case_name = file.replace(['/', ' ', '.', '-'], "_");
let mut failed = false;
let case = match res {
Ok(duration) => {
let mut case = TestCase::new(test_case_name, TestCaseStatus::success());
Expand All @@ -346,6 +357,7 @@ async fn run_parallel(
case
}
Err(e) => {
failed = true;
writeln!(buf, "{}\n\n{:?}", style("[FAILED]").red().bold(), e)?;
writeln!(buf)?;
failed_case.push(file.clone());
Expand All @@ -363,6 +375,20 @@ async fn run_parallel(
};
test_suite.add_test_case(case);
tokio::task::block_in_place(|| stdout().write_all(&buf))?;
if fail_fast && failed {
println!("early exit after failure...");
break;
}
}

for file in remaining_files {
println!("{file} is not finished, skipping");
let test_case_name = file.replace(['/', ' ', '.', '-'], "_");
let mut case = TestCase::new(test_case_name, TestCaseStatus::skipped());
case.set_time(Duration::from_millis(0));
case.set_timestamp(Local::now());
case.set_classname(junit.as_deref().unwrap_or_default());
test_suite.add_test_case(case);
}

eprintln!(
Expand Down Expand Up @@ -404,17 +430,20 @@ async fn run_serial(
config: DBConfig,
labels: &[String],
junit: Option<String>,
fail_fast: bool,
) -> Result<()> {
let mut failed_case = vec![];

for file in files {
let mut skipped_case = vec![];
let mut files = files.into_iter();
for file in &mut files {
let mut runner = Runner::new(|| engines::connect(engine, &config));
for label in labels {
runner.add_label(label);
}

let filename = file.to_string_lossy().to_string();
let test_case_name = filename.replace(['/', ' ', '.', '-'], "_");
let mut failed = false;
let case = match run_test_file(&mut std::io::stdout(), runner, &file).await {
Ok(duration) => {
let mut case = TestCase::new(test_case_name, TestCaseStatus::success());
Expand All @@ -424,6 +453,7 @@ async fn run_serial(
case
}
Err(e) => {
failed = true;
println!("{}\n\n{:?}", style("[FAILED]").red().bold(), e);
println!();
failed_case.push(filename.clone());
Expand All @@ -439,6 +469,23 @@ async fn run_serial(
}
};
test_suite.add_test_case(case);
if fail_fast && failed {
println!("early exit after failure...");
break;
}
}
for file in files {
let filename = file.to_string_lossy().to_string();
let test_case_name = filename.replace(['/', ' ', '.', '-'], "_");
let mut case = TestCase::new(test_case_name, TestCaseStatus::skipped());
case.set_time(Duration::from_millis(0));
case.set_timestamp(Local::now());
case.set_classname(junit.as_deref().unwrap_or_default());
test_suite.add_test_case(case);
skipped_case.push(filename.clone());
}
if !skipped_case.is_empty() {
println!("some test case skipped:\n{:#?}", skipped_case);
}

if !failed_case.is_empty() {
Expand Down
Loading