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,38 @@ fn integration_test() {
90104        None  => panic ! ( "Process terminated by signal" ) , 
91105    } 
92106} 
107+ 
108+ #[ cfg_attr( feature = "integration" ,  test) ]  
109+ fn  test_sysroot ( )  { 
110+     #[ track_caller]  
111+     fn  verify_cmd ( cmd :  & mut  Command )  { 
112+         // Test that SYSROOT is ignored if `--sysroot` is passed explicitly. 
113+         cmd. env ( "SYSROOT" ,  "/dummy/value/does/not/exist" ) ; 
114+         // We don't actually care about emitting lints, we only want to verify clippy doesn't give a hard 
115+         // error. 
116+         cmd. arg ( "-Awarnings" ) ; 
117+         let  output = cmd. output ( ) . expect ( "failed to run clippy" ) ; 
118+         let  stderr = String :: from_utf8_lossy ( & output. stderr ) ; 
119+         assert ! ( stderr. is_empty( ) ,  "clippy printed an error: {stderr}" ) ; 
120+         assert ! ( output. status. success( ) ,  "clippy exited with an error" ) ; 
121+     } 
122+ 
123+     let  rustc = std:: env:: var ( "RUSTC" ) . unwrap_or ( "rustc" . to_string ( ) ) ; 
124+     let  rustc_output = Command :: new ( rustc) 
125+         . args ( [ "--print" ,  "sysroot" ] ) 
126+         . output ( ) 
127+         . expect ( "unable to run rustc" ) ; 
128+     assert ! ( rustc_output. status. success( ) ) ; 
129+     let  sysroot = String :: from_utf8 ( rustc_output. stdout ) . unwrap ( ) ; 
130+     let  sysroot = sysroot. trim_end ( ) ; 
131+ 
132+     // This is a fairly small repo; we want to avoid checking out anything heavy twice, so just 
133+     // hard-code it. 
134+     let  repo_name = "rust-lang/log" ; 
135+     let  repo_dir = repo_dir ( repo_name) ; 
136+     // Pass the sysroot through RUSTFLAGS. 
137+     verify_cmd ( clippy_command ( & repo_dir,  & [ "--quiet" ] ) . env ( "RUSTFLAGS" ,  format ! ( "--sysroot={sysroot}" ) ) ) ; 
138+     // NOTE: we don't test passing the arguments directly to clippy-driver (with `-- --sysroot`) 
139+     // because it breaks for some reason. I (@jyn514) haven't taken time to track down the bug 
140+     // because rust-lang/rust uses RUSTFLAGS and nearly no one else uses --sysroot. 
141+ } 
0 commit comments