1#![cfg(feature = "test-support")]
2use std::env;
3use std::process::Command;
4use std::sync::atomic::{AtomicBool, AtomicPtr, Ordering};
5
6use crate::core::mark_initialized;
7
8static TEST_MODE: AtomicBool = AtomicBool::new(false);
9static TEST_MODULE: AtomicPtr<String> = AtomicPtr::new(std::ptr::null_mut());
10
11pub use small_ctor::ctor;
13
14#[macro_export]
26macro_rules! enable_test_support {
27 () => {
28 #[$crate::testsupport::ctor]
29 unsafe fn __procspawn_test_support_init() {
30 let module_path = std::module_path!().splitn(2, "::").nth(1);
32 $crate::testsupport::enable(module_path);
33 }
34
35 #[test]
36 fn procspawn_test_helper() {
37 $crate::init();
38 }
39 };
40}
41
42pub fn enable(module: Option<&str>) {
43 if TEST_MODE.swap(true, Ordering::SeqCst) {
44 panic!("procspawn testmode can only be enabled once");
45 }
46
47 if let Some(module) = module {
48 let ptr = Box::into_raw(Box::new(module.to_string()));
49 TEST_MODULE.store(ptr, Ordering::SeqCst);
50 }
51
52 mark_initialized();
53}
54
55pub struct TestMode {
56 pub can_pass_args: bool,
57 pub should_silence_stdout: bool,
58}
59
60fn test_helper_path() -> String {
61 match unsafe { TEST_MODULE.load(Ordering::SeqCst).as_ref() } {
62 Some(module) => format!("{}::procspawn_test_helper", module),
63 None => "procspawn_test_helper".to_string(),
64 }
65}
66
67pub fn update_command_for_tests(cmd: &mut Command) -> Option<TestMode> {
68 if TEST_MODE.load(Ordering::SeqCst) {
69 cmd.arg(test_helper_path());
70 cmd.arg("--exact");
71 cmd.arg("--test-threads=1");
72 cmd.arg("-q");
73 Some(TestMode {
74 can_pass_args: false,
75 should_silence_stdout: !env::args().any(|x| x == "--show-output" || x == "--nocapture"),
76 })
77 } else {
78 None
79 }
80}