Skip to content

Commit 3c4ee72

Browse files
authoredJan 10, 2025··
feat(bin): support --fail-fast (#246)
* feat(bin): support --fail-fast close #110 Signed-off-by: xxchan <[email protected]> * add env var Signed-off-by: xxchan <[email protected]> --------- Signed-off-by: xxchan <[email protected]>
1 parent 1341f2c commit 3c4ee72

File tree

4 files changed

+58
-7
lines changed

4 files changed

+58
-7
lines changed
 

‎CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## Unreleased
99

10+
## [0.26.2] - 2025-01-08
11+
12+
* bin: support `--fail-fast`, and add env vars `SLT_FAIL_FAST` and `SLT_KEEP_DB_ON_FAILURE`
13+
1014
## [0.26.1] - 2025-01-08
1115

1216
* parser/runner: support `system ok retry`

‎Cargo.lock

+3-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ resolver = "2"
33
members = ["sqllogictest", "sqllogictest-bin", "sqllogictest-engines", "tests"]
44

55
[workspace.package]
6-
version = "0.26.1"
6+
version = "0.26.2"
77
edition = "2021"
88
homepage = "https://github.com/risinglightdb/sqllogictest-rs"
99
keywords = ["sql", "database", "parser", "cli"]

‎sqllogictest-bin/src/main.rs

+50-3
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,13 @@ struct Opt {
6363
#[clap(long, short)]
6464
jobs: Option<usize>,
6565
/// When using `-j`, whether to keep the temporary database when a test case fails.
66-
#[clap(long, default_value = "false")]
66+
#[clap(long, default_value = "false", env = "SLT_KEEP_DB_ON_FAILURE")]
6767
keep_db_on_failure: bool,
6868

69+
/// Whether to exit immediately when a test case fails.
70+
#[clap(long, default_value = "false", env = "SLT_FAIL_FAST")]
71+
fail_fast: bool,
72+
6973
/// Report to junit XML.
7074
#[clap(long)]
7175
junit: Option<String>,
@@ -150,6 +154,7 @@ pub async fn main() -> Result<()> {
150154
color,
151155
jobs,
152156
keep_db_on_failure,
157+
fail_fast,
153158
junit,
154159
host,
155160
port,
@@ -239,6 +244,7 @@ pub async fn main() -> Result<()> {
239244
config,
240245
&labels,
241246
junit.clone(),
247+
fail_fast,
242248
)
243249
.await
244250
} else {
@@ -249,6 +255,7 @@ pub async fn main() -> Result<()> {
249255
config,
250256
&labels,
251257
junit.clone(),
258+
fail_fast,
252259
)
253260
.await
254261
};
@@ -272,6 +279,7 @@ async fn run_parallel(
272279
config: DBConfig,
273280
labels: &[String],
274281
junit: Option<String>,
282+
fail_fast: bool,
275283
) -> Result<()> {
276284
let mut create_databases = BTreeMap::new();
277285
let mut filenames = BTreeSet::new();
@@ -332,11 +340,14 @@ async fn run_parallel(
332340

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

336345
let start = Instant::now();
337346

338347
while let Some((db_name, file, res, mut buf)) = stream.next().await {
348+
remaining_files.remove(&file);
339349
let test_case_name = file.replace(['/', ' ', '.', '-'], "_");
350+
let mut failed = false;
340351
let case = match res {
341352
Ok(duration) => {
342353
let mut case = TestCase::new(test_case_name, TestCaseStatus::success());
@@ -346,6 +357,7 @@ async fn run_parallel(
346357
case
347358
}
348359
Err(e) => {
360+
failed = true;
349361
writeln!(buf, "{}\n\n{:?}", style("[FAILED]").red().bold(), e)?;
350362
writeln!(buf)?;
351363
failed_case.push(file.clone());
@@ -363,6 +375,20 @@ async fn run_parallel(
363375
};
364376
test_suite.add_test_case(case);
365377
tokio::task::block_in_place(|| stdout().write_all(&buf))?;
378+
if fail_fast && failed {
379+
println!("early exit after failure...");
380+
break;
381+
}
382+
}
383+
384+
for file in remaining_files {
385+
println!("{file} is not finished, skipping");
386+
let test_case_name = file.replace(['/', ' ', '.', '-'], "_");
387+
let mut case = TestCase::new(test_case_name, TestCaseStatus::skipped());
388+
case.set_time(Duration::from_millis(0));
389+
case.set_timestamp(Local::now());
390+
case.set_classname(junit.as_deref().unwrap_or_default());
391+
test_suite.add_test_case(case);
366392
}
367393

368394
eprintln!(
@@ -404,17 +430,20 @@ async fn run_serial(
404430
config: DBConfig,
405431
labels: &[String],
406432
junit: Option<String>,
433+
fail_fast: bool,
407434
) -> Result<()> {
408435
let mut failed_case = vec![];
409-
410-
for file in files {
436+
let mut skipped_case = vec![];
437+
let mut files = files.into_iter();
438+
for file in &mut files {
411439
let mut runner = Runner::new(|| engines::connect(engine, &config));
412440
for label in labels {
413441
runner.add_label(label);
414442
}
415443

416444
let filename = file.to_string_lossy().to_string();
417445
let test_case_name = filename.replace(['/', ' ', '.', '-'], "_");
446+
let mut failed = false;
418447
let case = match run_test_file(&mut std::io::stdout(), runner, &file).await {
419448
Ok(duration) => {
420449
let mut case = TestCase::new(test_case_name, TestCaseStatus::success());
@@ -424,6 +453,7 @@ async fn run_serial(
424453
case
425454
}
426455
Err(e) => {
456+
failed = true;
427457
println!("{}\n\n{:?}", style("[FAILED]").red().bold(), e);
428458
println!();
429459
failed_case.push(filename.clone());
@@ -439,6 +469,23 @@ async fn run_serial(
439469
}
440470
};
441471
test_suite.add_test_case(case);
472+
if fail_fast && failed {
473+
println!("early exit after failure...");
474+
break;
475+
}
476+
}
477+
for file in files {
478+
let filename = file.to_string_lossy().to_string();
479+
let test_case_name = filename.replace(['/', ' ', '.', '-'], "_");
480+
let mut case = TestCase::new(test_case_name, TestCaseStatus::skipped());
481+
case.set_time(Duration::from_millis(0));
482+
case.set_timestamp(Local::now());
483+
case.set_classname(junit.as_deref().unwrap_or_default());
484+
test_suite.add_test_case(case);
485+
skipped_case.push(filename.clone());
486+
}
487+
if !skipped_case.is_empty() {
488+
println!("some test case skipped:\n{:#?}", skipped_case);
442489
}
443490

444491
if !failed_case.is_empty() {

0 commit comments

Comments
 (0)
Please sign in to comment.