You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
aya/test/integration-test/src/tests/log.rs

153 lines
3.6 KiB
Rust

use std::{
borrow::Cow,
sync::{Arc, Mutex},
};
use aya::{programs::UProbe, Bpf};
use aya_log::BpfLogger;
use log::{Level, Log, Record};
use test_log::test;
#[no_mangle]
#[inline(never)]
pub extern "C" fn trigger_ebpf_program() {
core::hint::black_box(trigger_ebpf_program);
}
struct TestingLogger<F> {
log: F,
}
impl<F: Send + Sync + Fn(&Record)> Log for TestingLogger<F> {
fn enabled(&self, _metadata: &log::Metadata) -> bool {
true
}
fn flush(&self) {}
fn log(&self, record: &Record) {
let Self { log } = self;
log(record);
}
}
#[derive(Debug, PartialEq)]
struct CapturedLog<'a> {
pub body: Cow<'a, str>,
pub level: Level,
pub target: Cow<'a, str>,
}
#[test(tokio::test)]
async fn log() {
integration-test: build one binary instead of N "integration tests" as defined by Cargo produce a binary per file in the tests directory. This is really not what we want and has a number of downsides, but the main one is binary size. Before: tamird@pc:~/src/aya$ cargo xtask build-integration-test | xargs ls -lah Finished dev [unoptimized + debuginfo] target(s) in 0.05s Running `target/debug/xtask build-integration-test` Compiling integration-test v0.1.0 (/home/tamird/src/aya/test/integration-test) Finished dev [unoptimized + debuginfo] target(s) in 0.68s -rwxrwxr-x 1 tamird tamird 34M Jul 12 15:21 /home/tamird/src/aya/target/debug/deps/bpf_probe_read-e03eb905a5e6209c -rwxrwxr-x 1 tamird tamird 35M Jul 12 15:21 /home/tamird/src/aya/target/debug/deps/btf_relocations-57a4fbb38bf06064 -rwxrwxr-x 1 tamird tamird 31M Jul 12 15:21 /home/tamird/src/aya/target/debug/deps/elf-98b7a32d6d04effb -rwxrwxr-x 1 tamird tamird 6.9M Jul 12 15:21 /home/tamird/src/aya/target/debug/deps/integration_test-0dd55ce96bfdad77 -rwxrwxr-x 1 tamird tamird 34M Jul 12 15:21 /home/tamird/src/aya/target/debug/deps/load-0718562e85b86d03 -rwxrwxr-x 1 tamird tamird 40M Jul 12 15:21 /home/tamird/src/aya/target/debug/deps/log-dbf355f9ea34068a -rwxrwxr-x 1 tamird tamird 36M Jul 12 15:21 /home/tamird/src/aya/target/debug/deps/rbpf-89a1bb848fa5cc3c -rwxrwxr-x 1 tamird tamird 34M Jul 12 15:21 /home/tamird/src/aya/target/debug/deps/relocations-cfe655c3bb413d8b -rwxrwxr-x 1 tamird tamird 34M Jul 12 15:21 /home/tamird/src/aya/target/debug/deps/smoke-ccd3974180a3fd29 After: tamird@pc:~/src/aya$ cargo xtask build-integration-test | xargs ls -lah Finished dev [unoptimized + debuginfo] target(s) in 0.05s Running `target/debug/xtask build-integration-test` Compiling integration-test v0.1.0 (/home/tamird/src/aya/test/integration-test) Finished dev [unoptimized + debuginfo] target(s) in 0.90s -rwxrwxr-x 1 tamird tamird 47M Jul 12 15:21 /home/tamird/src/aya/target/debug/deps/integration_test-0dd55ce96bfdad77 Since we plan to run these tests in a VM, copying 10x fewer bytes seems like a win.
2 years ago
let mut bpf = Bpf::load(crate::LOG).unwrap();
let captured_logs = Arc::new(Mutex::new(Vec::new()));
{
let captured_logs = captured_logs.clone();
BpfLogger::init_with_logger(
&mut bpf,
TestingLogger {
log: move |record: &Record| {
let mut logs = captured_logs.lock().unwrap();
logs.push(CapturedLog {
body: format!("{}", record.args()).into(),
level: record.level(),
target: record.target().to_string().into(),
});
},
},
)
.unwrap();
}
let prog: &mut UProbe = bpf.program_mut("test_log").unwrap().try_into().unwrap();
prog.load().unwrap();
prog.attach(Some("trigger_ebpf_program"), 0, "/proc/self/exe", None)
.unwrap();
// Call the function that the uprobe is attached to, so it starts logging.
trigger_ebpf_program();
let mut logs = 0;
let records = loop {
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
let records = captured_logs.lock().unwrap();
let len = records.len();
if len == 0 {
continue;
}
if len == logs {
break records;
}
logs = len;
};
let mut records = records.iter();
assert_eq!(
records.next(),
Some(&CapturedLog {
body: "Hello from eBPF!".into(),
level: Level::Debug,
target: "log".into(),
}),
);
assert_eq!(
records.next(),
Some(&CapturedLog {
body: "69, 420, wao, 77616f".into(),
level: Level::Error,
target: "log".into(),
})
);
assert_eq!(
records.next(),
Some(&CapturedLog {
body: "ipv4: 10.0.0.1, ipv6: 2001:db8::1".into(),
level: Level::Info,
target: "log".into(),
})
);
assert_eq!(
records.next(),
Some(&CapturedLog {
body: "mac lc: 04:20:06:09:00:40, mac uc: 04:20:06:09:00:40".into(),
level: Level::Trace,
target: "log".into(),
})
);
assert_eq!(
records.next(),
Some(&CapturedLog {
body: "hex lc: 2f, hex uc: 2F".into(),
level: Level::Warn,
target: "log".into(),
})
);
assert_eq!(
records.next(),
Some(&CapturedLog {
body: "hex lc: deadbeef, hex uc: DEADBEEF".into(),
level: Level::Debug,
target: "log".into(),
})
);
assert_eq!(
records.next(),
Some(&CapturedLog {
body: "42 43 44 45".into(),
level: Level::Debug,
target: "log".into(),
})
);
assert_eq!(records.next(), None);
}