1 extern crate libloading;
2 use libloading::{Symbol, Library};
3 
4 const LIBPATH: &'static str = concat!(env!("OUT_DIR"), "/libtest_helpers.dll");
5 
make_helpers()6 fn make_helpers() {
7     static ONCE: ::std::sync::Once = ::std::sync::ONCE_INIT;
8     ONCE.call_once(|| {
9         let mut outpath = String::from(if let Some(od) = option_env!("OUT_DIR") { od } else { return });
10         let rustc = option_env!("RUSTC").unwrap_or_else(|| { "rustc".into() });
11         outpath.push_str(&"/libtest_helpers.dll"); // extension for windows required, POSIX does not care.
12         let _ = ::std::process::Command::new(rustc)
13             .arg("src/test_helpers.rs")
14             .arg("-o")
15             .arg(outpath)
16             .arg("-O")
17             .output()
18             .expect("could not compile the test helpers!");
19     });
20 }
21 
22 #[test]
test_id_u32()23 fn test_id_u32() {
24     make_helpers();
25     let lib = Library::new(LIBPATH).unwrap();
26     unsafe {
27         let f: Symbol<unsafe extern fn(u32) -> u32> = lib.get(b"test_identity_u32\0").unwrap();
28         assert_eq!(42, f(42));
29     }
30 }
31 
32 #[repr(C)]
33 #[derive(Clone,Copy,PartialEq,Debug)]
34 struct S {
35     a: u64,
36     b: u32,
37     c: u16,
38     d: u8
39 }
40 
41 #[test]
test_id_struct()42 fn test_id_struct() {
43     make_helpers();
44     let lib = Library::new(LIBPATH).unwrap();
45     unsafe {
46         let f: Symbol<unsafe extern fn(S) -> S> = lib.get(b"test_identity_struct\0").unwrap();
47         assert_eq!(S { a: 1, b: 2, c: 3, d: 4 }, f(S { a: 1, b: 2, c: 3, d: 4 }));
48     }
49 }
50 
51 #[test]
test_0_no_0()52 fn test_0_no_0() {
53     make_helpers();
54     let lib = Library::new(LIBPATH).unwrap();
55     unsafe {
56         let f: Symbol<unsafe extern fn(S) -> S> = lib.get(b"test_identity_struct\0").unwrap();
57         let f2: Symbol<unsafe extern fn(S) -> S> = lib.get(b"test_identity_struct").unwrap();
58         assert_eq!(*f, *f2);
59     }
60 }
61 
62 #[test]
wrong_name_fails()63 fn wrong_name_fails() {
64     Library::new(concat!(env!("OUT_DIR"), "/libtest_help")).err().unwrap();
65 }
66 
67 #[test]
missing_symbol_fails()68 fn missing_symbol_fails() {
69     make_helpers();
70     let lib = Library::new(LIBPATH).unwrap();
71     unsafe {
72         lib.get::<*mut ()>(b"test_does_not_exist").err().unwrap();
73         lib.get::<*mut ()>(b"test_does_not_exist\0").err().unwrap();
74     }
75 }
76 
77 #[test]
interior_null_fails()78 fn interior_null_fails() {
79     make_helpers();
80     let lib = Library::new(LIBPATH).unwrap();
81     unsafe {
82         lib.get::<*mut ()>(b"test_does\0_not_exist").err().unwrap();
83         lib.get::<*mut ()>(b"test\0_does_not_exist\0").err().unwrap();
84     }
85 }
86 
87 #[test]
88 #[should_panic]
test_incompatible_type()89 fn test_incompatible_type() {
90     make_helpers();
91     let lib = Library::new(LIBPATH).unwrap();
92     unsafe {
93         let _ = lib.get::<()>(b"test_identity_u32\0");
94     }
95 }
96 
97 #[test]
98 #[should_panic]
test_incompatible_type_named_fn()99 fn test_incompatible_type_named_fn() {
100     make_helpers();
101     unsafe fn get<'a, T>(l: &'a Library, _: T) -> libloading::Result<Symbol<'a, T>> {
102         l.get::<T>(b"test_identity_u32\0")
103     }
104     let lib = Library::new(LIBPATH).unwrap();
105     unsafe {
106         let _ = get(&lib, test_incompatible_type_named_fn);
107     }
108 }
109 
110 #[test]
test_static_u32()111 fn test_static_u32() {
112     make_helpers();
113     let lib = Library::new(LIBPATH).unwrap();
114     unsafe {
115         let var: Symbol<*mut u32> = lib.get(b"TEST_STATIC_U32\0").unwrap();
116         **var = 42;
117         let help: Symbol<unsafe extern fn() -> u32> = lib.get(b"test_get_static_u32\0").unwrap();
118         assert_eq!(42, help());
119     }
120 }
121 
122 #[test]
test_static_ptr()123 fn test_static_ptr() {
124     make_helpers();
125     let lib = Library::new(LIBPATH).unwrap();
126     unsafe {
127         let var: Symbol<*mut *mut ()> = lib.get(b"TEST_STATIC_PTR\0").unwrap();
128         **var = *var as *mut _;
129         let works: Symbol<unsafe extern fn() -> bool> =
130             lib.get(b"test_check_static_ptr\0").unwrap();
131         assert!(works());
132     }
133 }
134 
135 #[cfg(any(windows, target_os="linux"))]
136 #[cfg(test_nightly)]
137 #[test]
test_tls_static()138 fn test_tls_static() {
139     make_helpers();
140     let lib = Library::new(LIBPATH).unwrap();
141     unsafe {
142         let var: Symbol<*mut u32> = lib.get(b"TEST_THREAD_LOCAL\0").unwrap();
143         **var = 84;
144         let help: Symbol<unsafe extern fn() -> u32> = lib.get(b"test_get_thread_local\0").unwrap();
145         assert_eq!(84, help());
146     }
147     ::std::thread::spawn(move || unsafe {
148         let help: Symbol<unsafe extern fn() -> u32> = lib.get(b"test_get_thread_local\0").unwrap();
149         assert_eq!(0, help());
150     }).join().unwrap();
151 }
152