11//! Tests for Cargo's behavior under Rustup.
22
3+ use std:: collections:: BTreeMap ;
34use std:: env;
45use std:: env:: consts:: EXE_EXTENSION ;
56use std:: ffi:: OsString ;
7+ use std:: fmt:: Write ;
68use std:: fs;
79use std:: path:: { Path , PathBuf } ;
810
@@ -88,62 +90,115 @@ fn real_rustc_wrapper(bin_dir: &Path, message: &str) -> PathBuf {
8890 )
8991}
9092
91- /// Creates a simulation of a rustup environment with `~/.cargo/bin` and
92- /// `~/.rustup` directories populated with some executables that simulate
93- /// rustup.
94- fn simulated_rustup_environment ( ) -> RustupEnvironment {
95- // Set up ~/.rustup/toolchains/test-toolchain/bin with a custom rustc and cargo.
96- let rustup_home = home ( ) . join ( ".rustup" ) ;
97- let toolchain_bin = rustup_home
98- . join ( "toolchains" )
99- . join ( "test-toolchain" )
100- . join ( "bin" ) ;
101- toolchain_bin. mkdir_p ( ) ;
102- let rustc_toolchain_exe = real_rustc_wrapper ( & toolchain_bin, "real rustc running" ) ;
103- let cargo_toolchain_exe = make_exe (
104- & toolchain_bin,
105- "cargo" ,
106- r#"panic!("cargo toolchain should not be called");"# ,
107- & [ ] ,
108- ) ;
93+ /// A builder for a simulated rustup environment.
94+ ///
95+ /// The environment has `~/.cargo/bin` and `~/.rustup` directories populated
96+ /// with some executables that simulate rustup.
97+ struct RustupEnvironmentBuilder {
98+ /// Whether the cargo proxy should call the cargo under test. By default,
99+ /// the proxy calls an executable that panics immediately.
100+ proxy_calls_cargo : bool ,
101+ /// Environment variable setup the proxy should perform.
102+ env : BTreeMap < String , String > ,
103+ }
109104
110- // Set up ~/.cargo/bin with a typical set of rustup proxies.
111- let cargo_bin = home ( ) . join ( ".cargo" ) . join ( "bin" ) ;
112- cargo_bin. mkdir_p ( ) ;
105+ impl RustupEnvironmentBuilder {
106+ /// Creates a new [`RustupEnvironmentBuilder`].
107+ fn new ( ) -> Self {
108+ Self {
109+ proxy_calls_cargo : false ,
110+ env : BTreeMap :: new ( ) ,
111+ }
112+ }
113113
114- let rustc_proxy = make_exe (
115- & cargo_bin,
116- "rustc" ,
117- & format ! (
118- r#"
119- match std::env::args().next().unwrap().as_ref() {{
120- "rustc" => {{}}
121- arg => panic!("proxy only supports rustc, got {{arg:?}}"),
122- }}
123- eprintln!("rustc proxy running");
124- let r = std::process::Command::new(env!("CARGO_RUSTUP_TEST_rustc_toolchain_exe"))
125- .args(std::env::args_os().skip(1))
126- .status();
127- std::process::exit(r.unwrap().code().unwrap_or(2));
114+ /// Call the cargo under test rather than an executable that panics
115+ /// immediately.
116+ pub fn call_cargo_under_test ( & mut self ) -> & mut Self {
117+ self . proxy_calls_cargo = true ;
118+ self
119+ }
120+
121+ /// (chainable) Sets an environment variable for the proxy.
122+ pub fn env < T : AsRef < str > > ( & mut self , key : & str , val : T ) -> & mut Self {
123+ self . env . insert ( key. to_string ( ) , val. as_ref ( ) . to_string ( ) ) ;
124+ self
125+ }
126+
127+ pub fn build ( & mut self ) -> RustupEnvironment {
128+ // Set up ~/.rustup/toolchains/test-toolchain/bin with a custom rustc and cargo.
129+ let rustup_home = home ( ) . join ( ".rustup" ) ;
130+ let toolchain_bin = rustup_home
131+ . join ( "toolchains" )
132+ . join ( "test-toolchain" )
133+ . join ( "bin" ) ;
134+ toolchain_bin. mkdir_p ( ) ;
135+ let rustc_toolchain_exe = real_rustc_wrapper ( & toolchain_bin, "real rustc running" ) ;
136+ let cargo_toolchain_exe = if self . proxy_calls_cargo {
137+ crate :: utils:: cargo_exe ( )
138+ } else {
139+ make_exe (
140+ & toolchain_bin,
141+ "cargo" ,
142+ r#"panic!("cargo toolchain should not be called");"# ,
143+ & [ ] ,
144+ )
145+ } ;
146+
147+ // Set up ~/.cargo/bin with a typical set of rustup proxies.
148+ let cargo_bin = home ( ) . join ( ".cargo" ) . join ( "bin" ) ;
149+ cargo_bin. mkdir_p ( ) ;
150+
151+ let mut env_setup = String :: new ( ) ;
152+ for ( k, v) in & self . env {
153+ write ! ( env_setup, ".env(\" {k}\" , \" {v}\" )" ) . unwrap ( ) ;
154+ }
155+
156+ let rustc_proxy = make_exe (
157+ & cargo_bin,
158+ "rustc" ,
159+ & format ! (
160+ r#"
161+ let file_stem = std::path::PathBuf::from(std::env::args().next().unwrap())
162+ .file_stem()
163+ .map(ToOwned::to_owned)
164+ .unwrap();
165+ let program = match file_stem.to_str().unwrap() {{
166+ "cargo" => env!("CARGO_RUSTUP_TEST_cargo_toolchain_exe"),
167+ "rustc" => env!("CARGO_RUSTUP_TEST_rustc_toolchain_exe"),
168+ arg => panic!("proxy only supports cargo and rustc, got {{arg:?}}"),
169+ }};
170+ eprintln!("`{{program}}` proxy running");
171+ let r = std::process::Command::new(program)
172+ .args(std::env::args_os().skip(1))
173+ {env_setup}
174+ .status();
175+ std::process::exit(r.unwrap().code().unwrap_or(2));
128176 "#
129- ) ,
130- & [ ( "CARGO_RUSTUP_TEST_rustc_toolchain_exe" , rustc_toolchain_exe) ] ,
131- ) ;
132- fs:: hard_link (
133- & rustc_proxy,
134- cargo_bin. join ( "cargo" ) . with_extension ( EXE_EXTENSION ) ,
135- )
136- . unwrap ( ) ;
137- fs:: hard_link (
138- & rustc_proxy,
139- cargo_bin. join ( "rustup" ) . with_extension ( EXE_EXTENSION ) ,
140- )
141- . unwrap ( ) ;
177+ ) ,
178+ & [
179+ ( "CARGO_RUSTUP_TEST_rustc_toolchain_exe" , rustc_toolchain_exe) ,
180+ (
181+ "CARGO_RUSTUP_TEST_cargo_toolchain_exe" ,
182+ cargo_toolchain_exe. clone ( ) ,
183+ ) ,
184+ ] ,
185+ ) ;
186+ fs:: hard_link (
187+ & rustc_proxy,
188+ cargo_bin. join ( "cargo" ) . with_extension ( EXE_EXTENSION ) ,
189+ )
190+ . unwrap ( ) ;
191+ fs:: hard_link (
192+ & rustc_proxy,
193+ cargo_bin. join ( "rustup" ) . with_extension ( EXE_EXTENSION ) ,
194+ )
195+ . unwrap ( ) ;
142196
143- RustupEnvironment {
144- cargo_bin,
145- rustup_home,
146- cargo_toolchain_exe,
197+ RustupEnvironment {
198+ cargo_bin,
199+ rustup_home,
200+ cargo_toolchain_exe,
201+ }
147202 }
148203}
149204
@@ -154,7 +209,7 @@ fn typical_rustup() {
154209 cargo_bin,
155210 rustup_home,
156211 cargo_toolchain_exe,
157- } = simulated_rustup_environment ( ) ;
212+ } = RustupEnvironmentBuilder :: new ( ) . build ( ) ;
158213
159214 // Set up a project and run a normal cargo build.
160215 let p = project ( ) . file ( "src/lib.rs" , "" ) . build ( ) ;
@@ -202,7 +257,7 @@ fn custom_calls_other_cargo() {
202257 cargo_bin,
203258 rustup_home,
204259 cargo_toolchain_exe : _,
205- } = simulated_rustup_environment ( ) ;
260+ } = RustupEnvironmentBuilder :: new ( ) . build ( ) ;
206261
207262 // Create a directory with a custom toolchain (outside of the rustup universe).
208263 let custom_bin = root ( ) . join ( "custom-bin" ) ;
0 commit comments