mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-04 04:08:19 +00:00
We got a test working for panicking with the appropriate number fo failures. Ultimatly we want:
+ An error maessage that says what the failures were + Not panicking (so these are effectively error productions)
This commit is contained in:
parent
085c02ffee
commit
4f8d0776b3
8 changed files with 103 additions and 24 deletions
|
@ -23,12 +23,13 @@ extern fn roc_memcpy(dst: [*]u8, src: [*]u8, size: usize) callconv(.C) void;
|
|||
|
||||
comptime {
|
||||
const builtin = @import("builtin");
|
||||
// During tetsts, use the testing allocators to satisfy these functions.
|
||||
// During tests, use the testing allocators to satisfy these functions.
|
||||
if (builtin.is_test) {
|
||||
@export(testing_roc_alloc, .{ .name = "roc_alloc", .linkage = .Strong });
|
||||
@export(testing_roc_realloc, .{ .name = "roc_realloc", .linkage = .Strong });
|
||||
@export(testing_roc_dealloc, .{ .name = "roc_dealloc", .linkage = .Strong });
|
||||
@export(testing_roc_panic, .{ .name = "roc_panic", .linkage = .Strong });
|
||||
@export(testing_roc_memcpy, .{ .name = "roc_memcpy", .linkage = .Strong });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,6 +57,14 @@ fn testing_roc_panic(c_ptr: *c_void, tag_id: u32) callconv(.C) void {
|
|||
@panic("Roc panicked");
|
||||
}
|
||||
|
||||
fn testing_roc_memcpy(dest: *c_void, src: *c_void, bytes: usize) callconv(.C) ?*c_void {
|
||||
const zig_dest = @ptrCast([*]u8, dest);
|
||||
const zig_src = @ptrCast([*]u8, src);
|
||||
|
||||
@memcpy(zig_dest, zig_src, bytes);
|
||||
return dest;
|
||||
}
|
||||
|
||||
pub fn alloc(size: usize, alignment: u32) [*]u8 {
|
||||
return @ptrCast([*]u8, @call(.{ .modifier = always_inline }, roc_alloc, .{ size, alignment }));
|
||||
}
|
||||
|
|
|
@ -6030,7 +6030,10 @@ fn run_low_level<'a, 'ctx, 'env>(
|
|||
{
|
||||
bd.position_at_end(throw_block);
|
||||
|
||||
let func = env.module.get_function("roc_builtins.utils.expect_failed").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);
|
||||
|
@ -6039,7 +6042,12 @@ fn run_low_level<'a, 'ctx, 'env>(
|
|||
|
||||
bd.build_call(
|
||||
callable,
|
||||
&[start_line.into(), end_line.into(), start_col.into(), end_col.into()],
|
||||
&[
|
||||
start_line.into(),
|
||||
end_line.into(),
|
||||
start_col.into(),
|
||||
end_col.into(),
|
||||
],
|
||||
"call_expect_failed",
|
||||
);
|
||||
|
||||
|
|
|
@ -42,6 +42,43 @@ pub fn add_default_roc_externs(env: &Env<'_, '_, '_>) {
|
|||
}
|
||||
}
|
||||
|
||||
// roc_memcpy
|
||||
{
|
||||
// The type of this function (but not the implementation) should have
|
||||
// already been defined by the builtins, which rely on it.
|
||||
let fn_val = module.get_function("roc_memcpy").unwrap();
|
||||
let mut params = fn_val.get_param_iter();
|
||||
let dest_arg = params.next().unwrap();
|
||||
let dest_alignment = 1;
|
||||
let src_arg = params.next().unwrap();
|
||||
let src_alignment = 1;
|
||||
let bytes_arg = params.next().unwrap();
|
||||
|
||||
debug_assert!(params.next().is_none());
|
||||
|
||||
// Add a basic block for the entry point
|
||||
let entry = ctx.append_basic_block(fn_val, "entry");
|
||||
|
||||
builder.position_at_end(entry);
|
||||
|
||||
// Call libc memcpy()
|
||||
let _retval = builder
|
||||
.build_memcpy(
|
||||
dest_arg.into_pointer_value(),
|
||||
dest_alignment,
|
||||
src_arg.into_pointer_value(),
|
||||
src_alignment,
|
||||
bytes_arg.into_int_value(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
builder.build_return(None);
|
||||
|
||||
if cfg!(debug_assertions) {
|
||||
crate::llvm::build::verify_fn(fn_val);
|
||||
}
|
||||
}
|
||||
|
||||
// roc_realloc
|
||||
{
|
||||
let libc_realloc_val = {
|
||||
|
|
|
@ -45,22 +45,45 @@ macro_rules! run_jit_function {
|
|||
use roc_gen_llvm::run_roc::RocCallResult;
|
||||
use std::mem::MaybeUninit;
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
struct Failure {
|
||||
start_line: u32,
|
||||
end_line: u32,
|
||||
start_col: u16,
|
||||
end_col: u16,
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let main: libloading::Symbol<unsafe extern "C" fn(*mut RocCallResult<$ty>) -> ()> =
|
||||
$lib.get($main_fn_name.as_bytes())
|
||||
.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())
|
||||
let get_expect_failures: libloading::Symbol<
|
||||
unsafe extern "C" fn() -> (*const Failure, 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"))
|
||||
.ok_or(format!(
|
||||
"Unable to JIT compile `{}`",
|
||||
"roc_builtins.utils.get_expect_failures"
|
||||
))
|
||||
.expect("errored");
|
||||
let mut result = MaybeUninit::uninit();
|
||||
let mut main_result = MaybeUninit::uninit();
|
||||
|
||||
main(result.as_mut_ptr());
|
||||
main(main_result.as_mut_ptr());
|
||||
let (failures_ptr, num_failures) = get_expect_failures();
|
||||
let mut failures = std::vec::Vec::new();
|
||||
|
||||
match result.assume_init().into() {
|
||||
for index in 0..num_failures {
|
||||
failures.push(*failures_ptr.add(index));
|
||||
}
|
||||
|
||||
if (num_failures > 0) {
|
||||
panic!("Failed with {} failures. Failures: ", num_failures);
|
||||
}
|
||||
|
||||
match main_result.assume_init().into() {
|
||||
Ok(success) => {
|
||||
// only if there are no exceptions thrown, check for errors
|
||||
assert!($errors.is_empty(), "Encountered errors:\n{}", $errors);
|
||||
|
|
|
@ -2513,6 +2513,7 @@ fn call_invalid_layout() {
|
|||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[should_panic(expected = "Failed with 1 failures. Failures: ")]
|
||||
fn expect_fail() {
|
||||
assert_expect_failed!(
|
||||
indoc!(
|
||||
|
|
|
@ -272,10 +272,9 @@ macro_rules! assert_expect_failed {
|
|||
};
|
||||
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;
|
||||
|
|
|
@ -192,7 +192,11 @@ fn create_llvm_module<'a>(
|
|||
for function in FunctionIterator::from_module(module) {
|
||||
let name = function.get_name().to_str().unwrap();
|
||||
if name.starts_with("roc_builtins") {
|
||||
function.set_linkage(Linkage::Internal);
|
||||
if name.starts_with("roc_builtins.utils") {
|
||||
function.set_linkage(Linkage::External);
|
||||
} else {
|
||||
function.set_linkage(Linkage::Internal);
|
||||
}
|
||||
}
|
||||
|
||||
if name.starts_with("roc_builtins.dict") {
|
||||
|
@ -613,19 +617,14 @@ macro_rules! assert_expect_failed {
|
|||
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 (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)
|
||||
};
|
||||
|
||||
|
@ -644,7 +643,6 @@ macro_rules! assert_expect_failed {
|
|||
};
|
||||
}
|
||||
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn identity<T>(value: T) -> T {
|
||||
value
|
||||
|
@ -674,11 +672,10 @@ macro_rules! assert_non_opt_evals_to {
|
|||
#[allow(unused_imports)]
|
||||
pub(crate) use assert_evals_to;
|
||||
#[allow(unused_imports)]
|
||||
pub(crate) use assert_expect_failed;
|
||||
#[allow(unused_imports)]
|
||||
pub(crate) use assert_llvm_evals_to;
|
||||
#[allow(unused_imports)]
|
||||
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;
|
||||
|
||||
|
|
|
@ -23,6 +23,11 @@ pub unsafe fn roc_alloc(size: usize, _alignment: u32) -> *mut c_void {
|
|||
libc::malloc(size)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe fn roc_memcpy(dest: *mut c_void, src: *const c_void, bytes: usize) -> *mut c_void {
|
||||
libc::memcpy(dest, src, bytes)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe fn roc_realloc(
|
||||
c_ptr: *mut c_void,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue