summaryrefslogtreecommitdiffstats
path: root/third_party/rust/cc/tests
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /third_party/rust/cc/tests
parentInitial commit. (diff)
downloadfirefox-esr-upstream.tar.xz
firefox-esr-upstream.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--third_party/rust/cc/tests/cc_env.rs118
-rw-r--r--third_party/rust/cc/tests/cflags.rs15
-rw-r--r--third_party/rust/cc/tests/cxxflags.rs15
-rw-r--r--third_party/rust/cc/tests/support/mod.rs172
-rw-r--r--third_party/rust/cc/tests/test.rs413
5 files changed, 733 insertions, 0 deletions
diff --git a/third_party/rust/cc/tests/cc_env.rs b/third_party/rust/cc/tests/cc_env.rs
new file mode 100644
index 0000000000..43eb689f0f
--- /dev/null
+++ b/third_party/rust/cc/tests/cc_env.rs
@@ -0,0 +1,118 @@
+use std::env;
+use std::ffi::OsString;
+use std::path::Path;
+
+mod support;
+use crate::support::Test;
+
+#[test]
+fn main() {
+ ccache();
+ distcc();
+ ccache_spaces();
+ ccache_env_flags();
+ leading_spaces();
+ extra_flags();
+ path_to_ccache();
+ more_spaces();
+}
+
+fn ccache() {
+ let test = Test::gnu();
+
+ env::set_var("CC", "ccache cc");
+ let compiler = test.gcc().file("foo.c").get_compiler();
+
+ assert_eq!(compiler.path(), Path::new("cc"));
+}
+
+fn ccache_spaces() {
+ let test = Test::gnu();
+ test.shim("ccache");
+
+ env::set_var("CC", "ccache cc");
+ let compiler = test.gcc().file("foo.c").get_compiler();
+ assert_eq!(compiler.path(), Path::new("cc"));
+}
+
+fn distcc() {
+ let test = Test::gnu();
+ test.shim("distcc");
+
+ env::set_var("CC", "distcc cc");
+ let compiler = test.gcc().file("foo.c").get_compiler();
+ assert_eq!(compiler.path(), Path::new("cc"));
+}
+
+fn ccache_env_flags() {
+ let test = Test::gnu();
+ test.shim("ccache");
+
+ env::set_var("CC", "ccache lol-this-is-not-a-compiler");
+ let compiler = test.gcc().file("foo.c").get_compiler();
+ assert_eq!(compiler.path(), Path::new("lol-this-is-not-a-compiler"));
+ assert_eq!(
+ compiler.cc_env(),
+ OsString::from("ccache lol-this-is-not-a-compiler")
+ );
+ assert!(
+ compiler
+ .cflags_env()
+ .into_string()
+ .unwrap()
+ .contains("ccache")
+ == false
+ );
+ assert!(
+ compiler
+ .cflags_env()
+ .into_string()
+ .unwrap()
+ .contains(" lol-this-is-not-a-compiler")
+ == false
+ );
+
+ env::set_var("CC", "");
+}
+
+fn leading_spaces() {
+ let test = Test::gnu();
+ test.shim("ccache");
+
+ env::set_var("CC", " test ");
+ let compiler = test.gcc().file("foo.c").get_compiler();
+ assert_eq!(compiler.path(), Path::new("test"));
+
+ env::set_var("CC", "");
+}
+
+fn extra_flags() {
+ let test = Test::gnu();
+ test.shim("ccache");
+
+ env::set_var("CC", "ccache cc -m32");
+ let compiler = test.gcc().file("foo.c").get_compiler();
+ assert_eq!(compiler.path(), Path::new("cc"));
+}
+
+fn path_to_ccache() {
+ let test = Test::gnu();
+ test.shim("ccache");
+
+ env::set_var("CC", "/path/to/ccache.exe cc -m32");
+ let compiler = test.gcc().file("foo.c").get_compiler();
+ assert_eq!(compiler.path(), Path::new("cc"));
+ assert_eq!(
+ compiler.cc_env(),
+ OsString::from("/path/to/ccache.exe cc -m32"),
+ );
+}
+
+fn more_spaces() {
+ let test = Test::gnu();
+ test.shim("ccache");
+
+ env::set_var("CC", "cc -m32");
+ let compiler = test.gcc().file("foo.c").get_compiler();
+ assert_eq!(compiler.path(), Path::new("cc"));
+}
diff --git a/third_party/rust/cc/tests/cflags.rs b/third_party/rust/cc/tests/cflags.rs
new file mode 100644
index 0000000000..caec6ea4ed
--- /dev/null
+++ b/third_party/rust/cc/tests/cflags.rs
@@ -0,0 +1,15 @@
+mod support;
+
+use crate::support::Test;
+use std::env;
+
+/// This test is in its own module because it modifies the environment and would affect other tests
+/// when run in parallel with them.
+#[test]
+fn gnu_no_warnings_if_cflags() {
+ env::set_var("CFLAGS", "-arbitrary");
+ let test = Test::gnu();
+ test.gcc().file("foo.c").compile("foo");
+
+ test.cmd(0).must_not_have("-Wall").must_not_have("-Wextra");
+}
diff --git a/third_party/rust/cc/tests/cxxflags.rs b/third_party/rust/cc/tests/cxxflags.rs
new file mode 100644
index 0000000000..c524c7da4e
--- /dev/null
+++ b/third_party/rust/cc/tests/cxxflags.rs
@@ -0,0 +1,15 @@
+mod support;
+
+use crate::support::Test;
+use std::env;
+
+/// This test is in its own module because it modifies the environment and would affect other tests
+/// when run in parallel with them.
+#[test]
+fn gnu_no_warnings_if_cxxflags() {
+ env::set_var("CXXFLAGS", "-arbitrary");
+ let test = Test::gnu();
+ test.gcc().file("foo.cpp").cpp(true).compile("foo");
+
+ test.cmd(0).must_not_have("-Wall").must_not_have("-Wextra");
+}
diff --git a/third_party/rust/cc/tests/support/mod.rs b/third_party/rust/cc/tests/support/mod.rs
new file mode 100644
index 0000000000..f3c04405a3
--- /dev/null
+++ b/third_party/rust/cc/tests/support/mod.rs
@@ -0,0 +1,172 @@
+#![allow(dead_code)]
+
+use std::env;
+use std::ffi::{OsStr, OsString};
+use std::fs::{self, File};
+use std::io;
+use std::io::prelude::*;
+use std::path::{Path, PathBuf};
+
+use cc;
+use tempfile::{Builder, TempDir};
+
+pub struct Test {
+ pub td: TempDir,
+ pub gcc: PathBuf,
+ pub msvc: bool,
+}
+
+pub struct Execution {
+ args: Vec<String>,
+}
+
+impl Test {
+ pub fn new() -> Test {
+ // This is ugly: `sccache` needs to introspect the compiler it is
+ // executing, as it adjusts its behavior depending on the
+ // language/compiler. This crate's test driver uses mock compilers that
+ // are obviously not supported by sccache, so the tests fail if
+ // RUSTC_WRAPPER is set. rust doesn't build test dependencies with
+ // the `test` feature enabled, so we can't conditionally disable the
+ // usage of `sccache` if running in a test environment, at least not
+ // without setting an environment variable here and testing for it
+ // there. Explicitly deasserting RUSTC_WRAPPER here seems to be the
+ // lesser of the two evils.
+ env::remove_var("RUSTC_WRAPPER");
+
+ let mut gcc = PathBuf::from(env::current_exe().unwrap());
+ gcc.pop();
+ if gcc.ends_with("deps") {
+ gcc.pop();
+ }
+ let td = Builder::new().prefix("gcc-test").tempdir_in(&gcc).unwrap();
+ gcc.push(format!("gcc-shim{}", env::consts::EXE_SUFFIX));
+ Test {
+ td: td,
+ gcc: gcc,
+ msvc: false,
+ }
+ }
+
+ pub fn gnu() -> Test {
+ let t = Test::new();
+ t.shim("cc").shim("c++").shim("ar");
+ t
+ }
+
+ pub fn msvc() -> Test {
+ let mut t = Test::new();
+ t.shim("cl").shim("lib.exe");
+ t.msvc = true;
+ t
+ }
+
+ pub fn shim(&self, name: &str) -> &Test {
+ let name = if name.ends_with(env::consts::EXE_SUFFIX) {
+ name.to_string()
+ } else {
+ format!("{}{}", name, env::consts::EXE_SUFFIX)
+ };
+ link_or_copy(&self.gcc, self.td.path().join(name)).unwrap();
+ self
+ }
+
+ pub fn gcc(&self) -> cc::Build {
+ let mut cfg = cc::Build::new();
+ let target = if self.msvc {
+ "x86_64-pc-windows-msvc"
+ } else {
+ "x86_64-unknown-linux-gnu"
+ };
+
+ cfg.target(target)
+ .host(target)
+ .opt_level(2)
+ .debug(false)
+ .out_dir(self.td.path())
+ .__set_env("PATH", self.path())
+ .__set_env("GCCTEST_OUT_DIR", self.td.path());
+ if self.msvc {
+ cfg.compiler(self.td.path().join("cl"));
+ cfg.archiver(self.td.path().join("lib.exe"));
+ }
+ cfg
+ }
+
+ fn path(&self) -> OsString {
+ let mut path = env::split_paths(&env::var_os("PATH").unwrap()).collect::<Vec<_>>();
+ path.insert(0, self.td.path().to_owned());
+ env::join_paths(path).unwrap()
+ }
+
+ pub fn cmd(&self, i: u32) -> Execution {
+ let mut s = String::new();
+ File::open(self.td.path().join(format!("out{}", i)))
+ .unwrap()
+ .read_to_string(&mut s)
+ .unwrap();
+ Execution {
+ args: s.lines().map(|s| s.to_string()).collect(),
+ }
+ }
+}
+
+impl Execution {
+ pub fn must_have<P: AsRef<OsStr>>(&self, p: P) -> &Execution {
+ if !self.has(p.as_ref()) {
+ panic!("didn't find {:?} in {:?}", p.as_ref(), self.args);
+ } else {
+ self
+ }
+ }
+
+ pub fn must_not_have<P: AsRef<OsStr>>(&self, p: P) -> &Execution {
+ if self.has(p.as_ref()) {
+ panic!("found {:?}", p.as_ref());
+ } else {
+ self
+ }
+ }
+
+ pub fn has(&self, p: &OsStr) -> bool {
+ self.args.iter().any(|arg| OsStr::new(arg) == p)
+ }
+
+ pub fn must_have_in_order(&self, before: &str, after: &str) -> &Execution {
+ let before_position = self
+ .args
+ .iter()
+ .rposition(|x| OsStr::new(x) == OsStr::new(before));
+ let after_position = self
+ .args
+ .iter()
+ .rposition(|x| OsStr::new(x) == OsStr::new(after));
+ match (before_position, after_position) {
+ (Some(b), Some(a)) if b < a => {}
+ (b, a) => panic!(
+ "{:?} (last position: {:?}) did not appear before {:?} (last position: {:?})",
+ before, b, after, a
+ ),
+ };
+ self
+ }
+}
+
+/// Hard link an executable or copy it if that fails.
+///
+/// We first try to hard link an executable to save space. If that fails (as on Windows with
+/// different mount points, issue #60), we copy.
+#[cfg(not(target_os = "macos"))]
+fn link_or_copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<()> {
+ let from = from.as_ref();
+ let to = to.as_ref();
+ fs::hard_link(from, to).or_else(|_| fs::copy(from, to).map(|_| ()))
+}
+
+/// Copy an executable.
+///
+/// On macOS, hard linking the executable leads to strange failures (issue #419), so we just copy.
+#[cfg(target_os = "macos")]
+fn link_or_copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<()> {
+ fs::copy(from, to).map(|_| ())
+}
diff --git a/third_party/rust/cc/tests/test.rs b/third_party/rust/cc/tests/test.rs
new file mode 100644
index 0000000000..3c9b4dc498
--- /dev/null
+++ b/third_party/rust/cc/tests/test.rs
@@ -0,0 +1,413 @@
+use crate::support::Test;
+
+mod support;
+
+// Some tests check that a flag is *not* present. These tests might fail if the flag is set in the
+// CFLAGS or CXXFLAGS environment variables. This function clears the CFLAGS and CXXFLAGS
+// variables to make sure that the tests can run correctly.
+fn reset_env() {
+ std::env::set_var("CFLAGS", "");
+ std::env::set_var("CXXFLAGS", "");
+}
+
+#[test]
+fn gnu_smoke() {
+ reset_env();
+
+ let test = Test::gnu();
+ test.gcc().file("foo.c").compile("foo");
+
+ test.cmd(0)
+ .must_have("-O2")
+ .must_have("foo.c")
+ .must_not_have("-g")
+ .must_have("-c")
+ .must_have("-ffunction-sections")
+ .must_have("-fdata-sections");
+ test.cmd(1).must_have(test.td.path().join("foo.o"));
+}
+
+#[test]
+fn gnu_opt_level_1() {
+ reset_env();
+
+ let test = Test::gnu();
+ test.gcc().opt_level(1).file("foo.c").compile("foo");
+
+ test.cmd(0).must_have("-O1").must_not_have("-O2");
+}
+
+#[test]
+fn gnu_opt_level_s() {
+ reset_env();
+
+ let test = Test::gnu();
+ test.gcc().opt_level_str("s").file("foo.c").compile("foo");
+
+ test.cmd(0)
+ .must_have("-Os")
+ .must_not_have("-O1")
+ .must_not_have("-O2")
+ .must_not_have("-O3")
+ .must_not_have("-Oz");
+}
+
+#[test]
+fn gnu_debug_fp_auto() {
+ let test = Test::gnu();
+ test.gcc().debug(true).file("foo.c").compile("foo");
+ test.cmd(0).must_have("-g");
+ test.cmd(0).must_have("-fno-omit-frame-pointer");
+}
+
+#[test]
+fn gnu_debug_fp() {
+ let test = Test::gnu();
+ test.gcc().debug(true).file("foo.c").compile("foo");
+ test.cmd(0).must_have("-g");
+ test.cmd(0).must_have("-fno-omit-frame-pointer");
+}
+
+#[test]
+fn gnu_debug_nofp() {
+ reset_env();
+
+ let test = Test::gnu();
+ test.gcc()
+ .debug(true)
+ .force_frame_pointer(false)
+ .file("foo.c")
+ .compile("foo");
+ test.cmd(0).must_have("-g");
+ test.cmd(0).must_not_have("-fno-omit-frame-pointer");
+
+ let test = Test::gnu();
+ test.gcc()
+ .force_frame_pointer(false)
+ .debug(true)
+ .file("foo.c")
+ .compile("foo");
+ test.cmd(0).must_have("-g");
+ test.cmd(0).must_not_have("-fno-omit-frame-pointer");
+}
+
+#[test]
+fn gnu_warnings_into_errors() {
+ let test = Test::gnu();
+ test.gcc()
+ .warnings_into_errors(true)
+ .file("foo.c")
+ .compile("foo");
+
+ test.cmd(0).must_have("-Werror");
+}
+
+#[test]
+fn gnu_warnings() {
+ let test = Test::gnu();
+ test.gcc()
+ .warnings(true)
+ .flag("-Wno-missing-field-initializers")
+ .file("foo.c")
+ .compile("foo");
+
+ test.cmd(0).must_have("-Wall").must_have("-Wextra");
+}
+
+#[test]
+fn gnu_extra_warnings0() {
+ reset_env();
+
+ let test = Test::gnu();
+ test.gcc()
+ .warnings(true)
+ .extra_warnings(false)
+ .flag("-Wno-missing-field-initializers")
+ .file("foo.c")
+ .compile("foo");
+
+ test.cmd(0).must_have("-Wall").must_not_have("-Wextra");
+}
+
+#[test]
+fn gnu_extra_warnings1() {
+ reset_env();
+
+ let test = Test::gnu();
+ test.gcc()
+ .warnings(false)
+ .extra_warnings(true)
+ .flag("-Wno-missing-field-initializers")
+ .file("foo.c")
+ .compile("foo");
+
+ test.cmd(0).must_not_have("-Wall").must_have("-Wextra");
+}
+
+#[test]
+fn gnu_warnings_overridable() {
+ reset_env();
+
+ let test = Test::gnu();
+ test.gcc()
+ .warnings(true)
+ .flag("-Wno-missing-field-initializers")
+ .file("foo.c")
+ .compile("foo");
+
+ test.cmd(0)
+ .must_have_in_order("-Wall", "-Wno-missing-field-initializers");
+}
+
+#[test]
+fn gnu_x86_64() {
+ for vendor in &["unknown-linux-gnu", "apple-darwin"] {
+ let target = format!("x86_64-{}", vendor);
+ let test = Test::gnu();
+ test.gcc()
+ .target(&target)
+ .host(&target)
+ .file("foo.c")
+ .compile("foo");
+
+ test.cmd(0).must_have("-fPIC").must_have("-m64");
+ }
+}
+
+#[test]
+fn gnu_x86_64_no_pic() {
+ reset_env();
+
+ for vendor in &["unknown-linux-gnu", "apple-darwin"] {
+ let target = format!("x86_64-{}", vendor);
+ let test = Test::gnu();
+ test.gcc()
+ .pic(false)
+ .target(&target)
+ .host(&target)
+ .file("foo.c")
+ .compile("foo");
+
+ test.cmd(0).must_not_have("-fPIC");
+ }
+}
+
+#[test]
+fn gnu_i686() {
+ for vendor in &["unknown-linux-gnu", "apple-darwin"] {
+ let target = format!("i686-{}", vendor);
+ let test = Test::gnu();
+ test.gcc()
+ .target(&target)
+ .host(&target)
+ .file("foo.c")
+ .compile("foo");
+
+ test.cmd(0).must_have("-m32");
+ }
+}
+
+#[test]
+fn gnu_i686_pic() {
+ for vendor in &["unknown-linux-gnu", "apple-darwin"] {
+ let target = format!("i686-{}", vendor);
+ let test = Test::gnu();
+ test.gcc()
+ .pic(true)
+ .target(&target)
+ .host(&target)
+ .file("foo.c")
+ .compile("foo");
+
+ test.cmd(0).must_have("-fPIC");
+ }
+}
+
+#[test]
+fn gnu_x86_64_no_plt() {
+ let target = "x86_64-unknown-linux-gnu";
+ let test = Test::gnu();
+ test.gcc()
+ .pic(true)
+ .use_plt(false)
+ .target(&target)
+ .host(&target)
+ .file("foo.c")
+ .compile("foo");
+ test.cmd(0).must_have("-fno-plt");
+}
+
+#[test]
+fn gnu_set_stdlib() {
+ reset_env();
+
+ let test = Test::gnu();
+ test.gcc()
+ .cpp_set_stdlib(Some("foo"))
+ .file("foo.c")
+ .compile("foo");
+
+ test.cmd(0).must_not_have("-stdlib=foo");
+}
+
+#[test]
+fn gnu_include() {
+ let test = Test::gnu();
+ test.gcc().include("foo/bar").file("foo.c").compile("foo");
+
+ test.cmd(0).must_have("-I").must_have("foo/bar");
+}
+
+#[test]
+fn gnu_define() {
+ let test = Test::gnu();
+ test.gcc()
+ .define("FOO", "bar")
+ .define("BAR", None)
+ .file("foo.c")
+ .compile("foo");
+
+ test.cmd(0).must_have("-DFOO=bar").must_have("-DBAR");
+}
+
+#[test]
+fn gnu_compile_assembly() {
+ let test = Test::gnu();
+ test.gcc().file("foo.S").compile("foo");
+ test.cmd(0).must_have("foo.S");
+}
+
+#[test]
+fn gnu_shared() {
+ reset_env();
+
+ let test = Test::gnu();
+ test.gcc()
+ .file("foo.c")
+ .shared_flag(true)
+ .static_flag(false)
+ .compile("foo");
+
+ test.cmd(0).must_have("-shared").must_not_have("-static");
+}
+
+#[test]
+fn gnu_flag_if_supported() {
+ reset_env();
+
+ if cfg!(windows) {
+ return;
+ }
+ let test = Test::gnu();
+ test.gcc()
+ .file("foo.c")
+ .flag("-v")
+ .flag_if_supported("-Wall")
+ .flag_if_supported("-Wflag-does-not-exist")
+ .flag_if_supported("-std=c++11")
+ .compile("foo");
+
+ test.cmd(0)
+ .must_have("-v")
+ .must_have("-Wall")
+ .must_not_have("-Wflag-does-not-exist")
+ .must_not_have("-std=c++11");
+}
+
+#[test]
+fn gnu_flag_if_supported_cpp() {
+ if cfg!(windows) {
+ return;
+ }
+ let test = Test::gnu();
+ test.gcc()
+ .cpp(true)
+ .file("foo.cpp")
+ .flag_if_supported("-std=c++11")
+ .compile("foo");
+
+ test.cmd(0).must_have("-std=c++11");
+}
+
+#[test]
+fn gnu_static() {
+ reset_env();
+
+ let test = Test::gnu();
+ test.gcc()
+ .file("foo.c")
+ .shared_flag(false)
+ .static_flag(true)
+ .compile("foo");
+
+ test.cmd(0).must_have("-static").must_not_have("-shared");
+}
+
+#[test]
+fn msvc_smoke() {
+ reset_env();
+
+ let test = Test::msvc();
+ test.gcc().file("foo.c").compile("foo");
+
+ test.cmd(0)
+ .must_have("-O2")
+ .must_have("foo.c")
+ .must_not_have("-Z7")
+ .must_have("-c")
+ .must_have("-MD");
+ test.cmd(1).must_have(test.td.path().join("foo.o"));
+}
+
+#[test]
+fn msvc_opt_level_0() {
+ reset_env();
+
+ let test = Test::msvc();
+ test.gcc().opt_level(0).file("foo.c").compile("foo");
+
+ test.cmd(0).must_not_have("-O2");
+}
+
+#[test]
+fn msvc_debug() {
+ let test = Test::msvc();
+ test.gcc().debug(true).file("foo.c").compile("foo");
+ test.cmd(0).must_have("-Z7");
+}
+
+#[test]
+fn msvc_include() {
+ let test = Test::msvc();
+ test.gcc().include("foo/bar").file("foo.c").compile("foo");
+
+ test.cmd(0).must_have("-I").must_have("foo/bar");
+}
+
+#[test]
+fn msvc_define() {
+ let test = Test::msvc();
+ test.gcc()
+ .define("FOO", "bar")
+ .define("BAR", None)
+ .file("foo.c")
+ .compile("foo");
+
+ test.cmd(0).must_have("-DFOO=bar").must_have("-DBAR");
+}
+
+#[test]
+fn msvc_static_crt() {
+ let test = Test::msvc();
+ test.gcc().static_crt(true).file("foo.c").compile("foo");
+
+ test.cmd(0).must_have("-MT");
+}
+
+#[test]
+fn msvc_no_static_crt() {
+ let test = Test::msvc();
+ test.gcc().static_crt(false).file("foo.c").compile("foo");
+
+ test.cmd(0).must_have("-MD");
+}