1+ //! To run this test, use
2+ //! `env INTEGRATION=rust-lang/log cargo test --test integration --features=integration`
3+ //!
4+ //! You can use a different `INTEGRATION` value to test different repositories.
5+
16#![ cfg( feature = "integration" ) ]
27#![ cfg_attr( feature = "deny-warnings" , deny( warnings) ) ]
38#![ warn( rust_2018_idioms, unused_lifetimes) ]
49
5- use std:: env;
610use std:: ffi:: OsStr ;
11+ use std:: path:: { Path , PathBuf } ;
712use std:: process:: Command ;
13+ use std:: { env, eprintln} ;
814
915#[ cfg( not( windows) ) ]
1016const CARGO_CLIPPY : & str = "cargo-clippy" ;
1117#[ cfg( windows) ]
1218const CARGO_CLIPPY : & str = "cargo-clippy.exe" ;
1319
14- #[ cfg_attr( feature = "integration" , test) ]
15- fn integration_test ( ) {
16- let repo_name = env:: var ( "INTEGRATION" ) . expect ( "`INTEGRATION` var not set" ) ;
20+ // NOTE: arguments passed to the returned command will be `clippy-driver` args, not `cargo-clippy`
21+ // args. Use `cargo_args` to pass arguments to cargo-clippy.
22+ fn clippy_command ( repo_dir : & Path , cargo_args : & [ & str ] ) -> Command {
23+ let root_dir = std:: path:: PathBuf :: from ( env ! ( "CARGO_MANIFEST_DIR" ) ) ;
24+ let target_dir = option_env ! ( "CARGO_TARGET_DIR" ) . map_or_else ( || root_dir. join ( "target" ) , PathBuf :: from) ;
25+ let clippy_binary = target_dir. join ( env ! ( "PROFILE" ) ) . join ( CARGO_CLIPPY ) ;
26+
27+ let mut cargo_clippy = Command :: new ( clippy_binary) ;
28+ cargo_clippy
29+ . current_dir ( repo_dir)
30+ . env ( "RUST_BACKTRACE" , "full" )
31+ . env ( "CARGO_TARGET_DIR" , root_dir. join ( "target" ) )
32+ . args ( [ "clippy" , "--all-targets" , "--all-features" ] )
33+ . args ( cargo_args)
34+ . args ( [ "--" , "--cap-lints" , "warn" , "-Wclippy::pedantic" , "-Wclippy::nursery" ] ) ;
35+ cargo_clippy
36+ }
37+
38+ /// Return a directory with a checkout of the repository in `INTEGRATION`.
39+ fn repo_dir ( repo_name : & str ) -> PathBuf {
1740 let repo_url = format ! ( "https://github.com/{repo_name}" ) ;
1841 let crate_name = repo_name
1942 . split ( '/' )
@@ -34,28 +57,19 @@ fn integration_test() {
3457 . expect ( "unable to run git" ) ;
3558 assert ! ( st. success( ) ) ;
3659
37- let root_dir = std:: path:: PathBuf :: from ( env ! ( "CARGO_MANIFEST_DIR" ) ) ;
38- let target_dir = std:: path:: Path :: new ( & root_dir) . join ( "target" ) ;
39- let clippy_binary = target_dir. join ( env ! ( "PROFILE" ) ) . join ( CARGO_CLIPPY ) ;
40-
41- let output = Command :: new ( clippy_binary)
42- . current_dir ( repo_dir)
43- . env ( "RUST_BACKTRACE" , "full" )
44- . env ( "CARGO_TARGET_DIR" , target_dir)
45- . args ( [
46- "clippy" ,
47- "--all-targets" ,
48- "--all-features" ,
49- "--" ,
50- "--cap-lints" ,
51- "warn" ,
52- "-Wclippy::pedantic" ,
53- "-Wclippy::nursery" ,
54- ] )
55- . output ( )
56- . expect ( "unable to run clippy" ) ;
60+ repo_dir
61+ }
5762
63+ #[ cfg_attr( feature = "integration" , test) ]
64+ fn integration_test ( ) {
65+ let repo_name = env:: var ( "INTEGRATION" ) . expect ( "`INTEGRATION` var not set" ) ;
66+ let repo_dir = repo_dir ( & repo_name) ;
67+ let output = clippy_command ( & repo_dir, & [ ] ) . output ( ) . expect ( "failed to run clippy" ) ;
5868 let stderr = String :: from_utf8_lossy ( & output. stderr ) ;
69+ if !stderr. is_empty ( ) {
70+ eprintln ! ( "{}" , stderr) ;
71+ }
72+
5973 if let Some ( backtrace_start) = stderr. find ( "error: internal compiler error" ) {
6074 static BACKTRACE_END_MSG : & str = "end of query stack" ;
6175 let backtrace_end = stderr[ backtrace_start..]
@@ -90,3 +104,42 @@ fn integration_test() {
90104 None => panic ! ( "Process terminated by signal" ) ,
91105 }
92106}
107+
108+ #[ cfg_attr( feature = "integration" , test) ]
109+ fn test_sysroot ( ) {
110+ let rustc = std:: env:: var ( "RUSTC" ) . unwrap_or ( "rustc" . to_string ( ) ) ;
111+ let rustc_output = Command :: new ( rustc)
112+ . args ( [ "--print" , "sysroot" ] )
113+ . output ( )
114+ . expect ( "unable to run rustc" ) ;
115+ assert ! ( rustc_output. status. success( ) ) ;
116+ let sysroot = String :: from_utf8 ( rustc_output. stdout ) . unwrap ( ) ;
117+ let sysroot = sysroot. trim_end ( ) ;
118+
119+ #[ track_caller]
120+ fn verify_cmd ( cmd : & mut Command ) {
121+ // Test that SYSROOT is ignored if `--sysroot` is passed explicitly.
122+ cmd. env ( "SYSROOT" , "/dummy/value/does/not/exist" ) ;
123+ // We don't actually care about emitting lints, we only want to verify clippy doesn't give a hard
124+ // error.
125+ cmd. arg ( "-Awarnings" ) ;
126+ let output = cmd. output ( ) . expect ( "failed to run clippy" ) ;
127+ let stderr = String :: from_utf8_lossy ( & output. stderr ) ;
128+ if !stderr. is_empty ( ) {
129+ panic ! ( "clippy printed an error: {}" , stderr) ;
130+ }
131+ if !output. status . success ( ) {
132+ panic ! ( "clippy exited with an error" )
133+ }
134+ }
135+
136+ // This is a fairly small repo; we want to avoid checking out anything heavy twice, so just
137+ // hard-code it.
138+ let repo_name = "rust-lang/log" ;
139+ let repo_dir = repo_dir ( repo_name) ;
140+ // Pass the sysroot through RUSTFLAGS.
141+ verify_cmd ( clippy_command ( & repo_dir, & [ "--quiet" ] ) . env ( "RUSTFLAGS" , format ! ( "--sysroot={sysroot}" ) ) ) ;
142+ // NOTE: we don't test passing the arguments directly to clippy-driver (with `-- --sysroot`)
143+ // because it breaks for some reason. I (@jyn514) haven't taken time to track down the bug
144+ // because rust-lang/rust uses RUSTFLAGS and nearly no one else uses --sysroot.
145+ }
0 commit comments