From db3f2717bc4dd00d8eeff1af9feedf830f512164 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Bennet=20Ble=C3=9Fmann?= Date: Tue, 21 Jan 2025 23:36:14 +0100 Subject: [PATCH] add more ffi tests --- tests-pl/ffi_invalid_type.pl | 10 ++++ tests-pl/ffi_return_values.pl | 34 +++++++++++ tests/scryer/ffi.rs | 103 ++++++++++++++++++++++++++++++++++ 3 files changed, 147 insertions(+) create mode 100644 tests-pl/ffi_invalid_type.pl create mode 100644 tests-pl/ffi_return_values.pl diff --git a/tests-pl/ffi_invalid_type.pl b/tests-pl/ffi_invalid_type.pl new file mode 100644 index 00000000..c78668df --- /dev/null +++ b/tests-pl/ffi_invalid_type.pl @@ -0,0 +1,10 @@ +:- use_module(library(os)). +:- use_module(library(ffi)). + +test :- + getenv("ffi_invalid_type_LIB", LIB), + use_foreign_module(LIB, [ + 'ffi_invalid_type'([], c_void) + ]). + +:- initialization(test). diff --git a/tests-pl/ffi_return_values.pl b/tests-pl/ffi_return_values.pl new file mode 100644 index 00000000..3365262c --- /dev/null +++ b/tests-pl/ffi_return_values.pl @@ -0,0 +1,34 @@ +:- use_module(library(os)). +:- use_module(library(ffi)). + +test :- + getenv("ffi_return_values_LIB", LIB), + use_foreign_module(LIB, [ + 'ffi_return_values_true'([], bool), + 'ffi_return_values_false'([], bool), + 'ffi_return_values_i8'([], sint8), + 'ffi_return_values_u8'([], uint8), + 'ffi_return_values_i16'([], sint16), + 'ffi_return_values_u16'([], uint16), + 'ffi_return_values_i32'([], sint32), + 'ffi_return_values_u32'([], uint32), + 'ffi_return_values_i64'([], sint64), + 'ffi_return_values_u64'([], uint64), + 'ffi_return_values_f32'([], f32), + 'ffi_return_values_f64'([], f64) + ]), + ffi:'ffi_return_values_true', + (\+ ffi:'ffi_return_values_false'), + ffi:'ffi_return_values_i8'(I8), + ffi:'ffi_return_values_u8'(U8), + ffi:'ffi_return_values_i16'(I16), + ffi:'ffi_return_values_u16'(U16), + ffi:'ffi_return_values_i32'(I32), + ffi:'ffi_return_values_u32'(U32), + ffi:'ffi_return_values_i64'(I64), + ffi:'ffi_return_values_u64'(U64), + ffi:'ffi_return_values_f32'(F32), + ffi:'ffi_return_values_f64'(F64), + write((i8-I8, u8-U8, i16-I16, u16-U16, i32-I32, u32-U32, i64-I64, u64-U64, f32-F32, f64-F64)). + +:- initialization(test). diff --git a/tests/scryer/ffi.rs b/tests/scryer/ffi.rs index 95c465c0..04bef2cf 100644 --- a/tests/scryer/ffi.rs +++ b/tests/scryer/ffi.rs @@ -88,3 +88,106 @@ fn ffi_f64_minus_zero() { // note: ouput is currently wrong correct would be 1.0,1.0 load_module_test("tests-pl/ffi_f64_minus_zero.pl", "-1.0,1.0"); } + +#[test] +#[cfg_attr(miri, ignore = "ffi")] +fn ffi_return_values() { + let dynlib_path = build_dynamic_library( + "ffi_return_values", + r##" + #[no_mangle] + extern "C" fn ffi_return_values_true() -> bool { + true + } + + #[no_mangle] + extern "C" fn ffi_return_values_false() -> bool { + false + } + + #[no_mangle] + extern "C" fn ffi_return_values_i8() -> i8 { + -42 + } + + #[no_mangle] + extern "C" fn ffi_return_values_u8() -> u8 { + 73 + } + + #[no_mangle] + extern "C" fn ffi_return_values_i16() -> i16 { + -0xBEE + } + + #[no_mangle] + extern "C" fn ffi_return_values_u16() -> u16 { + 0xC0DE + } + + + #[no_mangle] + extern "C" fn ffi_return_values_i32() -> i32 { + -0xBEEFBEE + } + + #[no_mangle] + extern "C" fn ffi_return_values_u32() -> u32 { + 0xC0DEB000 + } + + #[no_mangle] + extern "C" fn ffi_return_values_i64() -> i64 { + -0xBEEFBEE5C0DEB00 + } + + #[no_mangle] + extern "C" fn ffi_return_values_u64() -> u64 { + // 0xFEDCBA9876543210 // too large for i64 + 0xBEEFBEE5C0DEB00 + } + + #[no_mangle] + extern "C" fn ffi_return_values_f32() -> f32 { + std::f32::consts::PI + } + + #[no_mangle] + extern "C" fn ffi_return_values_f64() -> f64 { + std::f64::consts::TAU + } + "##, + ); + + // technically UB as tests are by default multi-threaded, + // but there is currently no other easy way to get the dynamic library file path as an input into a load_module_test test + std::env::set_var("ffi_return_values_LIB", dynlib_path); + + // FIXME u32 and u64 have an incorrect result + load_module_test( + "tests-pl/ffi_return_values.pl", + "i8-214,u8-73,i16-18,u16-222,i32-18,u32-0,i64-0,u64- -4789548415587584,f32-3.1415927410125732,f64-6.283185307179586", + ); +} + +#[test] +#[cfg_attr(miri, ignore = "ffi")] +fn ffi_invalid_type() { + let dynlib_path = build_dynamic_library( + "ffi_invalid_type", + r##" + #[no_mangle] + extern "C" fn ffi_invalid_type() -> () { + } + "##, + ); + + // technically UB as tests are by default multi-threaded, + // but there is currently no other easy way to get the dynamic library file path as an input into a load_module_test test + std::env::set_var("ffi_invalid_type_LIB", dynlib_path); + + load_module_test( + "tests-pl/ffi_invalid_type.pl", + "% Warning: initialization/1 failed for: user:test\n", + ); +} -- 2.54.0