Skip to main content

proc_tree/
tree.rs

1//! Process tree types: events, links, and node definitions.
2
3use std::fmt;
4
5// ---- Process events (decoupled from proc-connector) ----
6
7/// A process lifecycle event. Decoupled from any specific event source
8/// (proc-connector, audit, etc.) so users can adapt their own events.
9#[derive(Debug, Clone)]
10pub enum ProcEvent {
11    /// A new process was created. `parent_pid` is the parent.
12    Fork {
13        child_pid: u32,
14        parent_pid: u32,
15        timestamp_ns: u64,
16    },
17    /// A process executed a new program. Its cmd/user may have changed.
18    Exec { pid: u32, timestamp_ns: u64 },
19    /// A process exited. The node is preserved for historical chain lookups.
20    Exit { pid: u32 },
21}
22
23// ---- ProcessLink (structured chain element) ----
24
25/// A single entry in a process ancestry chain.
26///
27/// Displayed as `"pid|cmd|user"` by the `Display` impl.
28///
29/// ```
30/// use proc_tree::ProcessLink;
31///
32/// let link = ProcessLink { pid: 102, cmd: "touch".into(), user: "root".into() };
33/// assert_eq!(link.to_string(), "102|touch|root");
34/// ```
35///
36/// A chain is a `Vec<ProcessLink>` ordered from child to ancestor.
37#[derive(Debug, Clone)]
38pub struct ProcessLink {
39    pub pid: u32,
40    pub cmd: String,
41    pub user: String,
42}
43
44impl fmt::Display for ProcessLink {
45    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46        write!(f, "{}|{}|{}", self.pid, self.cmd, self.user)
47    }
48}
49
50#[cfg(test)]
51mod tests {
52    use super::*;
53
54    #[test]
55    fn process_link_display_format() {
56        let link = ProcessLink {
57            pid: 42,
58            cmd: "bash".into(),
59            user: "root".into(),
60        };
61        assert_eq!(link.to_string(), "42|bash|root");
62    }
63
64    #[test]
65    fn process_link_clone() {
66        let link = ProcessLink {
67            pid: 1,
68            cmd: "init".into(),
69            user: "root".into(),
70        };
71        let link2 = link.clone();
72        assert_eq!(link.pid, link2.pid);
73        assert_eq!(link.cmd, link2.cmd);
74        assert_eq!(link.user, link2.user);
75    }
76
77    #[test]
78    fn proc_event_clone() {
79        let e = ProcEvent::Fork {
80            child_pid: 100,
81            parent_pid: 1,
82            timestamp_ns: 42,
83        };
84        let e2 = e.clone();
85        match e2 {
86            ProcEvent::Fork {
87                child_pid,
88                parent_pid,
89                timestamp_ns,
90            } => {
91                assert_eq!(child_pid, 100);
92                assert_eq!(parent_pid, 1);
93                assert_eq!(timestamp_ns, 42);
94            }
95            _ => panic!("expected Fork"),
96        }
97    }
98}