Skip to content

Commit 1746a5f

Browse files
committed
test(bpf): add chmod operation to bpf unit test
This allows us to exercise the trace_path_chmod bpf program on unit tests.
1 parent 2557b22 commit 1746a5f

File tree

2 files changed

+57
-14
lines changed

2 files changed

+57
-14
lines changed

fact/src/bpf/mod.rs

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -228,15 +228,14 @@ impl Bpf {
228228

229229
#[cfg(all(test, feature = "bpf-test"))]
230230
mod bpf_tests {
231-
use std::{env, path::PathBuf, time::Duration};
231+
use std::{env, os::unix::fs::PermissionsExt, path::PathBuf, time::Duration};
232232

233-
use fact_ebpf::file_activity_type_t;
234233
use tempfile::NamedTempFile;
235234
use tokio::{sync::watch, time::timeout};
236235

237236
use crate::{
238237
config::{reloader::Reloader, FactConfig},
239-
event::process::Process,
238+
event::{process::Process, EventTestData},
240239
host_info,
241240
metrics::exporter::Exporter,
242241
};
@@ -273,20 +272,39 @@ mod bpf_tests {
273272
let file = NamedTempFile::new_in(monitored_path).expect("Failed to create temporary file");
274273
println!("Created {file:?}");
275274

275+
// Trigger permission changes
276+
let mut perms = file
277+
.path()
278+
.metadata()
279+
.expect("Failed to read file permissions")
280+
.permissions();
281+
let old_perm = perms.mode() as u16;
282+
let new_perm: u16 = 0o666;
283+
perms.set_mode(new_perm as u32);
284+
std::fs::set_permissions(file.path(), perms).expect("Failed to set file permissions");
285+
276286
let current = Process::current();
277287
let file_path = file.path().to_path_buf();
278288

279289
let expected_events = [
280290
Event::new(
281-
file_activity_type_t::FILE_ACTIVITY_CREATION,
291+
EventTestData::Creation,
292+
host_info::get_hostname(),
293+
file_path.clone(),
294+
PathBuf::new(), // host path is resolved by HostScanner
295+
current.clone(),
296+
)
297+
.unwrap(),
298+
Event::new(
299+
EventTestData::Chmod(new_perm, old_perm),
282300
host_info::get_hostname(),
283301
file_path.clone(),
284302
PathBuf::new(), // host path is resolved by HostScanner
285303
current.clone(),
286304
)
287305
.unwrap(),
288306
Event::new(
289-
file_activity_type_t::FILE_ACTIVITY_UNLINK,
307+
EventTestData::Unlink,
290308
host_info::get_hostname(),
291309
file_path,
292310
PathBuf::new(), // host path is resolved by HostScanner
@@ -298,12 +316,13 @@ mod bpf_tests {
298316
// Close the file, removing it
299317
file.close().expect("Failed to close temp file");
300318

301-
println!("Expected: {expected_events:?}");
302319
let wait = timeout(Duration::from_secs(1), async move {
303320
for expected in expected_events {
321+
println!("expected: {expected:#?}");
304322
while let Some(event) = rx.recv().await {
305-
println!("{event:?}");
323+
println!("{event:#?}");
306324
if event == expected {
325+
println!("Found!");
307326
break;
308327
}
309328
}

fact/src/event/mod.rs

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,14 @@ fn timestamp_to_proto(ts: u64) -> prost_types::Timestamp {
2121
prost_types::Timestamp { seconds, nanos }
2222
}
2323

24+
#[cfg(test)]
25+
#[derive(Debug)]
26+
pub(crate) enum EventTestData {
27+
Creation,
28+
Unlink,
29+
Chmod(u16, u16),
30+
}
31+
2432
#[derive(Debug, Clone, Serialize)]
2533
pub struct Event {
2634
timestamp: u64,
@@ -31,8 +39,8 @@ pub struct Event {
3139

3240
impl Event {
3341
#[cfg(test)]
34-
pub fn new(
35-
event_type: file_activity_type_t,
42+
pub(crate) fn new(
43+
data: EventTestData,
3644
hostname: &'static str,
3745
filename: PathBuf,
3846
host_file: PathBuf,
@@ -47,11 +55,17 @@ impl Event {
4755
host_file,
4856
inode: Default::default(),
4957
};
50-
let file = match event_type {
51-
file_activity_type_t::FILE_ACTIVITY_OPEN => FileData::Open(inner),
52-
file_activity_type_t::FILE_ACTIVITY_CREATION => FileData::Creation(inner),
53-
file_activity_type_t::FILE_ACTIVITY_UNLINK => FileData::Unlink(inner),
54-
invalid => unreachable!("Invalid event type: {invalid:?}"),
58+
let file = match data {
59+
EventTestData::Creation => FileData::Creation(inner),
60+
EventTestData::Unlink => FileData::Unlink(inner),
61+
EventTestData::Chmod(new_mode, old_mode) => {
62+
let data = ChmodFileData {
63+
inner,
64+
new_mode,
65+
old_mode,
66+
};
67+
FileData::Chmod(data)
68+
}
5569
};
5670

5771
Ok(Event {
@@ -193,6 +207,7 @@ impl PartialEq for FileData {
193207
(FileData::Open(this), FileData::Open(other)) => this == other,
194208
(FileData::Creation(this), FileData::Creation(other)) => this == other,
195209
(FileData::Unlink(this), FileData::Unlink(other)) => this == other,
210+
(FileData::Chmod(this), FileData::Chmod(other)) => this == other,
196211
_ => false,
197212
}
198213
}
@@ -271,3 +286,12 @@ impl From<ChmodFileData> for fact_api::FilePermissionChange {
271286
}
272287
}
273288
}
289+
290+
#[cfg(test)]
291+
impl PartialEq for ChmodFileData {
292+
fn eq(&self, other: &Self) -> bool {
293+
self.new_mode == other.new_mode
294+
&& self.old_mode == other.old_mode
295+
&& self.inner == other.inner
296+
}
297+
}

0 commit comments

Comments
 (0)