From 74fc50bf7e72476820b8565d00f79b6d642e5e08 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Mon, 17 Jul 2023 20:34:14 -0400 Subject: [PATCH] integration-test: shuttle stdio to user Trampoline cargo-in-cargo stdio through cargo:warning to ensure the user sees all the output. Use bpf-linker from git in CI so we can see what's going on there. --- .github/workflows/ci.yml | 2 +- test/integration-test/build.rs | 32 +++++++++++++++++++++++--------- test/run.sh | 2 +- xtask/src/run.rs | 33 ++++++++++++++++++--------------- 4 files changed, 43 insertions(+), 26 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 29abcea5..a0d8af6b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -120,7 +120,7 @@ jobs: - uses: Swatinem/rust-cache@v2 - name: Prereqs - run: cargo install bpf-linker + run: cargo install bpf-linker --git https://github.com/aya-rs/bpf-linker.git - uses: taiki-e/install-action@cargo-hack - name: Build diff --git a/test/integration-test/build.rs b/test/integration-test/build.rs index b1d9e7db..4a1fca14 100644 --- a/test/integration-test/build.rs +++ b/test/integration-test/build.rs @@ -1,9 +1,8 @@ use std::{ env, ffi::OsString, - fmt::Write as _, fs, - io::BufReader, + io::{BufRead as _, BufReader}, path::PathBuf, process::{Child, Command, Stdio}, }; @@ -134,14 +133,25 @@ fn main() { let mut child = cmd .stdout(Stdio::piped()) + .stderr(Stdio::piped()) .spawn() .unwrap_or_else(|err| panic!("failed to spawn {cmd:?}: {err}")); - let Child { stdout, .. } = &mut child; + let Child { stdout, stderr, .. } = &mut child; + + // Trampoline stdout to cargo warnings. + let stderr = stderr.take().unwrap(); + let stderr = BufReader::new(stderr); + let stderr = std::thread::spawn(move || { + for line in stderr.lines() { + let line = line.unwrap(); + println!("cargo:warning={line}"); + } + }); + let stdout = stdout.take().unwrap(); - let reader = BufReader::new(stdout); + let stdout = BufReader::new(stdout); let mut executables = Vec::new(); - let mut compiler_messages = String::new(); - for message in Message::parse_stream(reader) { + for message in Message::parse_stream(stdout) { #[allow(clippy::collapsible_match)] match message.expect("valid JSON") { Message::CompilerArtifact(Artifact { @@ -154,7 +164,10 @@ fn main() { } } Message::CompilerMessage(CompilerMessage { message, .. }) => { - writeln!(&mut compiler_messages, "{message}").unwrap() + println!("cargo:warning={message}"); + } + Message::TextLine(line) => { + println!("cargo:warning={line}"); } _ => {} } @@ -163,15 +176,16 @@ fn main() { let status = child .wait() .unwrap_or_else(|err| panic!("failed to wait for {cmd:?}: {err}")); - match status.code() { Some(code) => match code { 0 => {} - code => panic!("{cmd:?} exited with status code {code}:\n{compiler_messages}"), + code => panic!("{cmd:?} exited with status code {code}"), }, None => panic!("{cmd:?} terminated by signal"), } + stderr.join().map_err(std::panic::resume_unwind).unwrap(); + for (name, binary) in executables { let dst = out_dir.join(name); let _: u64 = fs::copy(&binary, &dst) diff --git a/test/run.sh b/test/run.sh index 4f4f285e..5ba3d211 100755 --- a/test/run.sh +++ b/test/run.sh @@ -196,7 +196,7 @@ EOF exec_vm 'curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- \ -y --profile minimal --default-toolchain nightly --component rust-src --component clippy' exec_vm 'echo source ~/.cargo/env >> ~/.bashrc' - exec_vm cargo install bpf-linker --no-default-features + exec_vm cargo install bpf-linker --git https://github.com/aya-rs/bpf-linker.git } scp_vm() { diff --git a/xtask/src/run.rs b/xtask/src/run.rs index 68f614a0..f5f41aef 100644 --- a/xtask/src/run.rs +++ b/xtask/src/run.rs @@ -2,10 +2,10 @@ use std::{ fmt::Write as _, io::BufReader, path::PathBuf, - process::{Command, Stdio}, + process::{Child, Command, Stdio}, }; -use anyhow::{Context as _, Result}; +use anyhow::{bail, Context as _, Result}; use cargo_metadata::{Artifact, CompilerMessage, Message, Target}; use clap::Parser; use xtask::AYA_BUILD_INTEGRATION_BPF; @@ -48,15 +48,17 @@ pub fn build(opts: BuildOptions) -> Result> { if let Some(target) = target { cmd.args(["--target", &target]); } - let mut cmd = cmd + + let mut child = cmd .stdout(Stdio::piped()) .spawn() .with_context(|| format!("failed to spawn {cmd:?}"))?; + let Child { stdout, .. } = &mut child; - let reader = BufReader::new(cmd.stdout.take().unwrap()); + let stdout = stdout.take().unwrap(); + let stdout = BufReader::new(stdout); let mut executables = Vec::new(); - let mut compiler_messages = String::new(); - for message in Message::parse_stream(reader) { + for message in Message::parse_stream(stdout) { #[allow(clippy::collapsible_match)] match message.context("valid JSON")? { Message::CompilerArtifact(Artifact { @@ -69,26 +71,27 @@ pub fn build(opts: BuildOptions) -> Result> { } } Message::CompilerMessage(CompilerMessage { message, .. }) => { - writeln!(&mut compiler_messages, "{message}").context("String write failed")? + println!("{message}"); + } + Message::TextLine(line) => { + println!("{line}"); } - _ => {} } } - let status = cmd + let status = child .wait() .with_context(|| format!("failed to wait for {cmd:?}"))?; - match status.code() { Some(code) => match code { - 0 => Ok(executables), - code => Err(anyhow::anyhow!( - "{cmd:?} exited with status code {code}:\n{compiler_messages}" - )), + 0 => {} + code => bail!("{cmd:?} exited with status code {code}"), }, - None => Err(anyhow::anyhow!("{cmd:?} terminated by signal")), + None => bail!("{cmd:?} terminated by signal"), } + + Ok(executables) } /// Build and run the project