use std::fs; use std::env; use cargotest::{is_nightly, rustc_host}; use cargotest::support::{execs, project}; use hamcrest::assert_that; #[test] fn plugin_to_the_max() { if !is_nightly() { return; } let foo = project("foo") .file( "Cargo.toml", r#" [package] name = "foo" version = "0.0.1" authors = [] [lib] name = "foo_lib" [dependencies.bar] path = "../bar" "#, ) .file( "src/main.rs", r#" #![feature(plugin)] #![plugin(bar)] extern crate foo_lib; fn main() { foo_lib::foo(); } "#, ) .file( "src/foo_lib.rs", r#" #![feature(plugin)] #![plugin(bar)] pub fn foo() {} "#, ) .build(); let _bar = project("bar") .file( "Cargo.toml", r#" [package] name = "bar" version = "0.0.1" authors = [] [lib] name = "bar" plugin = true [dependencies.baz] path = "../baz" "#, ) .file( "src/lib.rs", r#" #![feature(plugin_registrar, rustc_private)] extern crate rustc_plugin; extern crate baz; use rustc_plugin::Registry; #[plugin_registrar] pub fn foo(_reg: &mut Registry) { println!("{}", baz::baz()); } "#, ) .build(); let _baz = project("baz") .file( "Cargo.toml", r#" [package] name = "baz" version = "0.0.1" authors = [] [lib] name = "baz" crate_type = ["dylib"] "#, ) .file("src/lib.rs", "pub fn baz() -> i32 { 1 }") .build(); assert_that(foo.cargo("build"), execs().with_status(0)); assert_that(foo.cargo("doc"), execs().with_status(0)); } #[test] fn plugin_with_dynamic_native_dependency() { if !is_nightly() { return; } let workspace = project("ws") .file( "Cargo.toml", r#" [workspace] members = ["builder", "foo"] "#, ) .build(); let build = project("ws/builder") .file( "Cargo.toml", r#" [package] name = "builder" version = "0.0.1" authors = [] [lib] name = "builder" crate-type = ["dylib"] "#, ) .file( "src/lib.rs", r#" #[no_mangle] pub extern fn foo() {} "#, ) .build(); let foo = project("ws/foo") .file( "Cargo.toml", r#" [package] name = "foo" version = "0.0.1" authors = [] [dependencies.bar] path = "bar" "#, ) .file( "src/main.rs", r#" #![feature(plugin)] #![plugin(bar)] fn main() {} "#, ) .file( "bar/Cargo.toml", r#" [package] name = "bar" version = "0.0.1" authors = [] build = 'build.rs' [lib] name = "bar" plugin = true "#, ) .file( "bar/build.rs", r#" use std::path::PathBuf; use std::env; fn main() { let src = PathBuf::from(env::var("SRC").unwrap()); println!("cargo:rustc-flags=-L {}/deps", src.parent().unwrap().display()); } "#, ) .file( "bar/src/lib.rs", r#" #![feature(plugin_registrar, rustc_private)] extern crate rustc_plugin; use rustc_plugin::Registry; #[cfg_attr(not(target_env = "msvc"), link(name = "builder"))] #[cfg_attr(target_env = "msvc", link(name = "builder.dll"))] extern { fn foo(); } #[plugin_registrar] pub fn bar(_reg: &mut Registry) { unsafe { foo() } } "#, ) .build(); assert_that(build.cargo("build"), execs().with_status(0)); let src = workspace.root().join("target/debug"); let lib = fs::read_dir(&src) .unwrap() .map(|s| s.unwrap().path()) .find(|lib| { let lib = lib.file_name().unwrap().to_str().unwrap(); lib.starts_with(env::consts::DLL_PREFIX) && lib.ends_with(env::consts::DLL_SUFFIX) }) .unwrap(); assert_that( foo.cargo("build").env("SRC", &lib).arg("-v"), execs().with_status(0), ); } #[test] fn plugin_integration() { let p = project("foo") .file( "Cargo.toml", r#" [package] name = "foo" version = "0.0.1" authors = [] build = "build.rs" [lib] name = "foo" plugin = true doctest = false "#, ) .file("build.rs", "fn main() {}") .file("src/lib.rs", "") .file("tests/it_works.rs", "") .build(); assert_that(p.cargo("test").arg("-v"), execs().with_status(0)); } #[test] fn doctest_a_plugin() { let p = project("foo") .file( "Cargo.toml", r#" [package] name = "foo" version = "0.0.1" authors = [] [dependencies] bar = { path = "bar" } "#, ) .file( "src/lib.rs", r#" #[macro_use] extern crate bar; "#, ) .file( "bar/Cargo.toml", r#" [package] name = "bar" version = "0.0.1" authors = [] [lib] name = "bar" plugin = true "#, ) .file( "bar/src/lib.rs", r#" pub fn bar() {} "#, ) .build(); assert_that(p.cargo("test").arg("-v"), execs().with_status(0)); } // See #1515 #[test] fn native_plugin_dependency_with_custom_ar_linker() { let target = rustc_host(); let _foo = project("foo") .file( "Cargo.toml", r#" [package] name = "foo" version = "0.0.1" authors = [] [lib] plugin = true "#, ) .file("src/lib.rs", "") .build(); let bar = project("bar") .file( "Cargo.toml", r#" [package] name = "bar" version = "0.0.1" authors = [] [dependencies.foo] path = "../foo" "#, ) .file("src/lib.rs", "") .file( ".cargo/config", &format!( r#" [target.{}] ar = "nonexistent-ar" linker = "nonexistent-linker" "#, target ), ) .build(); assert_that( bar.cargo("build").arg("--verbose"), execs().with_stderr_contains( "\ [COMPILING] foo v0.0.1 ([..]) [RUNNING] `rustc [..] -C ar=nonexistent-ar -C linker=nonexistent-linker [..]` [ERROR] [..]linker[..] ", ), ); } #[test] fn panic_abort_plugins() { if !is_nightly() { return; } let p = project("bar") .file( "Cargo.toml", r#" [package] name = "bar" version = "0.0.1" authors = [] [profile.dev] panic = 'abort' [dependencies] foo = { path = "foo" } "#, ) .file("src/lib.rs", "") .file( "foo/Cargo.toml", r#" [package] name = "foo" version = "0.0.1" authors = [] [lib] plugin = true "#, ) .file( "foo/src/lib.rs", r#" #![feature(rustc_private)] extern crate syntax; "#, ) .build(); assert_that(p.cargo("build"), execs().with_status(0)); } #[test] fn shared_panic_abort_plugins() { if !is_nightly() { return; } let p = project("top") .file( "Cargo.toml", r#" [package] name = "top" version = "0.0.1" authors = [] [profile.dev] panic = 'abort' [dependencies] foo = { path = "foo" } bar = { path = "bar" } "#, ) .file( "src/lib.rs", " extern crate bar; ", ) .file( "foo/Cargo.toml", r#" [package] name = "foo" version = "0.0.1" authors = [] [lib] plugin = true [dependencies] bar = { path = "../bar" } "#, ) .file( "foo/src/lib.rs", r#" #![feature(rustc_private)] extern crate syntax; extern crate bar; "#, ) .file( "bar/Cargo.toml", r#" [package] name = "bar" version = "0.0.1" authors = [] "#, ) .file("bar/src/lib.rs", "") .build(); assert_that(p.cargo("build"), execs().with_status(0)); }