| #[macro_use] |
| extern crate log; |
| extern crate env_logger; |
| |
| use std::env; |
| use std::process; |
| use std::str; |
| use std::thread; |
| |
| struct DropMe; |
| |
| impl Drop for DropMe { |
| fn drop(&mut self) { |
| debug!("Dropping now"); |
| } |
| } |
| |
| fn run() { |
| // Use multiple thread local values to increase the chance that our TLS |
| // value will get destroyed after the FORMATTER key in the library |
| thread_local! { |
| static DROP_ME_0: DropMe = DropMe; |
| static DROP_ME_1: DropMe = DropMe; |
| static DROP_ME_2: DropMe = DropMe; |
| static DROP_ME_3: DropMe = DropMe; |
| static DROP_ME_4: DropMe = DropMe; |
| static DROP_ME_5: DropMe = DropMe; |
| static DROP_ME_6: DropMe = DropMe; |
| static DROP_ME_7: DropMe = DropMe; |
| static DROP_ME_8: DropMe = DropMe; |
| static DROP_ME_9: DropMe = DropMe; |
| } |
| DROP_ME_0.with(|_| {}); |
| DROP_ME_1.with(|_| {}); |
| DROP_ME_2.with(|_| {}); |
| DROP_ME_3.with(|_| {}); |
| DROP_ME_4.with(|_| {}); |
| DROP_ME_5.with(|_| {}); |
| DROP_ME_6.with(|_| {}); |
| DROP_ME_7.with(|_| {}); |
| DROP_ME_8.with(|_| {}); |
| DROP_ME_9.with(|_| {}); |
| } |
| |
| fn main() { |
| env_logger::init(); |
| if env::var("YOU_ARE_TESTING_NOW").is_ok() { |
| // Run on a separate thread because TLS values on the main thread |
| // won't have their destructors run if pthread is used. |
| // https://doc.rust-lang.org/std/thread/struct.LocalKey.html#platform-specific-behavior |
| thread::spawn(run).join().unwrap(); |
| } else { |
| let exe = env::current_exe().unwrap(); |
| let out = process::Command::new(exe) |
| .env("YOU_ARE_TESTING_NOW", "1") |
| .env("RUST_LOG", "debug") |
| .output() |
| .unwrap_or_else(|e| panic!("Unable to start child process: {}", e)); |
| if !out.status.success() { |
| println!("test failed: {}", out.status); |
| println!("--- stdout\n{}", str::from_utf8(&out.stdout).unwrap()); |
| println!("--- stderr\n{}", str::from_utf8(&out.stderr).unwrap()); |
| process::exit(1); |
| } |
| } |
| } |