]> git.proxmox.com Git - rustc.git/blob - vendor/jobserver/tests/client.rs
New upstream version 1.32.0~beta.2+dfsg1
[rustc.git] / vendor / jobserver / tests / client.rs
1 extern crate futures;
2 extern crate jobserver;
3 extern crate num_cpus;
4 extern crate tempdir;
5 extern crate tokio_core;
6 extern crate tokio_process;
7
8 use std::env;
9 use std::fs::File;
10 use std::io::Write;
11 use std::process::Command;
12 use std::sync::Arc;
13 use std::sync::atomic::{AtomicBool, Ordering};
14 use std::sync::mpsc;
15 use std::thread;
16
17 use futures::future::{self, Future};
18 use futures::stream::{self, Stream};
19 use jobserver::Client;
20 use tempdir::TempDir;
21 use tokio_core::reactor::Core;
22 use tokio_process::CommandExt;
23
24 macro_rules! t {
25 ($e:expr) => (match $e {
26 Ok(e) => e,
27 Err(e) => panic!("{} failed with {}", stringify!($e), e),
28 })
29 }
30
31 struct Test {
32 name: &'static str,
33 f: &'static Fn(),
34 make_args: &'static [&'static str],
35 rule: &'static Fn(&str) -> String,
36 }
37
38 const TESTS: &[Test] = &[
39 Test {
40 name: "no j args",
41 make_args: &[],
42 rule: &|me| format!("{}", me),
43 f: &|| {
44 assert!(unsafe { Client::from_env().is_none() });
45 },
46 },
47 Test {
48 name: "no j args with plus",
49 make_args: &[],
50 rule: &|me| format!("+{}", me),
51 f: &|| {
52 assert!(unsafe { Client::from_env().is_none() });
53 },
54 },
55 Test {
56 name: "j args with plus",
57 make_args: &["-j2"],
58 rule: &|me| format!("+{}", me),
59 f: &|| {
60 assert!(unsafe { Client::from_env().is_some() });
61 },
62 },
63 Test {
64 name: "acquire",
65 make_args: &["-j2"],
66 rule: &|me| format!("+{}", me),
67 f: &|| {
68 let c = unsafe { Client::from_env().unwrap() };
69 drop(c.acquire().unwrap());
70 drop(c.acquire().unwrap());
71 },
72 },
73 Test {
74 name: "acquire3",
75 make_args: &["-j3"],
76 rule: &|me| format!("+{}", me),
77 f: &|| {
78 let c = unsafe { Client::from_env().unwrap() };
79 let a = c.acquire().unwrap();
80 let b = c.acquire().unwrap();
81 drop((a, b));
82 },
83 },
84 Test {
85 name: "acquire blocks",
86 make_args: &["-j2"],
87 rule: &|me| format!("+{}", me),
88 f: &|| {
89 let c = unsafe { Client::from_env().unwrap() };
90 let a = c.acquire().unwrap();
91 let hit = Arc::new(AtomicBool::new(false));
92 let hit2 = hit.clone();
93 let (tx, rx) = mpsc::channel();
94 let t = thread::spawn(move || {
95 tx.send(()).unwrap();
96 let _b = c.acquire().unwrap();
97 hit2.store(true, Ordering::SeqCst);
98 });
99 rx.recv().unwrap();
100 assert!(!hit.load(Ordering::SeqCst));
101 drop(a);
102 t.join().unwrap();
103 assert!(hit.load(Ordering::SeqCst));
104 },
105 },
106 ];
107
108 fn main() {
109 if let Ok(test) = env::var("TEST_TO_RUN") {
110 return (TESTS.iter().find(|t| t.name == test).unwrap().f)()
111 }
112
113 let me = t!(env::current_exe());
114 let me = me.to_str().unwrap();
115 let filter = env::args().skip(1).next();
116
117 let mut core = t!(Core::new());
118 let ref handle = core.handle();
119
120 let futures = TESTS.iter().filter(|test| {
121 match filter {
122 Some(ref s) => test.name.contains(s),
123 None => true,
124 }
125 }).map(|test| {
126 let td = t!(TempDir::new("foo"));
127 let makefile = format!("\
128 all: export TEST_TO_RUN={}
129 all:
130 \t{}
131 ", test.name, (test.rule)(me));
132 t!(t!(File::create(td.path().join("Makefile")))
133 .write_all(makefile.as_bytes()));
134 let prog = env::var("MAKE").unwrap_or("make".to_string());
135 let mut cmd = Command::new(prog);
136 cmd.args(test.make_args);
137 cmd.current_dir(td.path());
138 future::lazy(move || {
139 cmd.output_async(&handle).map(move |e| {
140 drop(td);
141 (test, e)
142 })
143 })
144 }).collect::<Vec<_>>();
145
146 println!("\nrunning {} tests\n", futures.len());
147
148 let stream = stream::iter(futures.into_iter().map(Ok))
149 .buffer_unordered(num_cpus::get());
150
151 let mut failures = Vec::new();
152 t!(core.run(stream.for_each(|(test, output)| {
153 if output.status.success() {
154 println!("test {} ... ok", test.name);
155 } else {
156 println!("test {} ... FAIL", test.name);
157 failures.push((test, output));
158 }
159 Ok(())
160 })));
161
162 if failures.len() == 0 {
163 println!("\ntest result: ok\n");
164 return
165 }
166
167 println!("\n----------- failures");
168
169 for (test, output) in failures {
170 println!("test {}", test.name);
171 let stdout = String::from_utf8_lossy(&output.stdout);
172 let stderr = String::from_utf8_lossy(&output.stderr);
173
174 println!("\texit status: {}", output.status);
175 if !stdout.is_empty() {
176 println!("\tstdout ===");
177 for line in stdout.lines() {
178 println!("\t\t{}", line);
179 }
180 }
181
182 if !stderr.is_empty() {
183 println!("\tstderr ===");
184 for line in stderr.lines() {
185 println!("\t\t{}", line);
186 }
187 }
188 }
189
190 std::process::exit(4);
191 }