Clippy over tests and integration-ebpf

Replace all `assert!(matches!(..))` with `assert_matches!(..)`.

Remove the now-unused build-integration-test xtask command whose logic
doesn't match that of the build-and-run command.
pull/648/head
Tamir Duberstein 1 year ago
parent 6e9aba55fe
commit e621a09181
No known key found for this signature in database

@ -26,13 +26,10 @@ jobs:
components: rustfmt, clippy, miri, rust-src components: rustfmt, clippy, miri, rust-src
- name: Check formatting - name: Check formatting
run: | run: cargo fmt --all -- --check
cargo fmt --all -- --check
- name: Run clippy - name: Run clippy
run: | run: cargo clippy --all-targets --workspace --exclude integration-test -- --deny warnings
cargo clippy --workspace --exclude integration-test -- --deny warnings
- name: Run miri - name: Run miri
run: | run: cargo miri test --all-targets
cargo miri test --all-targets

@ -102,7 +102,7 @@ impl Features {
} }
/// The loaded object file representation /// The loaded object file representation
#[derive(Clone)] #[derive(Clone, Debug)]
pub struct Object { pub struct Object {
/// The endianness /// The endianness
pub endianness: Endianness, pub endianness: Endianness,
@ -1537,66 +1537,57 @@ mod tests {
#[test] #[test]
fn test_parse_generic_error() { fn test_parse_generic_error() {
assert!(matches!( assert_matches!(Object::parse(&b"foo"[..]), Err(ParseError::ElfError(_)))
Object::parse(&b"foo"[..]),
Err(ParseError::ElfError(_))
))
} }
#[test] #[test]
fn test_parse_license() { fn test_parse_license() {
assert!(matches!( assert_matches!(parse_license(b""), Err(ParseError::InvalidLicense { .. }));
parse_license(b""),
Err(ParseError::InvalidLicense { .. })
));
assert!(matches!( assert_matches!(parse_license(b"\0"), Err(ParseError::InvalidLicense { .. }));
parse_license(b"\0"),
Err(ParseError::InvalidLicense { .. })
));
assert!(matches!( assert_matches!(
parse_license(b"GPL"), parse_license(b"GPL"),
Err(ParseError::MissingLicenseNullTerminator { .. }) Err(ParseError::MissingLicenseNullTerminator { .. })
)); );
assert_eq!(parse_license(b"GPL\0").unwrap().to_str().unwrap(), "GPL"); assert_eq!(parse_license(b"GPL\0").unwrap().to_str().unwrap(), "GPL");
} }
#[test] #[test]
fn test_parse_version() { fn test_parse_version() {
assert!(matches!( assert_matches!(
parse_version(b"", Endianness::Little), parse_version(b"", Endianness::Little),
Err(ParseError::InvalidKernelVersion { .. }) Err(ParseError::InvalidKernelVersion { .. })
)); );
assert!(matches!( assert_matches!(
parse_version(b"123", Endianness::Little), parse_version(b"123", Endianness::Little),
Err(ParseError::InvalidKernelVersion { .. }) Err(ParseError::InvalidKernelVersion { .. })
)); );
assert!(matches!( assert_matches!(
parse_version(&0xFFFF_FFFEu32.to_le_bytes(), Endianness::Little), parse_version(&0xFFFF_FFFEu32.to_le_bytes(), Endianness::Little),
Ok(None) Ok(None)
)); );
assert!(matches!( assert_matches!(
parse_version(&0xFFFF_FFFEu32.to_be_bytes(), Endianness::Big), parse_version(&0xFFFF_FFFEu32.to_be_bytes(), Endianness::Big),
Ok(None) Ok(None)
)); );
assert!(matches!( assert_matches!(
parse_version(&1234u32.to_le_bytes(), Endianness::Little), parse_version(&1234u32.to_le_bytes(), Endianness::Little),
Ok(Some(1234)) Ok(Some(1234))
)); );
} }
#[test] #[test]
fn test_parse_map_def_error() { fn test_parse_map_def_error() {
assert!(matches!( assert_matches!(
parse_map_def("foo", &[]), parse_map_def("foo", &[]),
Err(ParseError::InvalidMapDefinition { .. }) Err(ParseError::InvalidMapDefinition { .. })
)); );
} }
#[test] #[test]
@ -1652,7 +1643,7 @@ mod tests {
#[test] #[test]
fn test_parse_map_data() { fn test_parse_map_data() {
let map_data = b"map data"; let map_data = b"map data";
assert!(matches!( assert_matches!(
parse_data_map_section( parse_data_map_section(
&fake_section( &fake_section(
BpfSectionKind::Data, BpfSectionKind::Data,
@ -1675,7 +1666,7 @@ mod tests {
}, },
data, data,
})) if data == map_data && value_size == map_data.len() as u32 })) if data == map_data && value_size == map_data.len() as u32
)) )
} }
fn fake_obj() -> Object { fn fake_obj() -> Object {

@ -261,7 +261,7 @@ fn relocate_maps<'a, I: Iterator<Item = &'a Relocation>>(
debug_assert!(matches!( debug_assert!(matches!(
map.section_kind(), map.section_kind(),
BpfSectionKind::Bss | BpfSectionKind::Data | BpfSectionKind::Rodata BpfSectionKind::Bss | BpfSectionKind::Data | BpfSectionKind::Rodata
),); ));
m m
}; };
debug_assert_eq!(map.section_index(), section_index); debug_assert_eq!(map.section_index(), section_index);
@ -580,7 +580,7 @@ mod test {
let symbol_table = HashMap::from([(1, fake_sym(1, 0, 0, "test_map", 0))]); let symbol_table = HashMap::from([(1, fake_sym(1, 0, 0, "test_map", 0))]);
let relocations = vec![Relocation { let relocations = [Relocation {
offset: 0x0, offset: 0x0,
symbol_index: 1, symbol_index: 1,
size: 64, size: 64,
@ -625,7 +625,7 @@ mod test {
(2, fake_sym(2, 0, 0, "test_map_2", 0)), (2, fake_sym(2, 0, 0, "test_map_2", 0)),
]); ]);
let relocations = vec![ let relocations = [
Relocation { Relocation {
offset: 0x0, offset: 0x0,
symbol_index: 1, symbol_index: 1,
@ -675,7 +675,7 @@ mod test {
let symbol_table = HashMap::from([(1, fake_sym(1, 0, 0, "test_map", 0))]); let symbol_table = HashMap::from([(1, fake_sym(1, 0, 0, "test_map", 0))]);
let relocations = vec![Relocation { let relocations = [Relocation {
offset: 0x0, offset: 0x0,
symbol_index: 1, symbol_index: 1,
size: 64, size: 64,
@ -720,7 +720,7 @@ mod test {
(2, fake_sym(2, 0, 0, "test_map_2", 0)), (2, fake_sym(2, 0, 0, "test_map_2", 0)),
]); ]);
let relocations = vec![ let relocations = [
Relocation { Relocation {
offset: 0x0, offset: 0x0,
symbol_index: 1, symbol_index: 1,

@ -30,6 +30,7 @@ use crate::{
/// ``` /// ```
#[doc(alias = "BPF_MAP_TYPE_BLOOM_FILTER")] #[doc(alias = "BPF_MAP_TYPE_BLOOM_FILTER")]
#[derive(Debug)]
pub struct BloomFilter<T, V: Pod> { pub struct BloomFilter<T, V: Pod> {
inner: T, inner: T,
_v: PhantomData<V>, _v: PhantomData<V>,
@ -88,6 +89,7 @@ mod tests {
sys::{override_syscall, SysResult, Syscall}, sys::{override_syscall, SysResult, Syscall},
}; };
use libc::{EFAULT, ENOENT}; use libc::{EFAULT, ENOENT};
use matches::assert_matches;
use std::io; use std::io;
fn new_obj_map() -> obj::Map { fn new_obj_map() -> obj::Map {
@ -118,13 +120,13 @@ mod tests {
pinned: false, pinned: false,
btf_fd: None, btf_fd: None,
}; };
assert!(matches!( assert_matches!(
BloomFilter::<_, u16>::new(&map), BloomFilter::<_, u16>::new(&map),
Err(MapError::InvalidValueSize { Err(MapError::InvalidValueSize {
size: 2, size: 2,
expected: 4 expected: 4
}) })
)); );
} }
#[test] #[test]
@ -150,10 +152,10 @@ mod tests {
let map = Map::PerfEventArray(map_data); let map = Map::PerfEventArray(map_data);
assert!(matches!( assert_matches!(
BloomFilter::<_, u32>::try_from(&map), BloomFilter::<_, u32>::try_from(&map),
Err(MapError::InvalidMapType { .. }) Err(MapError::InvalidMapType { .. })
)); );
} }
#[test] #[test]
@ -165,10 +167,10 @@ mod tests {
btf_fd: None, btf_fd: None,
}; };
assert!(matches!( assert_matches!(
BloomFilter::<_, u32>::new(&mut map), BloomFilter::<_, u32>::new(&mut map),
Err(MapError::NotCreated { .. }) Err(MapError::NotCreated { .. })
)); );
} }
#[test] #[test]
@ -208,10 +210,10 @@ mod tests {
}; };
let bloom_filter = BloomFilter::<_, u32>::new(&mut map).unwrap(); let bloom_filter = BloomFilter::<_, u32>::new(&mut map).unwrap();
assert!(matches!( assert_matches!(
bloom_filter.insert(1, 0), bloom_filter.insert(1, 0),
Err(MapError::SyscallError { call, io_error }) if call == "bpf_map_push_elem" && io_error.raw_os_error() == Some(EFAULT) Err(MapError::SyscallError { call, io_error }) if call == "bpf_map_push_elem" && io_error.raw_os_error() == Some(EFAULT)
)); );
} }
#[test] #[test]
@ -246,10 +248,10 @@ mod tests {
}; };
let bloom_filter = BloomFilter::<_, u32>::new(&map).unwrap(); let bloom_filter = BloomFilter::<_, u32>::new(&map).unwrap();
assert!(matches!( assert_matches!(
bloom_filter.contains(&1, 0), bloom_filter.contains(&1, 0),
Err(MapError::SyscallError { call, io_error }) if call == "bpf_map_lookup_elem" && io_error.raw_os_error() == Some(EFAULT) Err(MapError::SyscallError { call, io_error }) if call == "bpf_map_lookup_elem" && io_error.raw_os_error() == Some(EFAULT)
)); );
} }
#[test] #[test]
@ -269,9 +271,6 @@ mod tests {
}; };
let bloom_filter = BloomFilter::<_, u32>::new(&map).unwrap(); let bloom_filter = BloomFilter::<_, u32>::new(&map).unwrap();
assert!(matches!( assert_matches!(bloom_filter.contains(&1, 0), Err(MapError::ElementNotFound));
bloom_filter.contains(&1, 0),
Err(MapError::ElementNotFound)
));
} }
} }

@ -108,6 +108,7 @@ mod tests {
use std::io; use std::io;
use libc::{EFAULT, ENOENT}; use libc::{EFAULT, ENOENT};
use matches::assert_matches;
use crate::{ use crate::{
bpf_map_def, bpf_map_def,
@ -150,13 +151,13 @@ mod tests {
pinned: false, pinned: false,
btf_fd: None, btf_fd: None,
}; };
assert!(matches!( assert_matches!(
HashMap::<_, u8, u32>::new(&map), HashMap::<_, u8, u32>::new(&map),
Err(MapError::InvalidKeySize { Err(MapError::InvalidKeySize {
size: 1, size: 1,
expected: 4 expected: 4
}) })
)); );
} }
#[test] #[test]
@ -167,13 +168,13 @@ mod tests {
pinned: false, pinned: false,
btf_fd: None, btf_fd: None,
}; };
assert!(matches!( assert_matches!(
HashMap::<_, u32, u16>::new(&map), HashMap::<_, u32, u16>::new(&map),
Err(MapError::InvalidValueSize { Err(MapError::InvalidValueSize {
size: 2, size: 2,
expected: 4 expected: 4
}) })
)); );
} }
#[test] #[test]
@ -186,10 +187,10 @@ mod tests {
}; };
let map = Map::Array(map_data); let map = Map::Array(map_data);
assert!(matches!( assert_matches!(
HashMap::<_, u8, u32>::try_from(&map), HashMap::<_, u8, u32>::try_from(&map),
Err(MapError::InvalidMapType { .. }) Err(MapError::InvalidMapType { .. })
)); );
} }
#[test] #[test]
@ -202,13 +203,13 @@ mod tests {
}; };
let map = Map::HashMap(map_data); let map = Map::HashMap(map_data);
assert!(matches!( assert_matches!(
HashMap::<_, u32, u16>::try_from(&map), HashMap::<_, u32, u16>::try_from(&map),
Err(MapError::InvalidValueSize { Err(MapError::InvalidValueSize {
size: 2, size: 2,
expected: 4 expected: 4
}) })
)); );
} }
#[test] #[test]
@ -220,10 +221,10 @@ mod tests {
btf_fd: None, btf_fd: None,
}; };
assert!(matches!( assert_matches!(
HashMap::<_, u32, u32>::new(&mut map), HashMap::<_, u32, u32>::new(&mut map),
Err(MapError::NotCreated { .. }) Err(MapError::NotCreated { .. })
)); );
} }
#[test] #[test]
@ -289,10 +290,10 @@ mod tests {
}; };
let mut hm = HashMap::<_, u32, u32>::new(&mut map).unwrap(); let mut hm = HashMap::<_, u32, u32>::new(&mut map).unwrap();
assert!(matches!( assert_matches!(
hm.insert(1, 42, 0), hm.insert(1, 42, 0),
Err(MapError::SyscallError { call, io_error }) if call == "bpf_map_update_elem" && io_error.raw_os_error() == Some(EFAULT) Err(MapError::SyscallError { call, io_error }) if call == "bpf_map_update_elem" && io_error.raw_os_error() == Some(EFAULT)
)); );
} }
#[test] #[test]
@ -349,10 +350,10 @@ mod tests {
}; };
let mut hm = HashMap::<_, u32, u32>::new(&mut map).unwrap(); let mut hm = HashMap::<_, u32, u32>::new(&mut map).unwrap();
assert!(matches!( assert_matches!(
hm.remove(&1), hm.remove(&1),
Err(MapError::SyscallError { call, io_error }) if call == "bpf_map_delete_elem" && io_error.raw_os_error() == Some(EFAULT) Err(MapError::SyscallError { call, io_error }) if call == "bpf_map_delete_elem" && io_error.raw_os_error() == Some(EFAULT)
)); );
} }
#[test] #[test]
@ -387,10 +388,10 @@ mod tests {
}; };
let hm = HashMap::<_, u32, u32>::new(&map).unwrap(); let hm = HashMap::<_, u32, u32>::new(&map).unwrap();
assert!(matches!( assert_matches!(
hm.get(&1, 0), hm.get(&1, 0),
Err(MapError::SyscallError { call, io_error }) if call == "bpf_map_lookup_elem" && io_error.raw_os_error() == Some(EFAULT) Err(MapError::SyscallError { call, io_error }) if call == "bpf_map_lookup_elem" && io_error.raw_os_error() == Some(EFAULT)
)); );
} }
#[test] #[test]
@ -410,7 +411,7 @@ mod tests {
}; };
let hm = HashMap::<_, u32, u32>::new(&map).unwrap(); let hm = HashMap::<_, u32, u32>::new(&map).unwrap();
assert!(matches!(hm.get(&1, 0), Err(MapError::KeyNotFound))); assert_matches!(hm.get(&1, 0), Err(MapError::KeyNotFound));
} }
fn bpf_key<T: Copy>(attr: &bpf_attr) -> Option<T> { fn bpf_key<T: Copy>(attr: &bpf_attr) -> Option<T> {
@ -447,7 +448,7 @@ mod tests {
}; };
let hm = HashMap::<_, u32, u32>::new(&map).unwrap(); let hm = HashMap::<_, u32, u32>::new(&map).unwrap();
let keys = hm.keys().collect::<Result<Vec<_>, _>>(); let keys = hm.keys().collect::<Result<Vec<_>, _>>();
assert!(matches!(keys, Ok(ks) if ks.is_empty())) assert_matches!(keys, Ok(ks) if ks.is_empty())
} }
fn get_next_key(attr: &bpf_attr) -> SysResult { fn get_next_key(attr: &bpf_attr) -> SysResult {
@ -530,13 +531,13 @@ mod tests {
let hm = HashMap::<_, u32, u32>::new(&map).unwrap(); let hm = HashMap::<_, u32, u32>::new(&map).unwrap();
let mut keys = hm.keys(); let mut keys = hm.keys();
assert!(matches!(keys.next(), Some(Ok(10)))); assert_matches!(keys.next(), Some(Ok(10)));
assert!(matches!(keys.next(), Some(Ok(20)))); assert_matches!(keys.next(), Some(Ok(20)));
assert!(matches!( assert_matches!(
keys.next(), keys.next(),
Some(Err(MapError::SyscallError { call, .. })) if call == "bpf_map_get_next_key" Some(Err(MapError::SyscallError { call, .. })) if call == "bpf_map_get_next_key"
)); );
assert!(matches!(keys.next(), None)); assert_matches!(keys.next(), None);
} }
#[test] #[test]
@ -642,13 +643,13 @@ mod tests {
let hm = HashMap::<_, u32, u32>::new(&map).unwrap(); let hm = HashMap::<_, u32, u32>::new(&map).unwrap();
let mut iter = hm.iter(); let mut iter = hm.iter();
assert!(matches!(iter.next(), Some(Ok((10, 100))))); assert_matches!(iter.next(), Some(Ok((10, 100))));
assert!(matches!(iter.next(), Some(Ok((20, 200))))); assert_matches!(iter.next(), Some(Ok((20, 200))));
assert!(matches!( assert_matches!(
iter.next(), iter.next(),
Some(Err(MapError::SyscallError { call, .. })) if call == "bpf_map_get_next_key" Some(Err(MapError::SyscallError { call, .. })) if call == "bpf_map_get_next_key"
)); );
assert!(matches!(iter.next(), None)); assert_matches!(iter.next(), None);
} }
#[test] #[test]
@ -687,12 +688,12 @@ mod tests {
let hm = HashMap::<_, u32, u32>::new(&map).unwrap(); let hm = HashMap::<_, u32, u32>::new(&map).unwrap();
let mut iter = hm.iter(); let mut iter = hm.iter();
assert!(matches!(iter.next(), Some(Ok((10, 100))))); assert_matches!(iter.next(), Some(Ok((10, 100))));
assert!(matches!( assert_matches!(
iter.next(), iter.next(),
Some(Err(MapError::SyscallError { call, .. })) if call == "bpf_map_lookup_elem" Some(Err(MapError::SyscallError { call, .. })) if call == "bpf_map_lookup_elem"
)); );
assert!(matches!(iter.next(), Some(Ok((30, 300))))); assert_matches!(iter.next(), Some(Ok((30, 300))));
assert!(matches!(iter.next(), None)); assert_matches!(iter.next(), None);
} }
} }

