1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-19 13:54:54 -05:00
denoland-deno/tests/util/server/src/macros.rs
Matt Mastracci b6e44f91ad
fix(cli): ensure that pre- and post-test output is flushed at the appropriate times (#22611)
Some `deno_std` tests were failing to print output that was resolved
after the last test finished. In addition, output printed before tests
began would sometimes appear above the "running X tests ..." line, and
sometimes below it depending on timing.

We now guarantee that all output is flushed before and after tests run,
making the output consistent.

Pre-test and post-test output are captured in `------ pre-test output
------` and `------ post-test output ------` blocks to differentiate
them from the regular output blocks.

Here's an example of a test (that is much noisier than normal, but an
example of what the output will look like):

```
Check ./load_unload.ts
------- pre-test output -------
load
----- output end -----
running 1 test from ./load_unload.ts
test ...
------- output -------
test
----- output end -----
test ... ok ([WILDCARD])
------- post-test output -------
unload
----- output end -----
```
2024-02-28 22:12:21 +00:00

129 lines
3.2 KiB
Rust

// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
#[macro_export]
// https://stackoverflow.com/questions/38088067/equivalent-of-func-or-function-in-rust
macro_rules! function {
() => {{
fn f() {}
fn type_name_of<T>(_: T) -> &'static str {
::std::any::type_name::<T>()
}
let name = type_name_of(f);
let name = name.strip_suffix("::f").unwrap_or(name);
let name = name.strip_suffix("::{{closure}}").unwrap_or(name);
name
}};
}
/// Detect a test timeout and panic with a message that includes the test name.
/// By default, the test timeout is 300 seconds (5 minutes), but any value may
/// be specified as an argument to this function.
#[macro_export]
macro_rules! timeout {
( $($timeout:literal)? ) => {
struct TestTimeoutHolder(::std::sync::mpsc::Sender<()>);
let _test_timeout_holder = {
let function = $crate::function!();
let (tx, rx) = ::std::sync::mpsc::channel::<()>();
let timeout: &[u64] = &[$($timeout)?];
let timeout = *timeout.get(0).unwrap_or(&300);
::std::thread::spawn(move || {
if rx.recv_timeout(::std::time::Duration::from_secs(timeout)) == Err(::std::sync::mpsc::RecvTimeoutError::Timeout) {
use std::io::Write;
eprintln!("Test {function} timed out after {timeout} seconds, aborting");
_ = std::io::stderr().flush();
::std::process::exit(1);
}
});
TestTimeoutHolder(tx)
};
};
}
#[macro_export]
macro_rules! itest(
($name:ident {$( $key:ident: $value:expr,)*}) => {
#[test]
fn $name() {
$crate::timeout!();
let test = $crate::CheckOutputIntegrationTest {
$(
$key: $value,
)*
.. Default::default()
};
let output = test.output();
output.assert_exit_code(test.exit_code);
if !test.output.is_empty() {
assert!(test.output_str.is_none());
output.assert_matches_file(test.output);
} else {
output.assert_matches_text(test.output_str.unwrap_or(""));
}
}
}
);
#[macro_export]
macro_rules! itest_flaky(
($name:ident {$( $key:ident: $value:expr,)*}) => {
#[flaky_test::flaky_test]
fn $name() {
$crate::timeout!();
let test = $crate::CheckOutputIntegrationTest {
$(
$key: $value,
)*
.. Default::default()
};
let output = test.output();
output.assert_exit_code(test.exit_code);
if !test.output.is_empty() {
assert!(test.output_str.is_none());
output.assert_matches_file(test.output);
} else {
output.assert_matches_text(test.output_str.unwrap_or(""));
}
}
}
);
#[macro_export]
macro_rules! context(
({$( $key:ident: $value:expr,)*}) => {
$crate::TestContext::create($crate::TestContextOptions {
$(
$key: $value,
)*
.. Default::default()
})
}
);
#[macro_export]
macro_rules! itest_steps(
($name:ident {$( $key:ident: $value:expr,)*}) => {
#[test]
fn $name() {
($crate::CheckOutputIntegrationTestSteps {
$(
$key: $value,
)*
.. Default::default()
}).run()
}
}
);
#[macro_export]
macro_rules! command_step(
({$( $key:ident: $value:expr,)*}) => {
$crate::CheckOutputIntegrationTestCommandStep {
$(
$key: $value,
)*
.. Default::default()
}
}
);