Skip to content

Commit

Permalink
Removed the boa_testing crate
Browse files Browse the repository at this point in the history
  • Loading branch information
Razican committed Apr 12, 2023
1 parent c2b1334 commit cc38810
Show file tree
Hide file tree
Showing 7 changed files with 212 additions and 360 deletions.
10 changes: 1 addition & 9 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 5 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ members = [
"boa_profiler",
"boa_runtime",
"boa_tester",
"boa_testing",
"boa_unicode",
"boa_wasm",
]
Expand All @@ -28,17 +27,16 @@ license = "Unlicense/MIT"
description = "Boa is a Javascript lexer, parser and compiler written in Rust. Currently, it has support for some of the language."

[workspace.dependencies]
boa_ast = { version = "0.16.0", path = "boa_ast" }
boa_engine = { version = "0.16.0", path = "boa_engine" }
boa_interner = { version = "0.16.0", path = "boa_interner" }
boa_gc = { version = "0.16.0", path = "boa_gc" }
boa_profiler = { version = "0.16.0", path = "boa_profiler" }
boa_unicode = { version = "0.16.0", path = "boa_unicode" }
boa_icu_provider = { version = "0.16.0", path = "boa_icu_provider" }
boa_interner = { version = "0.16.0", path = "boa_interner" }
boa_macros = { version = "0.16.0", path = "boa_macros" }
boa_ast = { version = "0.16.0", path = "boa_ast" }
boa_parser = { version = "0.16.0", path = "boa_parser" }
boa_icu_provider = { version = "0.16.0", path = "boa_icu_provider" }
boa_profiler = { version = "0.16.0", path = "boa_profiler" }
boa_runtime = { version = "0.16.0", path = "boa_runtime" }
boa_testing = { version = "0.16.0", path = "boa_testing" }
boa_unicode = { version = "0.16.0", path = "boa_unicode" }

[workspace.metadata.workspaces]
allow_branch = "main"
Expand Down
2 changes: 1 addition & 1 deletion boa_runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,5 @@ boa_gc.workspace = true
rustc-hash = "1.1.0"

[dev-dependencies]
boa_testing.workspace = true
indoc = "2.0.1"
textwrap = "0.16.0"
2 changes: 1 addition & 1 deletion boa_runtime/src/console/tests.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::{formatter, Console};
use crate::test::{run_test_actions, run_test_actions_with, TestAction};
use boa_engine::{property::Attribute, Context, JsValue};
use boa_testing::{run_test_actions, run_test_actions_with, TestAction};
use indoc::indoc;

#[test]
Expand Down
204 changes: 204 additions & 0 deletions boa_runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,207 @@ mod console;

#[doc(inline)]
pub use console::Console;

