mirror of
https://github.com/denoland/deno.git
synced 2025-01-03 04:48:52 -05:00
fix: output traces for op sanitizer in more cases (#20494)
This adds traces for the "started outside test, closed inside test" case.
This commit is contained in:
parent
bbb348aa33
commit
851f795001
6 changed files with 74 additions and 15 deletions
|
@ -206,15 +206,30 @@ function assertOps(fn) {
|
||||||
} else if (dispatchedDiff < completedDiff) {
|
} else if (dispatchedDiff < completedDiff) {
|
||||||
const [name, hint] = OP_DETAILS[key] || [key, null];
|
const [name, hint] = OP_DETAILS[key] || [key, null];
|
||||||
const count = completedDiff - dispatchedDiff;
|
const count = completedDiff - dispatchedDiff;
|
||||||
ArrayPrototypePush(
|
let message = `${count} async operation${
|
||||||
details,
|
count === 1 ? "" : "s"
|
||||||
`${count} async operation${count === 1 ? "" : "s"} to ${name} ${
|
} to ${name} ${
|
||||||
count === 1 ? "was" : "were"
|
count === 1 ? "was" : "were"
|
||||||
} started before this test, but ${
|
} started before this test, but ${
|
||||||
count === 1 ? "was" : "were"
|
count === 1 ? "was" : "were"
|
||||||
} completed during the test. Async operations should not complete in a test if they were not started in that test.
|
} completed during the test. Async operations should not complete in a test if they were not started in that test.`;
|
||||||
${hint ? `This is often caused by not ${hint}.` : ""}`,
|
if (hint) {
|
||||||
);
|
message += ` This is often caused by not ${hint}.`;
|
||||||
|
}
|
||||||
|
const traces = [];
|
||||||
|
for (const [id, { opName, stack }] of preTraces) {
|
||||||
|
if (opName !== key) continue;
|
||||||
|
if (MapPrototypeHas(postTraces, id)) continue;
|
||||||
|
ArrayPrototypePush(traces, stack);
|
||||||
|
}
|
||||||
|
if (traces.length === 1) {
|
||||||
|
message += " The operation was started here:\n";
|
||||||
|
message += traces[0];
|
||||||
|
} else if (traces.length > 1) {
|
||||||
|
message += " The operations were started here:\n";
|
||||||
|
message += ArrayPrototypeJoin(traces, "\n\n");
|
||||||
|
}
|
||||||
|
ArrayPrototypePush(details, message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return { failed: { leakedOps: [details, core.isOpCallTracingEnabled()] } };
|
return { failed: { leakedOps: [details, core.isOpCallTracingEnabled()] } };
|
||||||
|
|
|
@ -255,6 +255,12 @@ itest!(trace_ops_catch_error {
|
||||||
// output: "test/ops_sanitizer_missing_details.out",
|
// output: "test/ops_sanitizer_missing_details.out",
|
||||||
// });
|
// });
|
||||||
|
|
||||||
|
itest!(ops_sanitizer_closed_inside_started_before {
|
||||||
|
args: "test --trace-ops test/ops_sanitizer_closed_inside_started_before.ts",
|
||||||
|
exit_code: 1,
|
||||||
|
output: "test/ops_sanitizer_closed_inside_started_before.out",
|
||||||
|
});
|
||||||
|
|
||||||
itest!(ops_sanitizer_nexttick {
|
itest!(ops_sanitizer_nexttick {
|
||||||
args: "test --no-check test/ops_sanitizer_nexttick.ts",
|
args: "test --no-check test/ops_sanitizer_nexttick.ts",
|
||||||
output: "test/ops_sanitizer_nexttick.out",
|
output: "test/ops_sanitizer_nexttick.out",
|
||||||
|
|
19
cli/tests/testdata/test/ops_sanitizer_closed_inside_started_before.out
vendored
Normal file
19
cli/tests/testdata/test/ops_sanitizer_closed_inside_started_before.out
vendored
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
Check [WILDCARD]test/ops_sanitizer_closed_inside_started_before.ts
|
||||||
|
running 1 test from ./test/ops_sanitizer_closed_inside_started_before.ts
|
||||||
|
test 1 ... FAILED [WILDCARD]
|
||||||
|
|
||||||
|
ERRORS
|
||||||
|
|
||||||
|
test 1 => ./test/ops_sanitizer_closed_inside_started_before.ts:[WILDCARD]
|
||||||
|
error: Leaking async ops:
|
||||||
|
- 1 async operation to sleep for a duration was started before this test, but was completed during the test. Async operations should not complete in a test if they were not started in that test. This is often caused by not cancelling a `setTimeout` or `setInterval` call. The operation was started here:
|
||||||
|
at [WILDCARD]
|
||||||
|
at [WILDCARD]/cli/tests/testdata/test/ops_sanitizer_closed_inside_started_before.ts:[WILDCARD]
|
||||||
|
|
||||||
|
FAILURES
|
||||||
|
|
||||||
|
test 1 => ./test/ops_sanitizer_closed_inside_started_before.ts:[WILDCARD]
|
||||||
|
|
||||||
|
FAILED | 0 passed | 1 failed [WILDCARD]
|
||||||
|
|
||||||
|
error: Test failed
|
5
cli/tests/testdata/test/ops_sanitizer_closed_inside_started_before.ts
vendored
Normal file
5
cli/tests/testdata/test/ops_sanitizer_closed_inside_started_before.ts
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
const timer = setTimeout(() => {}, 10000000000);
|
||||||
|
|
||||||
|
Deno.test("test 1", () => {
|
||||||
|
clearTimeout(timer);
|
||||||
|
});
|
|
@ -433,6 +433,13 @@ pub async fn test_specifier(
|
||||||
|
|
||||||
let mut coverage_collector = worker.maybe_setup_coverage_collector().await?;
|
let mut coverage_collector = worker.maybe_setup_coverage_collector().await?;
|
||||||
|
|
||||||
|
if options.trace_ops {
|
||||||
|
worker.execute_script_static(
|
||||||
|
located_script_name!(),
|
||||||
|
"Deno[Deno.internal].core.enableOpCallTracing();",
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
// We execute the main module as a side module so that import.meta.main is not set.
|
// We execute the main module as a side module so that import.meta.main is not set.
|
||||||
match worker.execute_side_module_possibly_with_npm().await {
|
match worker.execute_side_module_possibly_with_npm().await {
|
||||||
Ok(()) => {}
|
Ok(()) => {}
|
||||||
|
@ -450,12 +457,7 @@ pub async fn test_specifier(
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut worker = worker.into_main_worker();
|
let mut worker = worker.into_main_worker();
|
||||||
if options.trace_ops {
|
|
||||||
worker.js_runtime.execute_script_static(
|
|
||||||
located_script_name!(),
|
|
||||||
"Deno[Deno.internal].core.enableOpCallTracing();",
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
worker.dispatch_load_event(located_script_name!())?;
|
worker.dispatch_load_event(located_script_name!())?;
|
||||||
|
|
||||||
let tests = {
|
let tests = {
|
||||||
|
|
|
@ -12,6 +12,7 @@ use deno_core::futures::FutureExt;
|
||||||
use deno_core::located_script_name;
|
use deno_core::located_script_name;
|
||||||
use deno_core::parking_lot::Mutex;
|
use deno_core::parking_lot::Mutex;
|
||||||
use deno_core::url::Url;
|
use deno_core::url::Url;
|
||||||
|
use deno_core::v8;
|
||||||
use deno_core::CompiledWasmModuleStore;
|
use deno_core::CompiledWasmModuleStore;
|
||||||
use deno_core::Extension;
|
use deno_core::Extension;
|
||||||
use deno_core::ModuleId;
|
use deno_core::ModuleId;
|
||||||
|
@ -279,6 +280,17 @@ impl CliMainWorker {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn execute_script_static(
|
||||||
|
&mut self,
|
||||||
|
name: &'static str,
|
||||||
|
source_code: &'static str,
|
||||||
|
) -> Result<v8::Global<v8::Value>, AnyError> {
|
||||||
|
self
|
||||||
|
.worker
|
||||||
|
.js_runtime
|
||||||
|
.execute_script_static(name, source_code)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CliMainWorkerFactory {
|
pub struct CliMainWorkerFactory {
|
||||||
|
|
Loading…
Reference in a new issue