@@ -2136,6 +2136,145 @@ async fn add_remove_multiple_components() {
21362136 }
21372137}
21382138
2139+ #[ tokio:: test]
2140+ async fn remove_multiple_components_is_best_effort_and_order_independent ( ) {
2141+ let files = [
2142+ "lib/rustlib/src/rust-src/foo.rs" . to_owned ( ) ,
2143+ format ! ( "lib/rustlib/{}/analysis/libfoo.json" , this_host_triple( ) ) ,
2144+ ] ;
2145+
2146+ // Case 1: invalid component first
2147+ let cx = CliTestContext :: new ( Scenario :: SimpleV2 ) . await ;
2148+ cx. config
2149+ . expect ( & [ "rustup" , "default" , "nightly" ] )
2150+ . await
2151+ . is_ok ( ) ;
2152+ cx. config
2153+ . expect ( & [ "rustup" , "component" , "add" , "rust-src" , "rust-analysis" ] )
2154+ . await
2155+ . is_ok ( ) ;
2156+
2157+ for file in & files {
2158+ let path = format ! ( "toolchains/nightly-{}/{}" , this_host_triple( ) , file) ;
2159+ assert ! ( cx. config. rustupdir. has( & path) ) ;
2160+ }
2161+
2162+ cx. config
2163+ . expect ( & [
2164+ "rustup" ,
2165+ "component" ,
2166+ "remove" ,
2167+ "bad-component" ,
2168+ "rust-src" ,
2169+ "rust-analysis" ,
2170+ ] )
2171+ . await
2172+ . is_err ( ) ;
2173+
2174+ for file in & files {
2175+ let path = PathBuf :: from ( format ! (
2176+ "toolchains/nightly-{}/{}" ,
2177+ this_host_triple( ) ,
2178+ file
2179+ ) ) ;
2180+ assert ! ( !cx. config. rustupdir. has( path. parent( ) . unwrap( ) ) ) ;
2181+ }
2182+
2183+ // Case 2: invalid component last
2184+ let cx = CliTestContext :: new ( Scenario :: SimpleV2 ) . await ;
2185+ cx. config
2186+ . expect ( & [ "rustup" , "default" , "nightly" ] )
2187+ . await
2188+ . is_ok ( ) ;
2189+ cx. config
2190+ . expect ( & [ "rustup" , "component" , "add" , "rust-src" , "rust-analysis" ] )
2191+ . await
2192+ . is_ok ( ) ;
2193+
2194+ for file in & files {
2195+ let path = format ! ( "toolchains/nightly-{}/{}" , this_host_triple( ) , file) ;
2196+ assert ! ( cx. config. rustupdir. has( & path) ) ;
2197+ }
2198+
2199+ cx. config
2200+ . expect ( & [
2201+ "rustup" ,
2202+ "component" ,
2203+ "remove" ,
2204+ "rust-src" ,
2205+ "rust-analysis" ,
2206+ "bad-component" ,
2207+ ] )
2208+ . await
2209+ . is_err ( ) ;
2210+
2211+ for file in & files {
2212+ let path = PathBuf :: from ( format ! (
2213+ "toolchains/nightly-{}/{}" ,
2214+ this_host_triple( ) ,
2215+ file
2216+ ) ) ;
2217+ assert ! ( !cx. config. rustupdir. has( path. parent( ) . unwrap( ) ) ) ;
2218+ }
2219+ }
2220+
2221+ #[ tokio:: test]
2222+ async fn remove_multiple_components_reports_all_invalid_names ( ) {
2223+ let files = [
2224+ "lib/rustlib/src/rust-src/foo.rs" . to_owned ( ) ,
2225+ format ! ( "lib/rustlib/{}/analysis/libfoo.json" , this_host_triple( ) ) ,
2226+ ] ;
2227+
2228+ let cx = CliTestContext :: new ( Scenario :: SimpleV2 ) . await ;
2229+ cx. config
2230+ . expect ( [ "rustup" , "default" , "nightly" ] )
2231+ . await
2232+ . is_ok ( ) ;
2233+
2234+ cx. config
2235+ . expect ( [ "rustup" , "component" , "add" , "rust-src" , "rust-analysis" ] )
2236+ . await
2237+ . is_ok ( ) ;
2238+
2239+ // Ensure components exist
2240+ for file in & files {
2241+ let path = format ! ( "toolchains/nightly-{}/{}" , this_host_triple( ) , file) ;
2242+ assert ! ( cx. config. rustupdir. has( & path) ) ;
2243+ }
2244+
2245+ cx. config
2246+ . expect ( [
2247+ "rustup" ,
2248+ "component" ,
2249+ "remove" ,
2250+ "bad-component-1" ,
2251+ "rust-src" ,
2252+ "bad-component-2" ,
2253+ "rust-analysis" ,
2254+ ] )
2255+ . await
2256+ . with_stderr ( snapbox:: str![ [ r#"
2257+ info: removing component rust-src
2258+ info: removing component rust-analysis
2259+ error: toolchain 'nightly-[HOST_TRIPLE]' does not contain these components:
2260+ - 'bad-component-1'
2261+ - 'bad-component-2'
2262+
2263+
2264+ "# ] ] )
2265+ . is_err ( ) ;
2266+
2267+ // Ensure valid components were removed
2268+ for file in & files {
2269+ let path = PathBuf :: from ( format ! (
2270+ "toolchains/nightly-{}/{}" ,
2271+ this_host_triple( ) ,
2272+ file
2273+ ) ) ;
2274+ assert ! ( !cx. config. rustupdir. has( path. parent( ) . unwrap( ) ) ) ;
2275+ }
2276+ }
2277+
21392278#[ tokio:: test]
21402279async fn file_override ( ) {
21412280 let cx = CliTestContext :: new ( Scenario :: SimpleV2 ) . await ;
@@ -3889,7 +4028,7 @@ async fn custom_toolchain_with_components_toolchains_profile_does_not_err() {
38894028 . with_stderr ( snapbox:: str![ [ r#"
38904029info: syncing channel updates for nightly-[HOST_TRIPLE]
38914030info: latest update on 2015-01-02 for version 1.3.0 (hash-nightly-2)
3892- info: downloading 2 components
4031+ info: downloading component cargo
38934032info: default toolchain set to nightly-[HOST_TRIPLE]
38944033
38954034"# ] ] )
0 commit comments