#[cfg(test)]
pub(crate) mod test {
use boa_engine::{builtins, Context, JsResult, JsValue, Source};
use std::borrow::Cow;

/// A test action executed in a test function.
#[allow(missing_debug_implementations)]
#[derive(Clone)]
pub(crate) struct TestAction(Inner);

#[derive(Clone)]
#[allow(dead_code)]
enum Inner {
RunHarness,
Run {
source: Cow<'static, str>,
},
InspectContext {
op: fn(&mut Context<'_>),
},
Assert {
source: Cow<'static, str>,
},
AssertEq {
source: Cow<'static, str>,
expected: JsValue,
},
AssertWithOp {
source: Cow<'static, str>,
op: fn(JsValue, &mut Context<'_>) -> bool,
},
AssertOpaqueError {
source: Cow<'static, str>,
expected: JsValue,
},
AssertNativeError {
source: Cow<'static, str>,
kind: builtins::error::ErrorKind,
message: &'static str,
},
AssertContext {
op: fn(&mut Context<'_>) -> bool,
},
}

impl TestAction {
/// Runs `source`, panicking if the execution throws.
pub(crate) fn run(source: impl Into<Cow<'static, str>>) -> Self {
Self(Inner::Run {
source: source.into(),
})
}

/// Executes `op` with the currently active context.
///
/// Useful to make custom assertions that must be done from Rust code.
pub(crate) fn inspect_context(op: fn(&mut Context<'_>)) -> Self {
Self(Inner::InspectContext { op })
}
}

/// Executes a list of test actions on a new, default context.
#[track_caller]
pub(crate) fn run_test_actions(actions: impl IntoIterator<Item = TestAction>) {
let context = &mut Context::default();
run_test_actions_with(actions, context);
}

/// Executes a list of test actions on the provided context.
#[track_caller]
#[allow(clippy::too_many_lines, clippy::missing_panics_doc)]
pub(crate) fn run_test_actions_with(
actions: impl IntoIterator<Item = TestAction>,
context: &mut Context<'_>,
) {
#[track_caller]
fn forward_val(context: &mut Context<'_>, source: &str) -> JsResult<JsValue> {
context.eval_script(Source::from_bytes(source))
}

#[track_caller]
fn fmt_test(source: &str, test: usize) -> String {
format!(
"\n\nTest case {test}: \n```\n{}\n```",
textwrap::indent(source, " ")
)
}

// Some unwrapping patterns look weird because they're replaceable
// by simpler patterns like `unwrap_or_else` or `unwrap_err
let mut i = 1;
for action in actions.into_iter().map(|a| a.0) {
match action {
Inner::RunHarness => {
// add utility functions for testing
// TODO: extract to a file
forward_val(
context,
r#"
function equals(a, b) {
if (Array.isArray(a) && Array.isArray(b)) {
return arrayEquals(a, b);
}
return a === b;
}
function arrayEquals(a, b) {
return Array.isArray(a) &&
Array.isArray(b) &&
a.length === b.length &&
a.every((val, index) => equals(val, b[index]));
}
"#,
)
.expect("failed to evaluate test harness");
}
Inner::Run { source } => {
if let Err(e) = forward_val(context, &source) {
panic!("{}\nUncaught {e}", fmt_test(&source, i));
}
}
Inner::InspectContext { op } => {
op(context);
}
Inner::Assert { source } => {
let val = match forward_val(context, &source) {
Err(e) => panic!("{}\nUncaught {e}", fmt_test(&source, i)),
Ok(v) => v,
};
let Some(val) = val.as_boolean() else {
panic!(
"{}\nTried to assert with the non-boolean value `{}`",
fmt_test(&source, i),
val.display()
)
};
assert!(val, "{}", fmt_test(&source, i));
i += 1;
}
Inner::AssertEq { source, expected } => {
let val = match forward_val(context, &source) {
Err(e) => panic!("{}\nUncaught {e}", fmt_test(&source, i)),
Ok(v) => v,
};
assert_eq!(val, expected, "{}", fmt_test(&source, i));
i += 1;
}
Inner::AssertWithOp { source, op } => {
let val = match forward_val(context, &source) {
Err(e) => panic!("{}\nUncaught {e}", fmt_test(&source, i)),
Ok(v) => v,
};
assert!(op(val, context), "{}", fmt_test(&source, i));
i += 1;
}
Inner::AssertOpaqueError { source, expected } => {
let err = match forward_val(context, &source) {
Ok(v) => panic!(
"{}\nExpected error, got value `{}`",
fmt_test(&source, i),
v.display()
),
Err(e) => e,
};
let Some(err) = err.as_opaque() else {
panic!("{}\nExpected opaque error, got native error `{}`", fmt_test(&source, i), err)
};

assert_eq!(err, &expected, "{}", fmt_test(&source, i));
i += 1;
}
Inner::AssertNativeError {
source,
kind,
message,
} => {
let err = match forward_val(context, &source) {
Ok(v) => panic!(
"{}\nExpected error, got value `{}`",
fmt_test(&source, i),
v.display()
),
Err(e) => e,
};
let native = match err.try_native(context) {
Ok(err) => err,
Err(e) => panic!(
"{}\nCouldn't obtain a native error: {e}",
fmt_test(&source, i)
),
};

assert_eq!(&native.kind, &kind, "{}", fmt_test(&source, i));
assert_eq!(native.message(), message, "{}", fmt_test(&source, i));
i += 1;
}
Inner::AssertContext { op } => {
assert!(op(context), "Test case {i}");
i += 1;
}
}
}
}
}
15 changes: 0 additions & 15 deletions boa_testing/Cargo.toml

This file was deleted.

Loading

0 comments on commit cc38810

Please sign in to comment.