@@ -10,8 +10,9 @@ use cargo::{
1010use cargo_test_support:: paths:: { root, CargoPathExt } ;
1111use cargo_test_support:: registry:: Package ;
1212use cargo_test_support:: {
13- basic_bin_manifest, basic_lib_manifest, basic_manifest, git, is_nightly, lines_match_unordered,
14- main_file, paths, project, rustc_host, sleep_ms, symlink_supported, t, Execs , ProjectBuilder ,
13+ basic_bin_manifest, basic_lib_manifest, basic_manifest, cargo_exe, git, is_nightly,
14+ lines_match_unordered, main_file, paths, process, project, rustc_host, sleep_ms,
15+ symlink_supported, t, Execs , ProjectBuilder ,
1516} ;
1617use std:: env;
1718use std:: fs;
@@ -5256,6 +5257,85 @@ hello stderr!
52565257 lines_match_unordered ( "hello stdout!\n " , & stdout) . unwrap ( ) ;
52575258}
52585259
5260+ #[ cargo_test]
5261+ fn close_output_during_drain ( ) {
5262+ // Test to close the output during the build phase (drain_the_queue).
5263+ // There was a bug where it would hang.
5264+
5265+ // Server to know when rustc has spawned.
5266+ let listener = std:: net:: TcpListener :: bind ( "127.0.0.1:0" ) . unwrap ( ) ;
5267+ let addr = listener. local_addr ( ) . unwrap ( ) ;
5268+
5269+ // Create a wrapper so the test can know when compiling has started.
5270+ let rustc_wrapper = {
5271+ let p = project ( )
5272+ . at ( "compiler" )
5273+ . file ( "Cargo.toml" , & basic_manifest ( "compiler" , "1.0.0" ) )
5274+ . file (
5275+ "src/main.rs" ,
5276+ & r#"
5277+ use std::process::Command;
5278+ use std::env;
5279+ use std::io::Read;
5280+
5281+ fn main() {
5282+ // Only wait on the first dependency.
5283+ if matches!(env::var("CARGO_PKG_NAME").as_deref(), Ok("dep")) {
5284+ let mut socket = std::net::TcpStream::connect("__ADDR__").unwrap();
5285+ // Wait for the test to tell us to start printing.
5286+ let mut buf = [0];
5287+ drop(socket.read_exact(&mut buf));
5288+ }
5289+ let mut cmd = Command::new("rustc");
5290+ for arg in env::args_os().skip(1) {
5291+ cmd.arg(arg);
5292+ }
5293+ std::process::exit(cmd.status().unwrap().code().unwrap());
5294+ }
5295+ "#
5296+ . replace ( "__ADDR__" , & addr. to_string ( ) ) ,
5297+ )
5298+ . build ( ) ;
5299+ p. cargo ( "build" ) . run ( ) ;
5300+ p. bin ( "compiler" )
5301+ } ;
5302+
5303+ Package :: new ( "dep" , "1.0.0" ) . publish ( ) ;
5304+ let p = project ( )
5305+ . file (
5306+ "Cargo.toml" ,
5307+ r#"
5308+ [package]
5309+ name = "foo"
5310+ version = "0.1.0"
5311+
5312+ [dependencies]
5313+ dep = "1.0"
5314+ "# ,
5315+ )
5316+ . file ( "src/lib.rs" , "" )
5317+ . build ( ) ;
5318+
5319+ // Spawn cargo, wait for the first rustc to start, and then close stderr.
5320+ let mut cmd = process ( & cargo_exe ( ) )
5321+ . arg ( "check" )
5322+ . cwd ( p. root ( ) )
5323+ . env ( "RUSTC" , rustc_wrapper)
5324+ . build_command ( ) ;
5325+ cmd. stdout ( Stdio :: piped ( ) ) . stderr ( Stdio :: piped ( ) ) ;
5326+ let mut child = cmd. spawn ( ) . expect ( "cargo should spawn" ) ;
5327+ // Wait for the rustc wrapper to start.
5328+ let rustc_conn = listener. accept ( ) . unwrap ( ) . 0 ;
5329+ // Close stderr to force an error.
5330+ drop ( child. stderr . take ( ) ) ;
5331+ // Tell the wrapper to continue.
5332+ drop ( rustc_conn) ;
5333+ match child. wait ( ) {
5334+ Ok ( status) => assert ! ( !status. success( ) ) ,
5335+ Err ( e) => panic ! ( "child wait failed: {}" , e) ,
5336+ }
5337+ }
5338+
52595339use cargo_test_support:: registry:: Dependency ;
52605340
52615341#[ cargo_test]
0 commit comments