mirror of
https://github.com/denoland/deno.git
synced 2024-12-22 07:14:47 -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) {
|
||||
const [name, hint] = OP_DETAILS[key] || [key, null];
|
||||
const count = completedDiff - dispatchedDiff;
|
||||
ArrayPrototypePush(
|
||||
details,
|
||||
`${count} async operation${count === 1 ? "" : "s"} to ${name} ${
|
||||
count === 1 ? "was" : "were"
|
||||
} started before this test, but ${
|
||||
count === 1 ? "was" : "were"
|
||||
} 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}.` : ""}`,
|
||||
);
|
||||
let message = `${count} async operation${
|
||||
count === 1 ? "" : "s"
|
||||
} to ${name} ${
|
||||
count === 1 ? "was" : "were"
|
||||
} started before this test, but ${
|
||||
count === 1 ? "was" : "were"
|
||||
} completed during the test. Async operations should not complete in a test if they were not started in that test.`;
|
||||
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()] } };
|
||||
|
|
|
@ -255,6 +255,12 @@ itest!(trace_ops_catch_error {
|
|||
// 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 {
|
||||
args: "test --no-check test/ops_sanitizer_nexttick.ts",
|
||||
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?;
|
||||
|
||||
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.
|
||||
match worker.execute_side_module_possibly_with_npm().await {
|
||||
Ok(()) => {}
|
||||
|
@ -450,12 +457,7 @@ pub async fn test_specifier(
|
|||
}
|
||||
|
||||
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!())?;
|
||||
|
||||
let tests = {
|
||||
|
|
|
@ -12,6 +12,7 @@ use deno_core::futures::FutureExt;
|
|||
use deno_core::located_script_name;
|
||||
use deno_core::parking_lot::Mutex;
|
||||
use deno_core::url::Url;
|
||||
use deno_core::v8;
|
||||
use deno_core::CompiledWasmModuleStore;
|
||||
use deno_core::Extension;
|
||||
use deno_core::ModuleId;
|
||||
|
@ -279,6 +280,17 @@ impl CliMainWorker {
|
|||
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 {
|
||||
|
|
Loading…
Reference in a new issue