mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-04 12:18:19 +00:00
Infrastructure to test and implement the replacement of an 'expect' failure with an error production
Last command run was 'cargo test expect_fail'
This commit is contained in:
parent
922d8e57c7
commit
085c02ffee
7 changed files with 108 additions and 36 deletions
|
@ -305,10 +305,15 @@ pub fn getExpectFailures() []Failure {
|
|||
return failures[0..failure_length];
|
||||
}
|
||||
|
||||
pub fn getExpectFailuresC() callconv(.C) *c_void {
|
||||
const CSlice = extern struct {
|
||||
pointer: *c_void,
|
||||
len: usize,
|
||||
};
|
||||
pub fn getExpectFailuresC() callconv(.C) CSlice {
|
||||
|
||||
var bytes = @ptrCast(*c_void, failures);
|
||||
|
||||
return bytes;
|
||||
return .{.pointer = bytes, .len = failure_length};
|
||||
}
|
||||
|
||||
pub fn deinitFailures() void {
|
||||
|
|
|
@ -316,3 +316,6 @@ pub const UTILS_TEST_PANIC: &str = "roc_builtins.utils.test_panic";
|
|||
pub const UTILS_INCREF: &str = "roc_builtins.utils.incref";
|
||||
pub const UTILS_DECREF: &str = "roc_builtins.utils.decref";
|
||||
pub const UTILS_DECREF_CHECK_NULL: &str = "roc_builtins.utils.decref_check_null";
|
||||
pub const UTILS_EXPECT_FAILED: &str = "roc_builtins.utils.expect_failed";
|
||||
pub const UTILS_GET_EXPECT_FAILURES: &str = "roc_builtins.utils.get_expect_failures";
|
||||
pub const UTILS_DEINIT_FAILURES: &str = "roc_builtins.utils.deinit_failures";
|
||||
|
|
|
@ -5259,11 +5259,6 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: Fix me! I should be different in tests vs. user code!
|
||||
fn expect_failed() {
|
||||
panic!("An expectation failed!");
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn run_low_level<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
|
@ -5274,7 +5269,6 @@ fn run_low_level<'a, 'ctx, 'env>(
|
|||
op: LowLevel,
|
||||
args: &[Symbol],
|
||||
update_mode: UpdateMode,
|
||||
// expect_failed: *const (),
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
use LowLevel::*;
|
||||
|
||||
|
@ -6036,33 +6030,20 @@ fn run_low_level<'a, 'ctx, 'env>(
|
|||
{
|
||||
bd.position_at_end(throw_block);
|
||||
|
||||
match env.ptr_bytes {
|
||||
8 => {
|
||||
let test = env.module.get_function("get_expect_failed").unwrap();
|
||||
let fn_ptr_type = context
|
||||
.void_type()
|
||||
.fn_type(&[], false)
|
||||
.ptr_type(AddressSpace::Generic);
|
||||
let fn_addr = env
|
||||
.ptr_int()
|
||||
.const_int(expect_failed as *const () as u64, false);
|
||||
let func: PointerValue<'ctx> = bd.build_int_to_ptr(
|
||||
fn_addr,
|
||||
fn_ptr_type,
|
||||
"cast_expect_failed_addr_to_ptr",
|
||||
);
|
||||
let callable = CallableValue::try_from(func).unwrap();
|
||||
let func = env.module.get_function("roc_builtins.utils.expect_failed").unwrap();
|
||||
let callable = CallableValue::try_from(func).unwrap();
|
||||
let start_line = context.i32_type().const_int(0, false);
|
||||
let end_line = context.i32_type().const_int(0, false);
|
||||
let start_col = context.i16_type().const_int(0, false);
|
||||
let end_col = context.i16_type().const_int(0, false);
|
||||
|
||||
bd.build_call(callable, &[], "call_expect_failed");
|
||||
bd.build_call(
|
||||
callable,
|
||||
&[start_line.into(), end_line.into(), start_col.into(), end_col.into()],
|
||||
"call_expect_failed",
|
||||
);
|
||||
|
||||
bd.build_unconditional_branch(then_block);
|
||||
}
|
||||
4 => {
|
||||
// temporary WASM implementation
|
||||
throw_exception(env, "An expectation failed!");
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
bd.build_unconditional_branch(then_block);
|
||||
}
|
||||
|
||||
bd.position_at_end(then_block);
|
||||
|
|
|
@ -38,6 +38,9 @@ macro_rules! run_jit_function {
|
|||
}};
|
||||
|
||||
($lib: expr, $main_fn_name: expr, $ty:ty, $transform:expr, $errors:expr) => {{
|
||||
run_jit_function!($lib, $main_fn_name, $ty, $transform, $errors, &[])
|
||||
}};
|
||||
($lib: expr, $main_fn_name: expr, $ty:ty, $transform:expr, $errors:expr, $expect_failures:expr) => {{
|
||||
use inkwell::context::Context;
|
||||
use roc_gen_llvm::run_roc::RocCallResult;
|
||||
use std::mem::MaybeUninit;
|
||||
|
@ -48,7 +51,11 @@ macro_rules! run_jit_function {
|
|||
.ok()
|
||||
.ok_or(format!("Unable to JIT compile `{}`", $main_fn_name))
|
||||
.expect("errored");
|
||||
|
||||
let get_expect_failures: libloading::Symbol<unsafe extern "C" fn() -> (usize, usize)> =
|
||||
$lib.get("roc_builtins.utils.get_expect_failures".as_bytes())
|
||||
.ok()
|
||||
.ok_or(format!("Unable to JIT compile `{}`", "roc_builtins.utils.get_expect_failures"))
|
||||
.expect("errored");
|
||||
let mut result = MaybeUninit::uninit();
|
||||
|
||||
main(result.as_mut_ptr());
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#[cfg(feature = "gen-llvm")]
|
||||
use crate::helpers::llvm::assert_evals_to;
|
||||
#[cfg(feature = "gen-llvm")]
|
||||
use crate::helpers::llvm::assert_expect_failed;
|
||||
#[cfg(feature = "gen-llvm")]
|
||||
use crate::helpers::llvm::assert_llvm_evals_to;
|
||||
#[cfg(feature = "gen-llvm")]
|
||||
use crate::helpers::llvm::assert_non_opt_evals_to;
|
||||
|
@ -8,6 +10,8 @@ use crate::helpers::llvm::assert_non_opt_evals_to;
|
|||
#[cfg(feature = "gen-dev")]
|
||||
use crate::helpers::dev::assert_evals_to;
|
||||
// #[cfg(feature = "gen-dev")]
|
||||
// use crate::helpers::dev::assert_expect_failed;
|
||||
// #[cfg(feature = "gen-dev")]
|
||||
// use crate::helpers::dev::assert_evals_to as assert_llvm_evals_to;
|
||||
// #[cfg(feature = "gen-dev")]
|
||||
// use crate::helpers::dev::assert_evals_to as assert_non_opt_evals_to;
|
||||
|
@ -15,6 +19,8 @@ use crate::helpers::dev::assert_evals_to;
|
|||
#[cfg(feature = "gen-wasm")]
|
||||
use crate::helpers::wasm::assert_evals_to;
|
||||
// #[cfg(feature = "gen-wasm")]
|
||||
// use crate::helpers::dev::assert_expect_failed;
|
||||
// #[cfg(feature = "gen-wasm")]
|
||||
// use crate::helpers::wasm::assert_evals_to as assert_llvm_evals_to;
|
||||
// #[cfg(feature = "gen-wasm")]
|
||||
// use crate::helpers::wasm::assert_evals_to as assert_non_opt_evals_to;
|
||||
|
@ -2507,9 +2513,8 @@ fn call_invalid_layout() {
|
|||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[should_panic(expected = "An expectation failed!")]
|
||||
fn expect_fail() {
|
||||
assert_evals_to!(
|
||||
assert_expect_failed!(
|
||||
indoc!(
|
||||
r#"
|
||||
expect 1 == 2
|
||||
|
|
|
@ -255,5 +255,27 @@ macro_rules! assert_evals_to {
|
|||
};
|
||||
}
|
||||
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! assert_expect_failed {
|
||||
($src:expr, $expected:expr, $ty:ty, $failures:expr) => {{
|
||||
use bumpalo::Bump;
|
||||
use roc_gen_dev::run_jit_function_raw;
|
||||
let stdlib = roc_builtins::std::standard_stdlib();
|
||||
|
||||
let arena = Bump::new();
|
||||
let (main_fn_name, errors, lib) =
|
||||
$crate::helpers::dev::helper(&arena, $src, stdlib, true, true);
|
||||
|
||||
let transform = |success| {
|
||||
let expected = $expected;
|
||||
assert_eq!(&success, &expected);
|
||||
};
|
||||
run_jit_function_raw!(lib, main_fn_name, $ty, transform, errors);
|
||||
todo!("Actually look up the failures and check them")
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#[allow(unused_imports)]
|
||||
pub(crate) use assert_evals_to;
|
||||
pub(crate) use assert_expect_failed;
|
||||
|
|
|
@ -599,6 +599,52 @@ macro_rules! assert_evals_to {
|
|||
};
|
||||
}
|
||||
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! assert_expect_failed {
|
||||
($src:expr, $expected:expr, $ty:ty) => {
|
||||
use bumpalo::Bump;
|
||||
use inkwell::context::Context;
|
||||
use roc_gen_llvm::run_jit_function;
|
||||
|
||||
let arena = Bump::new();
|
||||
let context = Context::create();
|
||||
|
||||
// NOTE the stdlib must be in the arena; just taking a reference will segfault
|
||||
let stdlib = arena.alloc(roc_builtins::std::standard_stdlib());
|
||||
|
||||
let is_gen_test = true;
|
||||
let (main_fn_name, errors, lib) = $crate::helpers::llvm::helper(
|
||||
&arena,
|
||||
$src,
|
||||
stdlib,
|
||||
is_gen_test,
|
||||
false,
|
||||
&context,
|
||||
);
|
||||
|
||||
let transform = |success| {
|
||||
let expected = $expected;
|
||||
assert_eq!(&success, &expected, "LLVM test failed");
|
||||
};
|
||||
run_jit_function!(lib, main_fn_name, $ty, transform, errors)
|
||||
};
|
||||
|
||||
($src:expr, $expected:expr, $ty:ty) => {
|
||||
$crate::helpers::llvm::assert_llvm_evals_to!(
|
||||
$src,
|
||||
$expected,
|
||||
$ty,
|
||||
$crate::helpers::llvm::identity,
|
||||
false
|
||||
);
|
||||
};
|
||||
|
||||
($src:expr, $expected:expr, $ty:ty, $transform:expr) => {
|
||||
$crate::helpers::llvm::assert_llvm_evals_to!($src, $expected, $ty, $transform, false);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn identity<T>(value: T) -> T {
|
||||
value
|
||||
|
@ -633,3 +679,6 @@ pub(crate) use assert_llvm_evals_to;
|
|||
pub(crate) use assert_non_opt_evals_to;
|
||||
#[allow(unused_imports)]
|
||||
pub(crate) use assert_wasm_evals_to;
|
||||
#[allow(unused_imports)]
|
||||
pub(crate) use assert_expect_failed;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue