Browse Source

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.
Tamir Duberstein 1 year ago
parent
commit
74fc50bf7e
4 changed files with 43 additions and 26 deletions
  1. 1 1
      .github/workflows/ci.yml
  2. 23 9
      test/integration-test/build.rs
  3. 1 1
      test/run.sh
  4. 18 15
      xtask/src/run.rs

+ 1 - 1
.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

+ 23 - 9
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)

+ 1 - 1
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() {

+ 18 - 15
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<Vec<(String, PathBuf)>> {
     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<Vec<(String, PathBuf)>> {
                 }
             }
             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