@ -45,6 +45,7 @@ use crate::{
/// ``` /// ```
#[doc(alias = "BPF_MAP_TYPE_LPM_TRIE")] #[doc(alias = "BPF_MAP_TYPE_LPM_TRIE")]
#[derive(Debug)]
pub struct LpmTrie<T, K, V> { pub struct LpmTrie<T, K, V> {
inner: T, inner: T,
_k: PhantomData<K>, _k: PhantomData<K>,
@ -207,6 +208,7 @@ mod tests {
sys::{override_syscall, SysResult, Syscall}, sys::{override_syscall, SysResult, Syscall},
}; };
use libc::{EFAULT, ENOENT}; use libc::{EFAULT, ENOENT};
use matches::assert_matches;
use std::{io, mem, net::Ipv4Addr}; use std::{io, mem, net::Ipv4Addr};
fn new_obj_map() -> obj::Map { fn new_obj_map() -> obj::Map {
@ -237,13 +239,13 @@ mod tests {
pinned: false, pinned: false,
btf_fd: None, btf_fd: None,
}; };
assert!(matches!( assert_matches!(
LpmTrie::<_, u16, u32>::new(&map), LpmTrie::<_, u16, u32>::new(&map),
Err(MapError::InvalidKeySize { Err(MapError::InvalidKeySize {
size: 6, size: 6,
expected: 8 // four bytes for prefixlen and four bytes for data. expected: 8 // four bytes for prefixlen and four bytes for data.
}) })
)); );
} }
#[test] #[test]
@ -254,13 +256,13 @@ mod tests {
pinned: false, pinned: false,
btf_fd: None, btf_fd: None,
}; };
assert!(matches!( assert_matches!(
LpmTrie::<_, u32, u16>::new(&map), LpmTrie::<_, u32, u16>::new(&map),
Err(MapError::InvalidValueSize { Err(MapError::InvalidValueSize {
size: 2, size: 2,
expected: 4 expected: 4
}) })
)); );
} }
#[test] #[test]
@ -286,10 +288,10 @@ mod tests {
let map = Map::PerfEventArray(map_data); let map = Map::PerfEventArray(map_data);
assert!(matches!( assert_matches!(
LpmTrie::<_, u32, u32>::try_from(&map), LpmTrie::<_, u32, u32>::try_from(&map),
Err(MapError::InvalidMapType { .. }) Err(MapError::InvalidMapType { .. })
)); );
} }
#[test] #[test]
@ -301,10 +303,10 @@ mod tests {
btf_fd: None, btf_fd: None,
}; };
assert!(matches!( assert_matches!(
LpmTrie::<_, u32, u32>::new(&mut map), LpmTrie::<_, u32, u32>::new(&mut map),
Err(MapError::NotCreated { .. }) Err(MapError::NotCreated { .. })
)); );
} }
#[test] #[test]
@ -345,10 +347,10 @@ mod tests {
let mut trie = LpmTrie::<_, u32, u32>::new(&mut map).unwrap(); let mut trie = LpmTrie::<_, u32, u32>::new(&mut map).unwrap();
let ipaddr = Ipv4Addr::new(8, 8, 8, 8); let ipaddr = Ipv4Addr::new(8, 8, 8, 8);
let key = Key::new(16, u32::from(ipaddr).to_be()); let key = Key::new(16, u32::from(ipaddr).to_be());
assert!(matches!( assert_matches!(
trie.insert(&key, 1, 0), trie.insert(&key, 1, 0),
Err(MapError::SyscallError { call, io_error }) if call == "bpf_map_update_elem" && io_error.raw_os_error() == Some(EFAULT) Err(MapError::SyscallError { call, io_error }) if call == "bpf_map_update_elem" && io_error.raw_os_error() == Some(EFAULT)
)); );
} }
#[test] #[test]
@ -387,10 +389,10 @@ mod tests {
let mut trie = LpmTrie::<_, u32, u32>::new(&mut map).unwrap(); let mut trie = LpmTrie::<_, u32, u32>::new(&mut map).unwrap();
let ipaddr = Ipv4Addr::new(8, 8, 8, 8); let ipaddr = Ipv4Addr::new(8, 8, 8, 8);
let key = Key::new(16, u32::from(ipaddr).to_be()); let key = Key::new(16, u32::from(ipaddr).to_be());
assert!(matches!( assert_matches!(
trie.remove(&key), trie.remove(&key),
Err(MapError::SyscallError { call, io_error }) if call == "bpf_map_delete_elem" && io_error.raw_os_error() == Some(EFAULT) Err(MapError::SyscallError { call, io_error }) if call == "bpf_map_delete_elem" && io_error.raw_os_error() == Some(EFAULT)
)); );
} }
#[test] #[test]
@ -428,10 +430,10 @@ mod tests {
let ipaddr = Ipv4Addr::new(8, 8, 8, 8); let ipaddr = Ipv4Addr::new(8, 8, 8, 8);
let key = Key::new(16, u32::from(ipaddr).to_be()); let key = Key::new(16, u32::from(ipaddr).to_be());
assert!(matches!( assert_matches!(
trie.get(&key, 0), trie.get(&key, 0),
Err(MapError::SyscallError { call, io_error }) if call == "bpf_map_lookup_elem" && io_error.raw_os_error() == Some(EFAULT) Err(MapError::SyscallError { call, io_error }) if call == "bpf_map_lookup_elem" && io_error.raw_os_error() == Some(EFAULT)
)); );
} }
#[test] #[test]
@ -453,6 +455,6 @@ mod tests {
let ipaddr = Ipv4Addr::new(8, 8, 8, 8); let ipaddr = Ipv4Addr::new(8, 8, 8, 8);
let key = Key::new(16, u32::from(ipaddr).to_be()); let key = Key::new(16, u32::from(ipaddr).to_be());
assert!(matches!(trie.get(&key, 0), Err(MapError::KeyNotFound))); assert_matches!(trie.get(&key, 0), Err(MapError::KeyNotFound));
} }
} }

@ -833,6 +833,7 @@ impl<T: Pod> Deref for PerCpuValues<T> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use libc::EFAULT; use libc::EFAULT;
use matches::assert_matches;
use crate::{ use crate::{
bpf_map_def, bpf_map_def,
@ -880,12 +881,9 @@ mod tests {
}); });
let mut map = new_map(); let mut map = new_map();
assert!(matches!(map.create("foo"), Ok(42))); assert_matches!(map.create("foo"), Ok(42));
assert_eq!(map.fd, Some(42)); assert_eq!(map.fd, Some(42));
assert!(matches!( assert_matches!(map.create("foo"), Err(MapError::AlreadyCreated { .. }));
map.create("foo"),
Err(MapError::AlreadyCreated { .. })
));
} }
#[test] #[test]
@ -894,7 +892,7 @@ mod tests {
let mut map = new_map(); let mut map = new_map();
let ret = map.create("foo"); let ret = map.create("foo");
assert!(matches!(ret, Err(MapError::CreateError { .. }))); assert_matches!(ret, Err(MapError::CreateError { .. }));
if let Err(MapError::CreateError { if let Err(MapError::CreateError {
name, name,
code, code,

@ -83,6 +83,7 @@ pub struct Events {
pub lost: usize, pub lost: usize,
} }
#[derive(Debug)]
pub(crate) struct PerfBuffer { pub(crate) struct PerfBuffer {
buf: AtomicPtr<perf_event_mmap_page>, buf: AtomicPtr<perf_event_mmap_page>,
size: usize, size: usize,
@ -318,6 +319,7 @@ mod tests {
generated::perf_event_mmap_page, generated::perf_event_mmap_page,
sys::{override_syscall, Syscall, TEST_MMAP_RET}, sys::{override_syscall, Syscall, TEST_MMAP_RET},
}; };
use matches::assert_matches;
use std::{fmt::Debug, mem}; use std::{fmt::Debug, mem};
const PAGE_SIZE: usize = 4096; const PAGE_SIZE: usize = 4096;
@ -336,18 +338,18 @@ mod tests {
#[test] #[test]
fn test_invalid_page_count() { fn test_invalid_page_count() {
assert!(matches!( assert_matches!(
PerfBuffer::open(1, PAGE_SIZE, 0), PerfBuffer::open(1, PAGE_SIZE, 0),
Err(PerfBufferError::InvalidPageCount { .. }) Err(PerfBufferError::InvalidPageCount { .. })
)); );
assert!(matches!( assert_matches!(
PerfBuffer::open(1, PAGE_SIZE, 3), PerfBuffer::open(1, PAGE_SIZE, 3),
Err(PerfBufferError::InvalidPageCount { .. }) Err(PerfBufferError::InvalidPageCount { .. })
)); );
assert!(matches!( assert_matches!(
PerfBuffer::open(1, PAGE_SIZE, 5), PerfBuffer::open(1, PAGE_SIZE, 5),
Err(PerfBufferError::InvalidPageCount { .. }) Err(PerfBufferError::InvalidPageCount { .. })
)); );
} }
#[test] #[test]
@ -359,10 +361,7 @@ mod tests {
fake_mmap(&mut mmapped_buf); fake_mmap(&mut mmapped_buf);
let mut buf = PerfBuffer::open(1, PAGE_SIZE, 1).unwrap(); let mut buf = PerfBuffer::open(1, PAGE_SIZE, 1).unwrap();
assert!(matches!( assert_matches!(buf.read_events(&mut []), Err(PerfBufferError::NoBuffers))
buf.read_events(&mut []),
Err(PerfBufferError::NoBuffers)
))
} }
#[test] #[test]

@ -329,6 +329,7 @@ pub enum LinkError {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use matches::assert_matches;
use std::{cell::RefCell, env, fs::File, mem, os::unix::io::AsRawFd, rc::Rc}; use std::{cell::RefCell, env, fs::File, mem, os::unix::io::AsRawFd, rc::Rc};
use crate::{programs::ProgramError, sys::override_syscall}; use crate::{programs::ProgramError, sys::override_syscall};
@ -394,10 +395,10 @@ mod tests {
let mut links = LinkMap::new(); let mut links = LinkMap::new();
links.insert(TestLink::new(1, 2)).unwrap(); links.insert(TestLink::new(1, 2)).unwrap();
assert!(matches!( assert_matches!(
links.insert(TestLink::new(1, 2)), links.insert(TestLink::new(1, 2)),
Err(ProgramError::AlreadyAttached) Err(ProgramError::AlreadyAttached)
)); );
} }
#[test] #[test]
@ -409,10 +410,7 @@ mod tests {
let l1_id2 = l1.id(); let l1_id2 = l1.id();
links.insert(TestLink::new(1, 2)).unwrap(); links.insert(TestLink::new(1, 2)).unwrap();
links.remove(l1_id1).unwrap(); links.remove(l1_id1).unwrap();
assert!(matches!( assert_matches!(links.remove(l1_id2), Err(ProgramError::NotAttached));
links.remove(l1_id2),
Err(ProgramError::NotAttached)
));
} }
#[test] #[test]

@ -438,7 +438,9 @@ fn read_str_bytes(len: i64, dest: &mut [u8]) -> Result<&[u8], c_long> {
// len includes the NULL terminator but not for b"\0" for which the kernel // len includes the NULL terminator but not for b"\0" for which the kernel
// returns len=0. So we do a saturating sub and for b"\0" we return the // returns len=0. So we do a saturating sub and for b"\0" we return the
// empty slice, for all other cases we omit the terminator. // empty slice, for all other cases we omit the terminator.
Ok(&dest[..(len as usize).saturating_sub(1)]) let len = usize::try_from(len).map_err(|core::num::TryFromIntError { .. }| -1)?;
let len = len.saturating_sub(1);
dest.get(..len).ok_or(-1)
} }
/// Read a null-terminated string from _kernel space_ stored at `src` into `dest`. /// Read a null-terminated string from _kernel space_ stored at `src` into `dest`.

@ -12,14 +12,15 @@ const RESULT_BUF_LEN: usize = 1024;
macro_rules! read_str_bytes { macro_rules! read_str_bytes {
($fun:ident, $ptr:expr, $len:expr $(,)?) => { ($fun:ident, $ptr:expr, $len:expr $(,)?) => {
let r = unsafe {
let Some(ptr) = RESULT.get_ptr_mut(0) else { let Some(ptr) = RESULT.get_ptr_mut(0) else {
return; return;
}; };
&mut *ptr let TestResult {
}; did_error,
len,
buf,
} = unsafe { &mut *ptr };
let s = unsafe {
// $len comes from ctx.arg(1) so it's dynamic and the verifier // $len comes from ctx.arg(1) so it's dynamic and the verifier
// doesn't see any bounds. We do $len.min(RESULT_BUF_LEN) here to // doesn't see any bounds. We do $len.min(RESULT_BUF_LEN) here to
// ensure that the verifier can see the upper bound, or you get: // ensure that the verifier can see the upper bound, or you get:
@ -30,15 +31,18 @@ macro_rules! read_str_bytes {
// R2_w=scalar(id=2,umax=9223372036854775807,var_off=(0x0; 0x7fffffffffffffff)) [snip] // R2_w=scalar(id=2,umax=9223372036854775807,var_off=(0x0; 0x7fffffffffffffff)) [snip]
// 28: (85) call bpf_probe_read_user_str#114 // 28: (85) call bpf_probe_read_user_str#114
// R2 unbounded memory access, use 'var &= const' or 'if (var < const)' // R2 unbounded memory access, use 'var &= const' or 'if (var < const)'
match $fun($ptr, &mut r.buf[..$len.min(RESULT_BUF_LEN)]) { let Some(buf) = buf.get_mut(..$len) else {
Ok(s) => s,
Err(_) => {
r.did_error = 1;
return; return;
};
match unsafe { $fun($ptr, buf) } {
Ok(s) => {
*len = s.len();
}
Err(_) => {
*did_error = 1;
} }
} }
};
r.len = s.len();
}; };
} }
@ -53,7 +57,7 @@ struct TestResult {
static RESULT: Array<TestResult> = Array::with_max_entries(1, 0); static RESULT: Array<TestResult> = Array::with_max_entries(1, 0);
#[map] #[map]
static KERNEL_BUFFER: Array<[u8; 1024]> = Array::with_max_entries(1, 0); static KERNEL_BUFFER: Array<[u8; RESULT_BUF_LEN]> = Array::with_max_entries(1, 0);
#[uprobe] #[uprobe]
pub fn test_bpf_probe_read_user_str_bytes(ctx: ProbeContext) { pub fn test_bpf_probe_read_user_str_bytes(ctx: ProbeContext) {
@ -85,7 +89,8 @@ pub fn test_bpf_probe_read_kernel_str_bytes(ctx: ProbeContext) {
); );
} }
#[cfg(not(test))]
#[panic_handler] #[panic_handler]
fn panic(_info: &core::panic::PanicInfo) -> ! { fn panic(_info: &core::panic::PanicInfo) -> ! {
unsafe { core::hint::unreachable_unchecked() } loop {}
} }

@ -36,7 +36,8 @@ pub fn test_log(ctx: ProbeContext) {
} }
} }
#[cfg(not(test))]
#[panic_handler] #[panic_handler]
fn panic(_info: &core::panic::PanicInfo) -> ! { fn panic(_info: &core::panic::PanicInfo) -> ! {
unsafe { core::hint::unreachable_unchecked() } loop {}
} }

@ -26,7 +26,8 @@ unsafe fn try_pass(_ctx: XdpContext) -> Result<u32, u32> {
Ok(xdp_action::XDP_PASS) Ok(xdp_action::XDP_PASS)
} }
#[cfg(not(test))]
#[panic_handler] #[panic_handler]
fn panic(_info: &core::panic::PanicInfo) -> ! { fn panic(_info: &core::panic::PanicInfo) -> ! {
unsafe { core::hint::unreachable_unchecked() } loop {}
} }

@ -15,7 +15,8 @@ unsafe fn try_pass(_ctx: XdpContext) -> Result<u32, u32> {
Ok(xdp_action::XDP_PASS) Ok(xdp_action::XDP_PASS)
} }
#[cfg(not(test))]
#[panic_handler] #[panic_handler]
fn panic(_info: &core::panic::PanicInfo) -> ! { fn panic(_info: &core::panic::PanicInfo) -> ! {
unsafe { core::hint::unreachable_unchecked() } loop {}
} }

@ -17,7 +17,8 @@ unsafe fn try_pass(_ctx: XdpContext) -> Result<u32, u32> {
Ok(xdp_action::XDP_PASS) Ok(xdp_action::XDP_PASS)
} }
#[cfg(not(test))]
#[panic_handler] #[panic_handler]
fn panic(_info: &core::panic::PanicInfo) -> ! { fn panic(_info: &core::panic::PanicInfo) -> ! {
unsafe { core::hint::unreachable_unchecked() } loop {}
} }

@ -39,7 +39,8 @@ fn set_result_backward(index: u32, value: u64) {
set_result(index, value); set_result(index, value);
} }
#[cfg(not(test))]
#[panic_handler] #[panic_handler]
fn panic(_info: &core::panic::PanicInfo) -> ! { fn panic(_info: &core::panic::PanicInfo) -> ! {
unsafe { core::hint::unreachable_unchecked() } loop {}
} }

@ -25,7 +25,8 @@ pub fn test_unload_kpr(_ctx: ProbeContext) -> u32 {
0 0
} }
#[cfg(not(test))]
#[panic_handler] #[panic_handler]
fn panic(_info: &core::panic::PanicInfo) -> ! { fn panic(_info: &core::panic::PanicInfo) -> ! {
unsafe { core::hint::unreachable_unchecked() } loop {}
} }

@ -11,7 +11,12 @@ aya-log = { path = "../../aya-log" }
aya-obj = { path = "../../aya-obj" } aya-obj = { path = "../../aya-obj" }
libc = { version = "0.2.105" } libc = { version = "0.2.105" }
log = "0.4" log = "0.4"
object = { version = "0.31", default-features = false, features = ["std", "read_core", "elf"] } matches = "0.1.8"
object = { version = "0.31", default-features = false, features = [
"std",
"read_core",
"elf",
] }
rbpf = "0.2.0" rbpf = "0.2.0"
tempfile = "3.3.0" tempfile = "3.3.0"
tokio = { version = "1.24", features = ["rt", "rt-multi-thread", "sync", "time"] } tokio = { version = "1.24", default-features = false, features = ["time"] }

@ -1,11 +1,4 @@
use std::process::exit; use aya::{include_bytes_aligned, maps::Array, programs::UProbe, Bpf};
use aya::{
include_bytes_aligned,
maps::Array,
programs::{ProgramError, UProbe},
Bpf,
};
const RESULT_BUF_LEN: usize = 1024; const RESULT_BUF_LEN: usize = 1024;
@ -113,16 +106,7 @@ fn load_and_attach_uprobe(prog_name: &str, func_name: &str, bytes: &[u8]) -> Bpf
let mut bpf = Bpf::load(bytes).unwrap(); let mut bpf = Bpf::load(bytes).unwrap();
let prog: &mut UProbe = bpf.program_mut(prog_name).unwrap().try_into().unwrap(); let prog: &mut UProbe = bpf.program_mut(prog_name).unwrap().try_into().unwrap();
if let Err(ProgramError::LoadError { prog.load().unwrap();
io_error,
verifier_log,
}) = prog.load()
{
println!(
"Failed to load program `{prog_name}`: {io_error}. Verifier log:\n{verifier_log:#}"
);
exit(1);
};
prog.attach(Some(func_name), 0, "/proc/self/exe", None) prog.attach(Some(func_name), 0, "/proc/self/exe", None)
.unwrap(); .unwrap();

