瀏覽代碼

Merge pull request #639 from aya-rs/test-no-bpftool

Remove dependency on bpftool in integration tests
Tamir Duberstein 1 年之前
父節點
當前提交
e93e3c4

+ 4 - 2
aya/src/programs/mod.rs

@@ -999,12 +999,14 @@ impl Iterator for ProgramsIter {
                             io_error,
                         })
                         .and_then(|fd| {
-                            bpf_prog_get_info_by_fd(fd)
+                            let info = bpf_prog_get_info_by_fd(fd)
                                 .map_err(|io_error| ProgramError::SyscallError {
                                     call: "bpf_prog_get_info_by_fd".to_owned(),
                                     io_error,
                                 })
-                                .map(ProgramInfo)
+                                .map(ProgramInfo);
+                            unsafe { libc::close(fd) };
+                            info
                         }),
                 )
             }

+ 0 - 1
test/integration-test/Cargo.toml

@@ -14,7 +14,6 @@ env_logger = "0.10"
 futures-core = "0.3"
 inventory = "0.3"
 integration-test-macros = { path = "../integration-test-macros" }
-lazy_static = "1"
 libc = { version = "0.2.105" }
 log = "0.4"
 object = { version = "0.31", default-features = false, features = ["std", "read_core", "elf"] }

+ 3 - 13
test/integration-test/src/tests/load.rs

@@ -1,11 +1,11 @@
-use std::{convert::TryInto, process::Command, thread, time};
+use std::{convert::TryInto as _, thread, time};
 
 use aya::{
     include_bytes_aligned,
     maps::Array,
     programs::{
         links::{FdLink, PinnedLink},
-        KProbe, TracePoint, Xdp, XdpFlags,
+        loaded_programs, KProbe, TracePoint, Xdp, XdpFlags,
     },
     Bpf,
 };
@@ -58,20 +58,10 @@ fn multiple_btf_maps() {
     assert_eq!(val_2, 42);
 }
 
-fn is_loaded(name: &str) -> bool {
-    let output = Command::new("bpftool").args(["prog"]).output();
-    let output = match output {
-        Err(e) => panic!("Failed to run 'bpftool prog': {e}"),
-        Ok(out) => out,
-    };
-    let stdout = String::from_utf8(output.stdout).unwrap();
-    stdout.contains(name)
-}
-
 macro_rules! assert_loaded {
     ($name:literal, $loaded:expr) => {
         for i in 0..(MAX_RETRIES + 1) {
-            let state = is_loaded($name);
+            let state = loaded_programs().any(|prog| prog.unwrap().name() == $name.as_bytes());
             if state == $loaded {
                 break;
             }

+ 5 - 6
test/integration-test/src/tests/mod.rs

@@ -1,8 +1,7 @@
 use anyhow::bail;
-use lazy_static::lazy_static;
 use libc::{uname, utsname};
 use regex::Regex;
-use std::{ffi::CStr, mem};
+use std::{cell::OnceCell, ffi::CStr, mem};
 
 pub mod bpf_probe_read;
 pub mod btf_relocations;
@@ -22,15 +21,15 @@ pub struct IntegrationTest {
 }
 
 pub(crate) fn kernel_version() -> anyhow::Result<(u8, u8, u8)> {
-    lazy_static! {
-        static ref RE: Regex = Regex::new(r"^([0-9]+)\.([0-9]+)\.([0-9]+)").unwrap();
-    }
+    static mut RE: OnceCell<Regex> = OnceCell::new();
+    let re =
+        unsafe { &mut RE }.get_or_init(|| Regex::new(r"^([0-9]+)\.([0-9]+)\.([0-9]+)").unwrap());
     let mut data: utsname = unsafe { mem::zeroed() };
     let ret = unsafe { uname(&mut data) };
     assert!(ret >= 0, "libc::uname failed.");
     let release_cstr = unsafe { CStr::from_ptr(data.release.as_ptr()) };
     let release = release_cstr.to_string_lossy();
-    if let Some(caps) = RE.captures(&release) {
+    if let Some(caps) = re.captures(&release) {
         let major = caps.get(1).unwrap().as_str().parse().unwrap();
         let minor = caps.get(2).unwrap().as_str().parse().unwrap();
         let patch = caps.get(3).unwrap().as_str().parse().unwrap();

+ 1 - 1
test/run.sh

@@ -193,7 +193,7 @@ EOF
     exec_vm sudo dnf config-manager --set-enabled updates-testing
     exec_vm sudo dnf config-manager --set-enabled updates-testing-modular
     echo "Installing dependencies"
-    exec_vm sudo dnf install -qy bpftool llvm llvm-devel clang clang-devel zlib-devel
+    exec_vm sudo dnf install -qy llvm llvm-devel clang clang-devel zlib-devel
     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'

+ 0 - 1
xtask/Cargo.toml

@@ -12,5 +12,4 @@ syn = "2"
 quote = "1"
 proc-macro2 = "1"
 indoc = "2.0"
-lazy_static = "1"
 serde_json = "1"

+ 20 - 12
xtask/src/build_ebpf.rs

@@ -1,5 +1,8 @@
 use std::{
-    env, fs,
+    borrow::Cow,
+    env,
+    ffi::{OsStr, OsString},
+    fs,
     path::{Path, PathBuf},
     process::Command,
 };
@@ -7,7 +10,7 @@ use std::{
 use anyhow::{bail, Context};
 use clap::Parser;
 
-use crate::utils::WORKSPACE_ROOT;
+use crate::utils::workspace_root;
 
 #[derive(Debug, Copy, Clone)]
 pub enum Architecture {
@@ -52,7 +55,7 @@ pub fn build_ebpf(opts: BuildEbpfOptions) -> anyhow::Result<()> {
 }
 
 fn build_rust_ebpf(opts: &BuildEbpfOptions) -> anyhow::Result<()> {
-    let mut dir = PathBuf::from(WORKSPACE_ROOT.to_string());
+    let mut dir = PathBuf::from(workspace_root());
     dir.push("test/integration-ebpf");
 
     let target = format!("--target={}", opts.target);
@@ -77,9 +80,12 @@ fn build_rust_ebpf(opts: &BuildEbpfOptions) -> anyhow::Result<()> {
 fn get_libbpf_headers<P: AsRef<Path>>(libbpf_dir: P, include_path: P) -> anyhow::Result<()> {
     let dir = include_path.as_ref();
     fs::create_dir_all(dir)?;
+    let mut includedir = OsString::new();
+    includedir.push("INCLUDEDIR=");
+    includedir.push(dir.as_os_str());
     let status = Command::new("make")
         .current_dir(libbpf_dir.as_ref().join("src"))
-        .arg(format!("INCLUDEDIR={}", dir.as_os_str().to_string_lossy()))
+        .arg(includedir)
         .arg("install_headers")
         .status()
         .expect("failed to build get libbpf headers");
@@ -88,10 +94,10 @@ fn get_libbpf_headers<P: AsRef<Path>>(libbpf_dir: P, include_path: P) -> anyhow:
 }
 
 fn build_c_ebpf(opts: &BuildEbpfOptions) -> anyhow::Result<()> {
-    let mut src = PathBuf::from(WORKSPACE_ROOT.to_string());
+    let mut src = PathBuf::from(workspace_root());
     src.push("test/integration-ebpf/src/bpf");
 
-    let mut out_path = PathBuf::from(WORKSPACE_ROOT.to_string());
+    let mut out_path = PathBuf::from(workspace_root());
     out_path.push("target");
     out_path.push(opts.target.to_string());
     out_path.push("release");
@@ -119,17 +125,19 @@ fn compile_with_clang<P: Clone + AsRef<Path>>(
     out: P,
     include_path: P,
 ) -> anyhow::Result<()> {
-    let clang = match env::var("CLANG") {
-        Ok(val) => val,
-        Err(_) => String::from("/usr/bin/clang"),
+    let clang: Cow<'_, _> = match env::var_os("CLANG") {
+        Some(val) => val.into(),
+        None => OsStr::new("/usr/bin/clang").into(),
     };
-    let arch = match std::env::consts::ARCH {
+    let arch = match env::consts::ARCH {
         "x86_64" => "x86",
         "aarch64" => "arm64",
-        _ => std::env::consts::ARCH,
+        arch => arch,
     };
     let mut cmd = Command::new(clang);
-    cmd.arg(format!("-I{}", include_path.as_ref().to_string_lossy()))
+    cmd.arg("-v")
+        .arg("-I")
+        .arg(include_path.as_ref())
         .arg("-g")
         .arg("-O2")
         .arg("-target")

+ 7 - 2
xtask/src/run.rs

@@ -36,8 +36,13 @@ fn build(opts: &Options) -> Result<(), anyhow::Error> {
         .args(&args)
         .status()
         .expect("failed to build userspace");
-    assert!(status.success());
-    Ok(())
+    match status.code() {
+        Some(code) => match code {
+            0 => Ok(()),
+            code => Err(anyhow::anyhow!("exited with status code: {code}")),
+        },
+        None => Err(anyhow::anyhow!("process terminated by signal")),
+    }
 }
 
 /// Build and run the project

+ 12 - 14
xtask/src/utils.rs

@@ -1,17 +1,15 @@
-use lazy_static::lazy_static;
 use serde_json::Value;
-use std::process::Command;
+use std::{cell::OnceCell, process::Command};
 
-lazy_static! {
-    pub static ref WORKSPACE_ROOT: String = workspace_root();
-}
-
-fn workspace_root() -> String {
-    let output = Command::new("cargo").arg("metadata").output().unwrap();
-    if !output.status.success() {
-        panic!("unable to run cargo metadata")
-    }
-    let stdout = String::from_utf8(output.stdout).unwrap();
-    let v: Value = serde_json::from_str(&stdout).unwrap();
-    v["workspace_root"].as_str().unwrap().to_string()
+pub fn workspace_root() -> &'static str {
+    static mut WORKSPACE_ROOT: OnceCell<String> = OnceCell::new();
+    unsafe { &mut WORKSPACE_ROOT }.get_or_init(|| {
+        let output = Command::new("cargo").arg("metadata").output().unwrap();
+        if !output.status.success() {
+            panic!("unable to run cargo metadata")
+        }
+        let stdout = String::from_utf8(output.stdout).unwrap();
+        let v: Value = serde_json::from_str(&stdout).unwrap();
+        v["workspace_root"].as_str().unwrap().to_string()
+    })
 }