Browse Source

Correctly run async tests (#2683)

So, while working on #2658 I apparently broke 1280 tests... except I didn't! Turns out we were considering async tests that didn't call the `print` function as passed tests, but the `async` section of https://github.com/tc39/test262/blob/main/INTERPRETING.md#flags says:
> The test must not be considered complete until the implementation-defined print function has been invoked or some length of time has passed without any such invocation.
pull/2689/head
José Julián Espina 2 years ago
parent
commit
a53edeb4aa
  1. 47
      boa_tester/src/exec/mod.rs

47
boa_tester/src/exec/mod.rs

@ -198,8 +198,15 @@ impl Test {
context.run_jobs(); context.run_jobs();
if let Err(e) = async_result.inner.borrow().as_ref() { match *async_result.inner.borrow() {
return (false, format!("Uncaught {e}")); UninitResult::Err(ref e) => return (false, format!("Uncaught {e}")),
UninitResult::Uninit if self.flags.contains(TestFlags::ASYNC) => {
return (
false,
"async test did not print \"Test262:AsyncTestComplete\"".to_string(),
)
}
_ => {}
} }
(true, value.display().to_string()) (true, value.display().to_string())
@ -423,9 +430,19 @@ fn register_print_fn(context: &mut Context<'_>, async_result: AsyncResult) {
.get_or_undefined(0) .get_or_undefined(0)
.to_string(context)? .to_string(context)?
.to_std_string_escaped(); .to_std_string_escaped();
if message != "Test262:AsyncTestComplete" { let mut result = async_result.inner.borrow_mut();
*async_result.inner.borrow_mut() = Err(message);
match *result {
UninitResult::Uninit | UninitResult::Ok(_) => {
if message == "Test262:AsyncTestComplete" {
*result = UninitResult::Ok(());
} else {
*result = UninitResult::Err(message);
}
} }
UninitResult::Err(_) => {}
}
Ok(JsValue::undefined()) Ok(JsValue::undefined())
}) })
}, },
@ -440,17 +457,35 @@ fn register_print_fn(context: &mut Context<'_>, async_result: AsyncResult) {
Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE, Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
); );
} }
/// A `Result` value that is possibly uninitialized.
///
/// This is mainly used to check if an async test did call `print` to signal the termination of
/// a test. Otherwise, all async tests that result in `UninitResult::Uninit` are considered
/// as failed.
///
/// The Test262 [interpreting guide][guide] contains more information about how to run async tests.
///
/// [guide]: https://github.com/tc39/test262/blob/main/INTERPRETING.md#flags
#[derive(Debug, Clone, Copy, Default)]
enum UninitResult<T, E> {
#[default]
Uninit,
Ok(T),
Err(E),
}
/// Object which includes the result of the async operation. /// Object which includes the result of the async operation.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct AsyncResult { struct AsyncResult {
inner: Rc<RefCell<Result<(), String>>>, inner: Rc<RefCell<UninitResult<(), String>>>,
} }
impl Default for AsyncResult { impl Default for AsyncResult {
#[inline] #[inline]
fn default() -> Self { fn default() -> Self {
Self { Self {
inner: Rc::new(RefCell::new(Ok(()))), inner: Rc::new(RefCell::new(UninitResult::default())),
} }
} }
} }

Loading…
Cancel
Save