@ -10,10 +10,7 @@ fn run_with_rbpf() {
let object = Object::parse(bytes).unwrap(); let object = Object::parse(bytes).unwrap();
assert_eq!(object.programs.len(), 1); assert_eq!(object.programs.len(), 1);
assert!(matches!( matches::assert_matches!(object.programs["pass"].section, ProgramSection::Xdp { .. });
object.programs["pass"].section,
ProgramSection::Xdp { .. }
));
assert_eq!(object.programs["pass"].section.name(), "pass"); assert_eq!(object.programs["pass"].section.name(), "pass");
let instructions = &object let instructions = &object
@ -42,10 +39,10 @@ fn use_map_with_rbpf() {
let mut object = Object::parse(bytes).unwrap(); let mut object = Object::parse(bytes).unwrap();
assert_eq!(object.programs.len(), 1); assert_eq!(object.programs.len(), 1);
assert!(matches!( matches::assert_matches!(
object.programs["tracepoint"].section, object.programs["tracepoint"].section,
ProgramSection::TracePoint { .. } ProgramSection::TracePoint { .. }
)); );
assert_eq!(object.programs["tracepoint"].section.name(), "tracepoint"); assert_eq!(object.programs["tracepoint"].section.name(), "tracepoint");
// Initialize maps: // Initialize maps:

@ -1,10 +1,6 @@
use std::{process::exit, time::Duration}; use std::time::Duration;
use aya::{ use aya::{include_bytes_aligned, programs::UProbe, Bpf};
include_bytes_aligned,
programs::{ProgramError, UProbe},
Bpf,
};
#[test] #[test]
fn relocations() { fn relocations() {
@ -44,14 +40,7 @@ fn load_and_attach(name: &str, bytes: &[u8]) -> Bpf {
let mut bpf = Bpf::load(bytes).unwrap(); let mut bpf = Bpf::load(bytes).unwrap();
let prog: &mut UProbe = bpf.program_mut(name).unwrap().try_into().unwrap(); let prog: &mut UProbe = bpf.program_mut(name).unwrap().try_into().unwrap();
if let Err(ProgramError::LoadError { prog.load().unwrap();
io_error,
verifier_log,
}) = prog.load()
{
println!("Failed to load program `{name}`: {io_error}. Verifier log:\n{verifier_log:#}");
exit(1);
};
prog.attach( prog.attach(
Some("trigger_relocations_program"), Some("trigger_relocations_program"),

@ -249,9 +249,9 @@ exec_vm "rm -rf aya/* libbpf"
rsync_vm "--exclude=target --exclude=.tmp $AYA_SOURCE_DIR" rsync_vm "--exclude=target --exclude=.tmp $AYA_SOURCE_DIR"
rsync_vm "$LIBBPF_DIR" rsync_vm "$LIBBPF_DIR"
# need to build or linting will fail trying to include object files # need to build or linting will fail trying to include object files; don't run the tests though.
exec_vm "cd aya; cargo xtask build-integration-test --libbpf-dir ~/libbpf" exec_vm "cd aya; cargo xtask integration-test --libbpf-dir ~/libbpf -- filter-that-matches-nothing"
exec_vm "cd aya; cargo clippy -p integration-test -- --deny warnings" exec_vm "cd aya; cargo clippy --all-targets -p integration-test -- --deny warnings"
exec_vm "cd aya; cargo xtask integration-test --libbpf-dir ~/libbpf" exec_vm "cd aya; cargo xtask integration-test --libbpf-dir ~/libbpf"
# we rm and sync but it doesn't seem to work reliably - I guess we could sleep a # we rm and sync but it doesn't seem to work reliably - I guess we could sleep a

@ -1,32 +0,0 @@
use anyhow::Result;
use clap::Parser;
use std::process::Command;
use crate::{build_ebpf, utils::exec};
#[derive(Parser)]
pub struct Options {
/// Target triple for which the code is compiled
#[clap(long)]
pub musl_target: Option<String>,
#[clap(flatten)]
pub ebpf_options: build_ebpf::BuildEbpfOptions,
}
pub fn build_test(opts: Options) -> Result<()> {
let Options {
musl_target,
ebpf_options,
} = opts;
build_ebpf::build_ebpf(ebpf_options)?;
let mut cmd = Command::new("cargo");
cmd.args(["build", "-p", "integration-test"]);
if let Some(target) = musl_target {
cmd.args(["--target", &target]);
}
exec(&mut cmd)
}

@ -1,5 +1,4 @@
mod build_ebpf; mod build_ebpf;
mod build_test;
mod codegen; mod codegen;
mod docs; mod docs;
mod run; mod run;
@ -18,8 +17,6 @@ pub struct XtaskOptions {
enum Command { enum Command {
Codegen(codegen::Options), Codegen(codegen::Options),
Docs, Docs,
BuildIntegrationTest(build_test::Options),
BuildIntegrationTestEbpf(build_ebpf::BuildEbpfOptions),
IntegrationTest(run::Options), IntegrationTest(run::Options),
} }
@ -29,8 +26,6 @@ fn main() {
let ret = match command { let ret = match command {
Command::Codegen(opts) => codegen::codegen(opts), Command::Codegen(opts) => codegen::codegen(opts),
Command::Docs => docs::docs(), Command::Docs => docs::docs(),
Command::BuildIntegrationTest(opts) => build_test::build_test(opts),
Command::BuildIntegrationTestEbpf(opts) => build_ebpf::build_ebpf(opts),
Command::IntegrationTest(opts) => run::run(opts), Command::IntegrationTest(opts) => run::run(opts),
}; };

Loading…
Cancel
Save