1#![feature(test)]
8#![feature(custom_test_frameworks)]
9#![feature(exitcode_exit_method)]
10#![test_runner(run_gdb)]
11
12extern crate test;
13
14mod console;
15mod gdb;
16mod socket;
17
18use std::process::{ExitCode, Termination};
19
20pub use console::ConsoleRunner;
21pub use gdb::GdbRunner;
22pub use socket::SocketRunner;
23use test::{ColorConfig, OutputFormat, TestDescAndFn, TestFn, TestOpts};
24
25pub fn run_gdb(tests: &[&TestDescAndFn]) {
28 run::<GdbRunner>(tests);
29}
30
31pub fn run_console(tests: &[&TestDescAndFn]) {
34 run::<ConsoleRunner>(tests);
35}
36
37pub fn run_socket(tests: &[&TestDescAndFn]) {
40 run::<SocketRunner>(tests);
41}
42
43fn run<Runner: TestRunner>(tests: &[&TestDescAndFn]) {
44 std::env::set_var("RUST_BACKTRACE", "1");
45
46 let mut runner = Runner::new();
47 let ctx = runner.setup();
48
49 let opts = TestOpts {
50 force_run_in_process: true,
51 run_tests: true,
52 color: ColorConfig::AlwaysColor,
55 format: OutputFormat::Pretty,
56 test_threads: Some(1),
57 ..test::test::parse_opts(&[]).unwrap().unwrap()
61 };
62
63 let tests = tests.iter().map(|t| make_owned_test(t)).collect();
64 let result = test::run_tests_console(&opts, tests);
65
66 drop(ctx);
67
68 let reportable_result = match result {
69 Ok(true) => Ok(()),
70 _ => Err(ExitCode::from(101)),
72 };
73
74 let _ = runner.cleanup(reportable_result);
75}
76
77fn make_owned_test(test: &TestDescAndFn) -> TestDescAndFn {
83 let testfn = match test.testfn {
84 TestFn::StaticTestFn(f) => TestFn::StaticTestFn(f),
85 TestFn::StaticBenchFn(f) => TestFn::StaticBenchFn(f),
86 _ => panic!("non-static tests passed to test::test_main_static"),
87 };
88
89 TestDescAndFn {
90 testfn,
91 desc: test.desc.clone(),
92 }
93}
94
95trait TestRunner: Sized {
97 type Context<'this>
102 where
103 Self: 'this;
104
105 fn new() -> Self;
107
108 fn setup(&mut self) -> Self::Context<'_>;
110
111 fn cleanup<T: Termination>(self, test_result: T) -> T {
116 test_result
117 }
118}
119
120mod link_fix {
123 #[no_mangle]
124 extern "C" fn execvp(
125 _argc: *const libc::c_char,
126 _argv: *mut *const libc::c_char,
127 ) -> libc::c_int {
128 -1
129 }
130
131 #[no_mangle]
132 extern "C" fn pipe(_fildes: *mut libc::c_int) -> libc::c_int {
133 -1
134 }
135
136 #[no_mangle]
137 extern "C" fn sigemptyset(_arg1: *mut libc::sigset_t) -> ::libc::c_int {
138 -1
139 }
140}
141
142#[cfg(test)]
143mod tests {
144 #[test]
145 fn it_works() {
146 assert_eq!(2 + 2, 4);
147 }
148
149 #[test]
150 #[should_panic]
151 fn it_fails() {
152 assert_eq!(2 + 2, 5);
153 }
154}