diff options
Diffstat (limited to 'third_party/rust/libloading/tests')
-rw-r--r-- | third_party/rust/libloading/tests/constants.rs | 13 | ||||
-rw-r--r-- | third_party/rust/libloading/tests/functions.rs | 285 | ||||
-rw-r--r-- | third_party/rust/libloading/tests/library_filename.rs | 17 | ||||
-rw-r--r-- | third_party/rust/libloading/tests/markers.rs | 96 | ||||
-rw-r--r-- | third_party/rust/libloading/tests/nagisa32.dll | bin | 0 -> 3072 bytes | |||
-rw-r--r-- | third_party/rust/libloading/tests/nagisa64.dll | bin | 0 -> 2560 bytes | |||
-rw-r--r-- | third_party/rust/libloading/tests/windows.rs | 64 |
7 files changed, 475 insertions, 0 deletions
diff --git a/third_party/rust/libloading/tests/constants.rs b/third_party/rust/libloading/tests/constants.rs new file mode 100644 index 0000000000..6ae5a8460a --- /dev/null +++ b/third_party/rust/libloading/tests/constants.rs @@ -0,0 +1,13 @@ +extern crate libc; +extern crate libloading; +extern crate static_assertions; + +#[cfg(all(test, unix))] +mod unix { + use super::static_assertions::const_assert_eq; + + const_assert_eq!(libloading::os::unix::RTLD_LOCAL, libc::RTLD_LOCAL); + const_assert_eq!(libloading::os::unix::RTLD_GLOBAL, libc::RTLD_GLOBAL); + const_assert_eq!(libloading::os::unix::RTLD_NOW, libc::RTLD_NOW); + const_assert_eq!(libloading::os::unix::RTLD_LAZY, libc::RTLD_LAZY); +} diff --git a/third_party/rust/libloading/tests/functions.rs b/third_party/rust/libloading/tests/functions.rs new file mode 100644 index 0000000000..c8d1952b3c --- /dev/null +++ b/third_party/rust/libloading/tests/functions.rs @@ -0,0 +1,285 @@ +#[cfg(windows)] +extern crate winapi; + +extern crate libloading; +use libloading::{Library, Symbol}; + +const TARGET_DIR: Option<&'static str> = option_env!("CARGO_TARGET_DIR"); +const TARGET_TMPDIR: Option<&'static str> = option_env!("CARGO_TARGET_TMPDIR"); + +fn lib_path() -> std::path::PathBuf { + [ + TARGET_TMPDIR.unwrap_or(TARGET_DIR.unwrap_or("target")), + "libtest_helpers.module", + ] + .iter() + .collect() +} + +fn make_helpers() { + static ONCE: ::std::sync::Once = ::std::sync::Once::new(); + ONCE.call_once(|| { + let rustc = std::env::var_os("RUSTC").unwrap_or_else(|| "rustc".into()); + let mut cmd = ::std::process::Command::new(rustc); + cmd.arg("src/test_helpers.rs").arg("-o").arg(lib_path()); + if let Some(target) = std::env::var_os("TARGET") { + cmd.arg("--target").arg(target); + } else { + eprintln!("WARNING: $TARGET NOT SPECIFIED! BUILDING HELPER MODULE FOR NATIVE TARGET."); + } + assert!(cmd + .status() + .expect("could not compile the test helpers!") + .success()); + }); +} + +#[test] +fn test_id_u32() { + make_helpers(); + unsafe { + let lib = Library::new(lib_path()).unwrap(); + let f: Symbol<unsafe extern "C" fn(u32) -> u32> = lib.get(b"test_identity_u32\0").unwrap(); + assert_eq!(42, f(42)); + } +} + +#[repr(C)] +#[derive(Clone, Copy, PartialEq, Debug)] +struct S { + a: u64, + b: u32, + c: u16, + d: u8, +} + +#[test] +fn test_id_struct() { + make_helpers(); + unsafe { + let lib = Library::new(lib_path()).unwrap(); + let f: Symbol<unsafe extern "C" fn(S) -> S> = lib.get(b"test_identity_struct\0").unwrap(); + assert_eq!( + S { + a: 1, + b: 2, + c: 3, + d: 4 + }, + f(S { + a: 1, + b: 2, + c: 3, + d: 4 + }) + ); + } +} + +#[test] +fn test_0_no_0() { + make_helpers(); + unsafe { + let lib = Library::new(lib_path()).unwrap(); + let f: Symbol<unsafe extern "C" fn(S) -> S> = lib.get(b"test_identity_struct\0").unwrap(); + let f2: Symbol<unsafe extern "C" fn(S) -> S> = lib.get(b"test_identity_struct").unwrap(); + assert_eq!(*f, *f2); + } +} + +#[test] +fn wrong_name_fails() { + unsafe { + Library::new("target/this_location_is_definitely_non existent:^~") + .err() + .unwrap(); + } +} + +#[test] +fn missing_symbol_fails() { + make_helpers(); + unsafe { + let lib = Library::new(lib_path()).unwrap(); + lib.get::<*mut ()>(b"test_does_not_exist").err().unwrap(); + lib.get::<*mut ()>(b"test_does_not_exist\0").err().unwrap(); + } +} + +#[test] +fn interior_null_fails() { + make_helpers(); + unsafe { + let lib = Library::new(lib_path()).unwrap(); + lib.get::<*mut ()>(b"test_does\0_not_exist").err().unwrap(); + lib.get::<*mut ()>(b"test\0_does_not_exist\0") + .err() + .unwrap(); + } +} + +#[test] +fn test_incompatible_type() { + make_helpers(); + unsafe { + let lib = Library::new(lib_path()).unwrap(); + assert!(match lib.get::<()>(b"test_identity_u32\0") { + Err(libloading::Error::IncompatibleSize) => true, + _ => false, + }) + } +} + +#[test] +fn test_incompatible_type_named_fn() { + make_helpers(); + unsafe fn get<'a, T>(l: &'a Library, _: T) -> Result<Symbol<'a, T>, libloading::Error> { + l.get::<T>(b"test_identity_u32\0") + } + unsafe { + let lib = Library::new(lib_path()).unwrap(); + assert!(match get(&lib, test_incompatible_type_named_fn) { + Err(libloading::Error::IncompatibleSize) => true, + _ => false, + }) + } +} + +#[test] +fn test_static_u32() { + make_helpers(); + unsafe { + let lib = Library::new(lib_path()).unwrap(); + let var: Symbol<*mut u32> = lib.get(b"TEST_STATIC_U32\0").unwrap(); + **var = 42; + let help: Symbol<unsafe extern "C" fn() -> u32> = + lib.get(b"test_get_static_u32\0").unwrap(); + assert_eq!(42, help()); + } +} + +#[test] +fn test_static_ptr() { + make_helpers(); + unsafe { + let lib = Library::new(lib_path()).unwrap(); + let var: Symbol<*mut *mut ()> = lib.get(b"TEST_STATIC_PTR\0").unwrap(); + **var = *var as *mut _; + let works: Symbol<unsafe extern "C" fn() -> bool> = + lib.get(b"test_check_static_ptr\0").unwrap(); + assert!(works()); + } +} + +#[test] +// Something about i686-pc-windows-gnu, makes dll initialisation code call abort when it is loaded +// and unloaded many times. So far it seems like an issue with mingw, not libloading, so ignoring +// the target. Especially since it is very unlikely to be fixed given the state of support its +// support. +#[cfg(not(all(target_arch = "x86", target_os = "windows", target_env = "gnu")))] +fn manual_close_many_times() { + make_helpers(); + let join_handles: Vec<_> = (0..16) + .map(|_| { + std::thread::spawn(|| unsafe { + for _ in 0..10000 { + let lib = Library::new(lib_path()).expect("open library"); + let _: Symbol<unsafe extern "C" fn(u32) -> u32> = + lib.get(b"test_identity_u32").expect("get fn"); + lib.close().expect("close is successful"); + } + }) + }) + .collect(); + for handle in join_handles { + handle.join().expect("thread should succeed"); + } +} + +#[cfg(unix)] +#[test] +fn library_this_get() { + use libloading::os::unix::Library; + make_helpers(); + // SAFE: functions are never called + unsafe { + let _lib = Library::new(lib_path()).unwrap(); + let this = Library::this(); + // Library we loaded in `_lib` (should be RTLD_LOCAL). + assert!(this + .get::<unsafe extern "C" fn()>(b"test_identity_u32") + .is_err()); + // Something obscure from libc... + assert!(this.get::<unsafe extern "C" fn()>(b"freopen").is_ok()); + } +} + +#[cfg(windows)] +#[test] +fn library_this() { + use libloading::os::windows::Library; + make_helpers(); + unsafe { + // SAFE: well-known library without initialisers is loaded. + let _lib = Library::new(lib_path()).unwrap(); + let this = Library::this().expect("this library"); + // SAFE: functions are never called. + // Library we loaded in `_lib`. + assert!(this + .get::<unsafe extern "C" fn()>(b"test_identity_u32") + .is_err()); + // Something "obscure" from kernel32... + assert!(this.get::<unsafe extern "C" fn()>(b"GetLastError").is_err()); + } +} + +#[cfg(windows)] +#[test] +fn works_getlasterror() { + use libloading::os::windows::{Library, Symbol}; + use winapi::shared::minwindef::DWORD; + use winapi::um::errhandlingapi; + + unsafe { + let lib = Library::new("kernel32.dll").unwrap(); + let gle: Symbol<unsafe extern "system" fn() -> DWORD> = lib.get(b"GetLastError").unwrap(); + errhandlingapi::SetLastError(42); + assert_eq!(errhandlingapi::GetLastError(), gle()) + } +} + +#[cfg(windows)] +#[test] +fn works_getlasterror0() { + use libloading::os::windows::{Library, Symbol}; + use winapi::shared::minwindef::DWORD; + use winapi::um::errhandlingapi; + + unsafe { + let lib = Library::new("kernel32.dll").unwrap(); + let gle: Symbol<unsafe extern "system" fn() -> DWORD> = lib.get(b"GetLastError\0").unwrap(); + errhandlingapi::SetLastError(42); + assert_eq!(errhandlingapi::GetLastError(), gle()) + } +} + +#[cfg(windows)] +#[test] +fn library_open_already_loaded() { + use libloading::os::windows::Library; + + // Present on Windows systems and NOT used by any other tests to prevent races. + const LIBPATH: &str = "Msftedit.dll"; + + // Not loaded yet. + assert!(match Library::open_already_loaded(LIBPATH) { + Err(libloading::Error::GetModuleHandleExW { .. }) => true, + _ => false, + }); + + unsafe { + let _lib = Library::new(LIBPATH).unwrap(); + // Loaded now. + assert!(Library::open_already_loaded(LIBPATH).is_ok()); + } +} diff --git a/third_party/rust/libloading/tests/library_filename.rs b/third_party/rust/libloading/tests/library_filename.rs new file mode 100644 index 0000000000..efe51b8656 --- /dev/null +++ b/third_party/rust/libloading/tests/library_filename.rs @@ -0,0 +1,17 @@ +extern crate libloading; +use libloading::library_filename; +use std::path::Path; + +#[cfg(target_os = "windows")] +const EXPECTED: &str = "audioengine.dll"; +#[cfg(target_os = "linux")] +const EXPECTED: &str = "libaudioengine.so"; +#[cfg(target_os = "macos")] +const EXPECTED: &str = "libaudioengine.dylib"; + +#[test] +fn test_library_filename() { + let name = "audioengine"; + let resolved = library_filename(name); + assert!(Path::new(&resolved).ends_with(EXPECTED)); +} diff --git a/third_party/rust/libloading/tests/markers.rs b/third_party/rust/libloading/tests/markers.rs new file mode 100644 index 0000000000..330c034ad5 --- /dev/null +++ b/third_party/rust/libloading/tests/markers.rs @@ -0,0 +1,96 @@ +extern crate libloading; + +#[cfg(test)] +fn assert_send<T: Send>() {} +#[cfg(test)] +fn assert_sync<T: Sync>() {} +#[cfg(test)] +fn assert_display<T: std::fmt::Display>() {} + +#[test] +fn check_error_send() { + assert_send::<libloading::Error>(); +} + +#[test] +fn check_error_sync() { + assert_sync::<libloading::Error>(); +} + +#[test] +fn check_error_display() { + assert_display::<libloading::Error>(); +} + +#[test] +fn check_library_send() { + assert_send::<libloading::Library>(); +} + +#[cfg(unix)] +#[test] +fn check_unix_library_send() { + assert_send::<libloading::os::unix::Library>(); +} + +#[cfg(windows)] +#[test] +fn check_windows_library_send() { + assert_send::<libloading::os::windows::Library>(); +} + +#[test] +fn check_library_sync() { + assert_sync::<libloading::Library>(); +} + +#[cfg(unix)] +#[test] +fn check_unix_library_sync() { + assert_sync::<libloading::os::unix::Library>(); +} + +#[cfg(windows)] +#[test] +fn check_windows_library_sync() { + assert_sync::<libloading::os::windows::Library>(); +} + +#[test] +fn check_symbol_send() { + assert_send::<libloading::Symbol<fn() -> ()>>(); + // assert_not_send::<libloading::Symbol<*const ()>>(); +} + +#[cfg(unix)] +#[test] +fn check_unix_symbol_send() { + assert_send::<libloading::os::unix::Symbol<fn() -> ()>>(); + // assert_not_send::<libloading::os::unix::Symbol<*const ()>>(); +} + +#[cfg(windows)] +#[test] +fn check_windows_symbol_send() { + assert_send::<libloading::os::windows::Symbol<fn() -> ()>>(); +} + +#[test] +fn check_symbol_sync() { + assert_sync::<libloading::Symbol<fn() -> ()>>(); + // assert_not_sync::<libloading::Symbol<*const ()>>(); +} + +#[cfg(unix)] +#[test] +fn check_unix_symbol_sync() { + assert_sync::<libloading::os::unix::Symbol<fn() -> ()>>(); + // assert_not_sync::<libloading::os::unix::Symbol<*const ()>>(); +} + +#[cfg(windows)] +#[test] +fn check_windows_symbol_sync() { + assert_sync::<libloading::os::windows::Symbol<fn() -> ()>>(); + // assert_not_sync::<libloading::os::windows::Symbol<*const ()>>(); +} diff --git a/third_party/rust/libloading/tests/nagisa32.dll b/third_party/rust/libloading/tests/nagisa32.dll Binary files differnew file mode 100644 index 0000000000..0a6218ade9 --- /dev/null +++ b/third_party/rust/libloading/tests/nagisa32.dll diff --git a/third_party/rust/libloading/tests/nagisa64.dll b/third_party/rust/libloading/tests/nagisa64.dll Binary files differnew file mode 100644 index 0000000000..bacaa4b969 --- /dev/null +++ b/third_party/rust/libloading/tests/nagisa64.dll diff --git a/third_party/rust/libloading/tests/windows.rs b/third_party/rust/libloading/tests/windows.rs new file mode 100644 index 0000000000..b4aad4a698 --- /dev/null +++ b/third_party/rust/libloading/tests/windows.rs @@ -0,0 +1,64 @@ +#![cfg(windows)] +extern crate libloading; +use libloading::os::windows::*; +use std::ffi::CStr; + +// The ordinal DLL contains exactly one function (other than DllMain, that is) with ordinal number +// 1. This function has the sugnature `fn() -> *const c_char` and returns a string "bunny\0" (in +// reference to WindowsBunny). +// +// Both x86_64 and x86 versions of the .dll are functionally the same. Ideally we would compile the +// dlls with well known ordinals from our own testing helpers library, but rustc does not allow +// specifying a custom .def file (https://github.com/rust-lang/rust/issues/35089) +// +// The DLLs were kindly compiled by WindowsBunny (aka. @retep998). + +#[cfg(target_arch="x86")] +fn load_ordinal_lib() -> Library { + unsafe { + Library::new("tests/nagisa32.dll").expect("nagisa32.dll") + } +} + +#[cfg(target_arch="x86_64")] +fn load_ordinal_lib() -> Library { + unsafe { + Library::new("tests/nagisa64.dll").expect("nagisa64.dll") + } +} + +#[cfg(any(target_arch="x86", target_arch="x86_64"))] +#[test] +fn test_ordinal() { + let lib = load_ordinal_lib(); + unsafe { + let windows: Symbol<unsafe fn() -> *const i8> = lib.get_ordinal(1).expect("function"); + assert_eq!(CStr::from_ptr(windows()).to_bytes(), b"bunny"); + } +} + +#[cfg(any(target_arch="x86", target_arch="x86_64"))] +#[test] +fn test_ordinal_missing_fails() { + let lib = load_ordinal_lib(); + unsafe { + let r: Result<Symbol<unsafe fn() -> *const i8>, _> = lib.get_ordinal(2); + r.err().unwrap(); + let r: Result<Symbol<unsafe fn() -> *const i8>, _> = lib.get_ordinal(!0); + r.err().unwrap(); + } +} + +#[test] +fn test_new_kernel23() { + unsafe { + Library::new("kernel23").err().unwrap(); + } +} + +#[test] +fn test_new_kernel32_no_ext() { + unsafe { + Library::new("kernel32").unwrap(); + } +} |