1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-01-05 22:09:02 -05:00

fix(test): race condition for cancelled tests (#15233)

This commit is contained in:
Nayeem Rahman 2022-08-02 15:55:11 +01:00 committed by crowlkats
parent 58409d24bd
commit 850a98ce25
No known key found for this signature in database
GPG key ID: A82C9D461FC483E8
3 changed files with 32 additions and 23 deletions

View file

@ -1,6 +1,9 @@
running 2 tests from ./test/uncaught_errors_1.ts running 3 tests from ./test/uncaught_errors_1.ts
foo 1 ... FAILED ([WILDCARD]) foo 1 ... FAILED ([WILDCARD])
foo 2 ... ok ([WILDCARD]) foo 2 ... ok ([WILDCARD])
foo 3 ...
Uncaught error from ./test/uncaught_errors_1.ts FAILED
foo 3 ... cancelled (0ms)
running 3 tests from ./test/uncaught_errors_2.ts running 3 tests from ./test/uncaught_errors_2.ts
bar 1 ... ok ([WILDCARD]) bar 1 ... ok ([WILDCARD])
bar 2 ... FAILED ([WILDCARD]) bar 2 ... FAILED ([WILDCARD])
@ -15,6 +18,14 @@ error: Error: foo 1 message
^ ^
at [WILDCARD]/test/uncaught_errors_1.ts:2:9 at [WILDCARD]/test/uncaught_errors_1.ts:2:9
./test/uncaught_errors_1.ts (uncaught error)
error: (in promise) Error: foo 3 message
Promise.reject(new Error("foo 3 message"));
^
at [WILDCARD]/test/uncaught_errors_1.ts:8:18
This error was not caught from a test and caused the test runner to fail on the referenced module.
It most likely originated from a dangling promise, event/timeout handler or top-level code.
bar 2 => ./test/uncaught_errors_2.ts:3:6 bar 2 => ./test/uncaught_errors_2.ts:3:6
error: Error: bar 2 error: Error: bar 2
throw new Error("bar 2"); throw new Error("bar 2");
@ -38,10 +49,11 @@ It most likely originated from a dangling promise, event/timeout handler or top-
FAILURES FAILURES
foo 1 => ./test/uncaught_errors_1.ts:1:6 foo 1 => ./test/uncaught_errors_1.ts:1:6
./test/uncaught_errors_1.ts (uncaught error)
bar 2 => ./test/uncaught_errors_2.ts:3:6 bar 2 => ./test/uncaught_errors_2.ts:3:6
bar 3 => ./test/uncaught_errors_2.ts:6:6 bar 3 => ./test/uncaught_errors_2.ts:6:6
./test/uncaught_errors_3.ts (uncaught error) ./test/uncaught_errors_3.ts (uncaught error)
FAILED | 2 passed | 4 failed ([WILDCARD]) FAILED | 2 passed | 6 failed ([WILDCARD])
error: Test failed error: Test failed

View file

@ -3,3 +3,7 @@ Deno.test("foo 1", () => {
}); });
Deno.test("foo 2", () => {}); Deno.test("foo 2", () => {});
Deno.test("foo 3", () => {
Promise.reject(new Error("foo 3 message"));
});

View file

