diff --git a/.github/workflows/libloading.yml b/.github/workflows/libloading.yml index d315445..7ee08b1 100644 --- a/.github/workflows/libloading.yml +++ b/.github/workflows/libloading.yml @@ -26,6 +26,9 @@ jobs: profile: minimal components: clippy default: true + - name: Set LIBLOADING_TEST_NIGHTLY + run: echo "::set-env name=LIBLOADING_TEST_NIGHTLY::1" + if: ${{ matrix.rust_toolchain == 'nightly' }} - name: Update uses: actions-rs/cargo@v1 with: @@ -70,6 +73,9 @@ jobs: - i686-pc-windows-gnu steps: - uses: actions/checkout@v2 + - name: Set LIBLOADING_TEST_NIGHTLY + run: echo "::set-env name=LIBLOADING_TEST_NIGHTLY::1" + if: ${{ matrix.rust_toolchain == 'nightly' }} - name: Add MSYS2 to the PATH run: echo "::add-path::c:/msys64/bin" - name: Add 32-bit mingw-w64 to the PATH diff --git a/build.rs b/build.rs index fdc446d..6bc147c 100644 --- a/build.rs +++ b/build.rs @@ -61,4 +61,11 @@ fn main() { ::std::process::exit(0xfd); } } + + // For tests + println!( + "cargo:rustc-env=LIBLOADING_TEST_TARGET={}", + std::env::var("TARGET").expect("$TARGET is not set") + ); + println!("cargo:rerun-if-env-changed=LIBLOADING_TEST_NIGHTLY"); } diff --git a/src/error.rs b/src/error.rs index 1114510..6ba5367 100644 --- a/src/error.rs +++ b/src/error.rs @@ -128,24 +128,3 @@ impl std::fmt::Display for Error { } } } - -#[cfg(test)] -mod tests { - #[test] - fn error_send() { - fn assert_send() {} - assert_send::(); - } - - #[test] - fn error_sync() { - fn assert_sync() {} - assert_sync::(); - } - - #[test] - fn error_display() { - fn assert_display() {} - assert_display::(); - } -} diff --git a/src/os/unix/mod.rs b/src/os/unix/mod.rs index b460c11..6167763 100644 --- a/src/os/unix/mod.rs +++ b/src/os/unix/mod.rs @@ -406,11 +406,3 @@ struct DlInfo { dli_sname: *const raw::c_char, dli_saddr: *mut raw::c_void } - -#[cfg(test)] -mod tests { - #[test] - fn this() { - super::Library::this(); - } -} diff --git a/src/os/windows/mod.rs b/src/os/windows/mod.rs index d6bce11..17f0ee4 100644 --- a/src/os/windows/mod.rs +++ b/src/os/windows/mod.rs @@ -348,50 +348,3 @@ where F: FnOnce() -> Option { } }) } - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn works_getlasterror() { - let lib = Library::new("kernel32.dll").unwrap(); - let gle: Symbol DWORD> = unsafe { - lib.get(b"GetLastError").unwrap() - }; - unsafe { - errhandlingapi::SetLastError(42); - assert_eq!(errhandlingapi::GetLastError(), gle()) - } - } - - #[test] - fn works_getlasterror0() { - let lib = Library::new("kernel32.dll").unwrap(); - let gle: Symbol DWORD> = unsafe { - lib.get(b"GetLastError\0").unwrap() - }; - unsafe { - errhandlingapi::SetLastError(42); - assert_eq!(errhandlingapi::GetLastError(), gle()) - } - } - - #[test] - fn library_this_get() { - use std::sync::atomic::{AtomicBool, Ordering}; - static VARIABLE: AtomicBool = AtomicBool::new(); - - #[no_mangle] - extern "C" fn library_this_get_test_fn() { - VARIABLE.store(true, Ordering::SeqCst); - } - let lib = Library::this().expect("this library"); - let test_fn: Symbol = unsafe { - lib.get(b"library_this_get_test_fn\0").expect("get symbol"); - }; - assert_eq!(VARIABLE.load(Ordering::SeqCst), false); - test_fn(); - assert_eq!(VARIABLE.load(Ordering::SeqCst), true); - } -} diff --git a/src/test_helpers.rs b/src/test_helpers.rs index 32f7023..76c6ce0 100644 --- a/src/test_helpers.rs +++ b/src/test_helpers.rs @@ -1,7 +1,7 @@ //! This is a separate file containing helpers for tests of this library. It is built into a //! dynamic library by the build.rs script. -#![crate_type="dylib"] // FIXME: should become a cdylib in due time -#![cfg_attr(test_nightly, feature(thread_local))] +#![crate_type="cdylib"] +#![cfg_attr(thread_local, feature(thread_local))] #[no_mangle] pub static mut TEST_STATIC_U32: u32 = 0; @@ -9,7 +9,7 @@ pub static mut TEST_STATIC_U32: u32 = 0; #[no_mangle] pub static mut TEST_STATIC_PTR: *mut () = 0 as *mut _; -#[cfg(test_nightly)] +#[cfg(thread_local)] #[thread_local] #[no_mangle] pub static mut TEST_THREAD_LOCAL: u32 = 0; @@ -42,7 +42,7 @@ pub unsafe extern "C" fn test_check_static_ptr() -> bool { TEST_STATIC_PTR == (&mut TEST_STATIC_PTR as *mut *mut _ as *mut _) } -#[cfg(test_nightly)] +#[cfg(thread_local)] #[no_mangle] pub unsafe extern "C" fn test_get_thread_local() -> u32 { TEST_THREAD_LOCAL diff --git a/tests/functions.rs b/tests/functions.rs index dece58c..a1190e7 100644 --- a/tests/functions.rs +++ b/tests/functions.rs @@ -1,19 +1,28 @@ +#[cfg(windows)] +extern crate winapi; + extern crate libloading; use libloading::{Symbol, Library}; -const LIBPATH: &'static str = concat!(env!("OUT_DIR"), "/libtest_helpers.dll"); +const LIBPATH: &'static str = concat!(env!("OUT_DIR"), "/libtest_helpers.module"); fn make_helpers() { static ONCE: ::std::sync::Once = ::std::sync::Once::new(); ONCE.call_once(|| { - let mut outpath = String::from(if let Some(od) = option_env!("OUT_DIR") { od } else { return }); let rustc = option_env!("RUSTC").unwrap_or_else(|| { "rustc".into() }); - outpath.push_str(&"/libtest_helpers.dll"); // extension for windows required, POSIX does not care. - let _ = ::std::process::Command::new(rustc) + let mut cmd = ::std::process::Command::new(rustc); + cmd .arg("src/test_helpers.rs") .arg("-o") - .arg(outpath) - .arg("-O") + .arg(LIBPATH) + .arg("--target") + .arg(env!("LIBLOADING_TEST_TARGET")) + .arg("-O"); + if std::env::var_os("LIBLOADING_TEST_NIGHTLY").is_some() { + cmd.arg("--cfg").arg("thread_local"); + } + + cmd .output() .expect("could not compile the test helpers!"); }); @@ -137,19 +146,91 @@ fn test_static_ptr() { } #[cfg(any(windows, target_os="linux"))] -#[cfg(test_nightly)] #[test] fn test_tls_static() { make_helpers(); let lib = Library::new(LIBPATH).unwrap(); - unsafe { - let var: Symbol<*mut u32> = lib.get(b"TEST_THREAD_LOCAL\0").unwrap(); - **var = 84; - let help: Symbol u32> = lib.get(b"test_get_thread_local\0").unwrap(); - assert_eq!(84, help()); + if std::env::var_os("LIBLOADING_TEST_NIGHTLY").is_some() { + unsafe { + let var: Symbol<*mut u32> = lib.get(b"TEST_THREAD_LOCAL\0").unwrap(); + **var = 84; + let help: Symbol u32> = lib.get(b"test_get_thread_local\0").unwrap(); + assert_eq!(84, help()); + } + ::std::thread::spawn(move || unsafe { + let help: Symbol u32> = lib.get(b"test_get_thread_local\0").unwrap(); + assert_eq!(0, help()); + }).join().unwrap(); + } else { + unsafe { + assert!(lib.get::>(b"TEST_THREAD_LOCAL\0").is_err()); + } + } +} + +#[cfg(unix)] +#[test] +fn library_this_get() { + use libloading::os::unix::Library; + make_helpers(); + let _lib = Library::new(LIBPATH).unwrap(); + let this = Library::this(); + // SAFE: functions are never called + unsafe { + // Library we loaded in `_lib` (should be RTLD_LOCAL). + // FIXME: inconsistent behaviour between macos and other posix systems + // assert!(this.get::(b"test_identity_u32").is_err()); + // Something obscure from libc... + assert!(this.get::(b"freopen").is_ok()); + } +} + +#[cfg(windows)] +#[test] +fn library_this() { + use libloading::os::windows::Library; + make_helpers(); + let _lib = Library::new(LIBPATH).unwrap(); + let this = Library::this().expect("this library"); + // SAFE: functions are never called + unsafe { + // Library we loaded in `_lib`. + assert!(this.get::(b"test_identity_u32").is_err()); + // Something "obscure" from kernel32... + assert!(this.get::(b"GetLastError").is_err()); + } +} + +#[cfg(windows)] +#[test] +fn works_getlasterror() { + use winapi::um::errhandlingapi; + use winapi::shared::minwindef::DWORD; + use libloading::os::windows::{Library, Symbol}; + + let lib = Library::new("kernel32.dll").unwrap(); + let gle: Symbol DWORD> = unsafe { + lib.get(b"GetLastError").unwrap() + }; + unsafe { + errhandlingapi::SetLastError(42); + assert_eq!(errhandlingapi::GetLastError(), gle()) + } +} + +#[cfg(windows)] +#[test] +fn works_getlasterror0() { + use winapi::um::errhandlingapi; + use winapi::shared::minwindef::DWORD; + use libloading::os::windows::{Library, Symbol}; + + let lib = Library::new("kernel32.dll").unwrap(); + let gle: Symbol DWORD> = unsafe { + lib.get(b"GetLastError\0").unwrap() + }; + unsafe { + errhandlingapi::SetLastError(42); + assert_eq!(errhandlingapi::GetLastError(), gle()) } - ::std::thread::spawn(move || unsafe { - let help: Symbol u32> = lib.get(b"test_get_thread_local\0").unwrap(); - assert_eq!(0, help()); - }).join().unwrap(); } diff --git a/tests/markers.rs b/tests/markers.rs index 01da108..330c034 100644 --- a/tests/markers.rs +++ b/tests/markers.rs @@ -4,6 +4,23 @@ extern crate libloading; fn assert_send() {} #[cfg(test)] fn assert_sync() {} +#[cfg(test)] +fn assert_display() {} + +#[test] +fn check_error_send() { + assert_send::(); +} + +#[test] +fn check_error_sync() { + assert_sync::(); +} + +#[test] +fn check_error_display() { + assert_display::(); +} #[test] fn check_library_send() {