]> git.proxmox.com Git - rustc.git/blame - vendor/cc/tests/support/mod.rs
New upstream version 1.61.0+dfsg1
[rustc.git] / vendor / cc / tests / support / mod.rs
CommitLineData
476ff2be
SL
1#![allow(dead_code)]
2
3use std::env;
60c5eb7d 4use std::ffi::{OsStr, OsString};
476ff2be 5use std::fs::{self, File};
60c5eb7d 6use std::io;
476ff2be 7use std::io::prelude::*;
60c5eb7d 8use std::path::{Path, PathBuf};
476ff2be 9
ea8adc8c 10use cc;
dfeec247 11use tempfile::{Builder, TempDir};
476ff2be
SL
12
13pub struct Test {
14 pub td: TempDir,
15 pub gcc: PathBuf,
16 pub msvc: bool,
17}
18
19pub struct Execution {
20 args: Vec<String>,
21}
22
23impl Test {
24 pub fn new() -> Test {
ba9703b0
XL
25 // This is ugly: `sccache` needs to introspect the compiler it is
26 // executing, as it adjusts its behavior depending on the
27 // language/compiler. This crate's test driver uses mock compilers that
28 // are obviously not supported by sccache, so the tests fail if
29 // RUSTC_WRAPPER is set. rust doesn't build test dependencies with
30 // the `test` feature enabled, so we can't conditionally disable the
31 // usage of `sccache` if running in a test environment, at least not
32 // without setting an environment variable here and testing for it
33 // there. Explicitly deasserting RUSTC_WRAPPER here seems to be the
34 // lesser of the two evils.
35 env::remove_var("RUSTC_WRAPPER");
36
476ff2be
SL
37 let mut gcc = PathBuf::from(env::current_exe().unwrap());
38 gcc.pop();
39 if gcc.ends_with("deps") {
40 gcc.pop();
41 }
dfeec247 42 let td = Builder::new().prefix("gcc-test").tempdir_in(&gcc).unwrap();
476ff2be
SL
43 gcc.push(format!("gcc-shim{}", env::consts::EXE_SUFFIX));
44 Test {
60c5eb7d 45 td: td,
476ff2be
SL
46 gcc: gcc,
47 msvc: false,
48 }
49 }
50
51 pub fn gnu() -> Test {
52 let t = Test::new();
ea8adc8c 53 t.shim("cc").shim("c++").shim("ar");
8bb4bdeb 54 t
476ff2be
SL
55 }
56
57 pub fn msvc() -> Test {
58 let mut t = Test::new();
59 t.shim("cl").shim("lib.exe");
60 t.msvc = true;
8bb4bdeb 61 t
476ff2be
SL
62 }
63
64 pub fn shim(&self, name: &str) -> &Test {
ee023bcb
FG
65 let name = if name.ends_with(env::consts::EXE_SUFFIX) {
66 name.to_string()
67 } else {
68 format!("{}{}", name, env::consts::EXE_SUFFIX)
69 };
70 link_or_copy(&self.gcc, self.td.path().join(name)).unwrap();
476ff2be
SL
71 self
72 }
73
ea8adc8c
XL
74 pub fn gcc(&self) -> cc::Build {
75 let mut cfg = cc::Build::new();
476ff2be
SL
76 let target = if self.msvc {
77 "x86_64-pc-windows-msvc"
78 } else {
79 "x86_64-unknown-linux-gnu"
80 };
81
8bb4bdeb
XL
82 cfg.target(target)
83 .host(target)
84 .opt_level(2)
85 .debug(false)
86 .out_dir(self.td.path())
60c5eb7d 87 .__set_env("PATH", self.path())
8bb4bdeb 88 .__set_env("GCCTEST_OUT_DIR", self.td.path());
476ff2be
SL
89 if self.msvc {
90 cfg.compiler(self.td.path().join("cl"));
91 cfg.archiver(self.td.path().join("lib.exe"));
92 }
8bb4bdeb 93 cfg
476ff2be
SL
94 }
95
60c5eb7d
XL
96 fn path(&self) -> OsString {
97 let mut path = env::split_paths(&env::var_os("PATH").unwrap()).collect::<Vec<_>>();
98 path.insert(0, self.td.path().to_owned());
99 env::join_paths(path).unwrap()
100 }
101
476ff2be
SL
102 pub fn cmd(&self, i: u32) -> Execution {
103 let mut s = String::new();
8bb4bdeb
XL
104 File::open(self.td.path().join(format!("out{}", i)))
105 .unwrap()
106 .read_to_string(&mut s)
107 .unwrap();
0531ce1d
XL
108 Execution {
109 args: s.lines().map(|s| s.to_string()).collect(),
110 }
476ff2be
SL
111 }
112}
113
114impl Execution {
115 pub fn must_have<P: AsRef<OsStr>>(&self, p: P) -> &Execution {
116 if !self.has(p.as_ref()) {
117 panic!("didn't find {:?} in {:?}", p.as_ref(), self.args);
118 } else {
119 self
120 }
121 }
122
123 pub fn must_not_have<P: AsRef<OsStr>>(&self, p: P) -> &Execution {
124 if self.has(p.as_ref()) {
125 panic!("found {:?}", p.as_ref());
126 } else {
127 self
128 }
129 }
130
131 pub fn has(&self, p: &OsStr) -> bool {
8bb4bdeb 132 self.args.iter().any(|arg| OsStr::new(arg) == p)
476ff2be 133 }
abe05a73
XL
134
135 pub fn must_have_in_order(&self, before: &str, after: &str) -> &Execution {
48663c56
XL
136 let before_position = self
137 .args
0531ce1d
XL
138 .iter()
139 .rposition(|x| OsStr::new(x) == OsStr::new(before));
48663c56
XL
140 let after_position = self
141 .args
0531ce1d
XL
142 .iter()
143 .rposition(|x| OsStr::new(x) == OsStr::new(after));
abe05a73 144 match (before_position, after_position) {
0531ce1d
XL
145 (Some(b), Some(a)) if b < a => {}
146 (b, a) => panic!(
147 "{:?} (last position: {:?}) did not appear before {:?} (last position: {:?})",
148 before, b, after, a
149 ),
abe05a73
XL
150 };
151 self
152 }
476ff2be 153}
60c5eb7d
XL
154
155/// Hard link an executable or copy it if that fails.
156///
157/// We first try to hard link an executable to save space. If that fails (as on Windows with
158/// different mount points, issue #60), we copy.
159#[cfg(not(target_os = "macos"))]
160fn link_or_copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<()> {
161 let from = from.as_ref();
162 let to = to.as_ref();
163 fs::hard_link(from, to).or_else(|_| fs::copy(from, to).map(|_| ()))
164}
165
166/// Copy an executable.
167///
168/// On macOS, hard linking the executable leads to strange failures (issue #419), so we just copy.
169#[cfg(target_os = "macos")]
170fn link_or_copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<()> {
171 fs::copy(from, to).map(|_| ())
172}