@ -34,7 +34,6 @@ use deno_core::futures::stream;
use deno_core::futures::FutureExt; use deno_core::futures::FutureExt;
use deno_core::futures::StreamExt; use deno_core::futures::StreamExt;
use deno_core::parking_lot::Mutex; use deno_core::parking_lot::Mutex;
use deno_core::parking_lot::RwLock;
use deno_core::serde_json::json; use deno_core::serde_json::json;
use deno_core::url::Url; use deno_core::url::Url;
use deno_core::ModuleSpecifier; use deno_core::ModuleSpecifier;
@ -1123,11 +1122,7 @@ async fn test_specifiers(
let sender = TestEventSender::new(sender); let sender = TestEventSender::new(sender);
let concurrent_jobs = options.concurrent_jobs; let concurrent_jobs = options.concurrent_jobs;
let fail_fast = options.fail_fast; let fail_fast = options.fail_fast;
let tests: Arc<RwLock<IndexMap<usize, TestDescription>>> =
Arc::new(RwLock::new(IndexMap::new()));
let mut test_steps = IndexMap::new();
let tests_ = tests.clone();
let join_handles = let join_handles =
specifiers_with_mode.iter().map(move |(specifier, mode)| { specifiers_with_mode.iter().map(move |(specifier, mode)| {
let ps = ps.clone(); let ps = ps.clone();
@ -1136,7 +1131,6 @@ async fn test_specifiers(
let mode = mode.clone(); let mode = mode.clone();
let mut sender = sender.clone(); let mut sender = sender.clone();
let options = options.clone(); let options = options.clone();
let tests = tests_.clone();
tokio::task::spawn_blocking(move || { tokio::task::spawn_blocking(move || {
let origin = specifier.to_string(); let origin = specifier.to_string();
@ -1151,18 +1145,9 @@ async fn test_specifiers(
if let Err(error) = file_result { if let Err(error) = file_result {
if error.is::<JsError>() { if error.is::<JsError>() {
sender.send(TestEvent::UncaughtError( sender.send(TestEvent::UncaughtError(
origin.clone(), origin,
Box::new(error.downcast::<JsError>().unwrap()), Box::new(error.downcast::<JsError>().unwrap()),
))?; ))?;
for desc in tests.read().values() {
if desc.origin == origin {
sender.send(TestEvent::Result(
desc.id,
TestResult::Cancelled,
0,
))?
}
}
} else { } else {
return Err(error); return Err(error);
} }
@ -1181,6 +1166,8 @@ async fn test_specifiers(
let handler = { let handler = {
tokio::task::spawn(async move { tokio::task::spawn(async move {
let earlier = Instant::now(); let earlier = Instant::now();
let mut tests = IndexMap::new();
let mut test_steps = IndexMap::new();
let mut tests_with_result = HashSet::new(); let mut tests_with_result = HashSet::new();
let mut summary = TestSummary::new(); let mut summary = TestSummary::new();
let mut used_only = false; let mut used_only = false;
@ -1189,7 +1176,7 @@ async fn test_specifiers(
match event { match event {
TestEvent::Register(description) => { TestEvent::Register(description) => {
reporter.report_register(&description); reporter.report_register(&description);
tests.write().insert(description.id, description); tests.insert(description.id, description);
} }
TestEvent::Plan(plan) => { TestEvent::Plan(plan) => {
@ -1204,7 +1191,7 @@ async fn test_specifiers(
} }
TestEvent::Wait(id) => { TestEvent::Wait(id) => {
reporter.report_wait(tests.read().get(&id).unwrap()); reporter.report_wait(tests.get(&id).unwrap());
} }
TestEvent::Output(output) => { TestEvent::Output(output) => {
@ -1213,7 +1200,7 @@ async fn test_specifiers(
TestEvent::Result(id, result, elapsed) => { TestEvent::Result(id, result, elapsed) => {
if tests_with_result.insert(id) { if tests_with_result.insert(id) {
let description = tests.read().get(&id).unwrap().clone(); let description = tests.get(&id).unwrap().clone();
match &result { match &result {
TestResult::Ok => { TestResult::Ok => {
summary.passed += 1; summary.passed += 1;
@ -1226,7 +1213,7 @@ async fn test_specifiers(
summary.failures.push((description.clone(), error.clone())); summary.failures.push((description.clone(), error.clone()));
} }
TestResult::Cancelled => { TestResult::Cancelled => {
summary.failed += 1; unreachable!("should be handled in TestEvent::UncaughtError");
} }
} }
reporter.report_result(&description, &result, elapsed); reporter.report_result(&description, &result, elapsed);
@ -1236,7 +1223,13 @@ async fn test_specifiers(
TestEvent::UncaughtError(origin, error) => { TestEvent::UncaughtError(origin, error) => {
reporter.report_uncaught_error(&origin, &error); reporter.report_uncaught_error(&origin, &error);
summary.failed += 1; summary.failed += 1;
summary.uncaught_errors.push((origin, error)); summary.uncaught_errors.push((origin.clone(), error));
for desc in tests.values() {
if desc.origin == origin && tests_with_result.insert(desc.id) {
summary.failed += 1;
reporter.report_result(desc, &TestResult::Cancelled, 0);
}
}
} }
TestEvent::StepRegister(description) => { TestEvent::StepRegister(description) => {