diff options
Diffstat (limited to 'gcc/tests')
| -rw-r--r-- | gcc/tests/cc_env.rs | 49 | ||||
| -rw-r--r-- | gcc/tests/support/mod.rs | 112 | ||||
| -rw-r--r-- | gcc/tests/test.rs | 229 | 
3 files changed, 390 insertions, 0 deletions
| diff --git a/gcc/tests/cc_env.rs b/gcc/tests/cc_env.rs new file mode 100644 index 0000000..559dbe8 --- /dev/null +++ b/gcc/tests/cc_env.rs @@ -0,0 +1,49 @@ +extern crate tempdir; +extern crate gcc; + +use std::env; + +mod support; +use support::Test; + +#[test] +fn main() { +    ccache(); +    distcc(); +    ccache_spaces(); +} + +fn ccache() { +    let test = Test::gnu(); +    test.shim("ccache"); + +    env::set_var("CC", "ccache lol-this-is-not-a-compiler foo"); +    test.gcc().file("foo.c").compile("libfoo.a"); + +    test.cmd(0) +        .must_have("lol-this-is-not-a-compiler foo") +        .must_have("foo.c") +        .must_not_have("ccache"); +} + +fn ccache_spaces() { +    let test = Test::gnu(); +    test.shim("ccache"); + +    env::set_var("CC", "ccache        lol-this-is-not-a-compiler foo"); +    test.gcc().file("foo.c").compile("libfoo.a"); +    test.cmd(0).must_have("lol-this-is-not-a-compiler foo"); +} + +fn distcc() { +    let test = Test::gnu(); +    test.shim("distcc"); + +    env::set_var("CC", "distcc lol-this-is-not-a-compiler foo"); +    test.gcc().file("foo.c").compile("libfoo.a"); + +    test.cmd(0) +        .must_have("lol-this-is-not-a-compiler foo") +        .must_have("foo.c") +        .must_not_have("distcc"); +} diff --git a/gcc/tests/support/mod.rs b/gcc/tests/support/mod.rs new file mode 100644 index 0000000..135a663 --- /dev/null +++ b/gcc/tests/support/mod.rs @@ -0,0 +1,112 @@ +#![allow(dead_code)] + +use std::env; +use std::ffi::OsStr; +use std::fs::{self, File}; +use std::io::prelude::*; +use std::path::PathBuf; + +use gcc; +use tempdir::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 { +        let mut gcc = PathBuf::from(env::current_exe().unwrap()); +        gcc.pop(); +        if gcc.ends_with("deps") { +            gcc.pop(); +        } +        gcc.push(format!("gcc-shim{}", env::consts::EXE_SUFFIX)); +        Test { +            td: TempDir::new("gcc-test").unwrap(), +            gcc: gcc, +            msvc: false, +        } +    } + +    pub fn gnu() -> Test { +        let t = Test::new(); +        t.shim("cc").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 fname = format!("{}{}", name, env::consts::EXE_SUFFIX); +        fs::hard_link(&self.gcc, self.td.path().join(&fname)) +            .or_else(|_| fs::copy(&self.gcc, self.td.path().join(&fname)).map(|_| ())) +            .unwrap(); +        self +    } + +    pub fn gcc(&self) -> gcc::Config { +        let mut cfg = gcc::Config::new(); +        let mut path = env::split_paths(&env::var_os("PATH").unwrap()).collect::<Vec<_>>(); +        path.insert(0, self.td.path().to_owned()); +        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", env::join_paths(path).unwrap()) +            .__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 +    } + +    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) +    } +} diff --git a/gcc/tests/test.rs b/gcc/tests/test.rs new file mode 100644 index 0000000..1c51e09 --- /dev/null +++ b/gcc/tests/test.rs @@ -0,0 +1,229 @@ +extern crate gcc; +extern crate tempdir; + +use support::Test; + +mod support; + +#[test] +fn gnu_smoke() { +    let test = Test::gnu(); +    test.gcc() +        .file("foo.c") +        .compile("libfoo.a"); + +    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() { +    let test = Test::gnu(); +    test.gcc() +        .opt_level(1) +        .file("foo.c") +        .compile("libfoo.a"); + +    test.cmd(0) +        .must_have("-O1") +        .must_not_have("-O2"); +} + +#[test] +fn gnu_opt_level_s() { +    let test = Test::gnu(); +    test.gcc() +        .opt_level_str("s") +        .file("foo.c") +        .compile("libfoo.a"); + +    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() { +    let test = Test::gnu(); +    test.gcc() +        .debug(true) +        .file("foo.c") +        .compile("libfoo.a"); +    test.cmd(0).must_have("-g"); +} + +#[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("libfoo.a"); + +        test.cmd(0) +            .must_have("-fPIC") +            .must_have("-m64"); +    } +} + +#[test] +fn gnu_x86_64_no_pic() { +    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("libfoo.a"); + +        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("libfoo.a"); + +        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("libfoo.a"); + +        test.cmd(0).must_have("-fPIC"); +    } +} + +#[test] +fn gnu_set_stdlib() { +    let test = Test::gnu(); +    test.gcc() +        .cpp_set_stdlib(Some("foo")) +        .file("foo.c") +        .compile("libfoo.a"); + +    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("libfoo.a"); + +    test.cmd(0).must_have("-I").must_have("foo/bar"); +} + +#[test] +fn gnu_define() { +    let test = Test::gnu(); +    test.gcc() +        .define("FOO", Some("bar")) +        .define("BAR", None) +        .file("foo.c") +        .compile("libfoo.a"); + +    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("libfoo.a"); +    test.cmd(0).must_have("foo.S"); +} + +#[test] +fn msvc_smoke() { +    let test = Test::msvc(); +    test.gcc() +        .file("foo.c") +        .compile("libfoo.a"); + +    test.cmd(0) +        .must_have("/O2") +        .must_have("foo.c") +        .must_not_have("/Z7") +        .must_have("/c"); +    test.cmd(1).must_have(test.td.path().join("foo.o")); +} + +#[test] +fn msvc_opt_level_0() { +    let test = Test::msvc(); +    test.gcc() +        .opt_level(0) +        .file("foo.c") +        .compile("libfoo.a"); + +    test.cmd(0).must_not_have("/O2"); +} + +#[test] +fn msvc_debug() { +    let test = Test::msvc(); +    test.gcc() +        .debug(true) +        .file("foo.c") +        .compile("libfoo.a"); +    test.cmd(0).must_have("/Z7"); +} + +#[test] +fn msvc_include() { +    let test = Test::msvc(); +    test.gcc() +        .include("foo/bar") +        .file("foo.c") +        .compile("libfoo.a"); + +    test.cmd(0).must_have("/I").must_have("foo/bar"); +} + +#[test] +fn msvc_define() { +    let test = Test::msvc(); +    test.gcc() +        .define("FOO", Some("bar")) +        .define("BAR", None) +        .file("foo.c") +        .compile("libfoo.a"); + +    test.cmd(0).must_have("/DFOO=bar").must_have("/DBAR"); +} | 
