Skip to main content

rs_teststand/station/
debug_options.rs

1//! Engine debugging option flags.
2
3bitflags::bitflags! {
4    /// Station debugging options (`DebugOption_*`).
5    ///
6    /// A bitmask read and written whole via
7    /// [`StationOptions::debug_options`](crate::StationOptions::debug_options)
8    /// and its setter, so changing one option means editing a mask rather than
9    /// assigning a value, always read, modify the bits, write back.
10    ///
11    /// ```
12    /// use rs_teststand::DebugOptions;
13    ///
14    /// // Turn off just the dialog-raising bits, preserving everything else.
15    /// let current = DebugOptions::STACK_CHECKING | DebugOptions::REPORT_OBJECT_LEAKS;
16    /// let quiet = current.difference(DebugOptions::MODAL_ON_SHUTDOWN);
17    /// assert!(quiet.contains(DebugOptions::STACK_CHECKING));
18    /// assert!(!quiet.contains(DebugOptions::REPORT_OBJECT_LEAKS));
19    /// ```
20    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
21    pub struct DebugOptions: i32 {
22        /// No debugging options (`DebugOption_NoOptions`).
23        const NONE = 0;
24        /// Validate the stack around code-module calls (`DebugOption_StackChecking`).
25        const STACK_CHECKING = 1;
26        /// Validate buffers around code-module calls (`DebugOption_BufferChecking`).
27        const BUFFER_CHECKING = 2;
28        /// Report leaked objects at shutdown (`DebugOption_ReportObjectLeaks`).
29        ///
30        /// The report is a modal dialog, so this bit blocks an unattended host
31        /// at exit. Leak *detection* is separate, clearing this suppresses
32        /// only the dialog.
33        const REPORT_OBJECT_LEAKS = 4;
34        /// Send output messages to an attached debugger
35        /// (`DebugOption_SendOutputMessagesToDebugger`).
36        const SEND_OUTPUT_MESSAGES_TO_DEBUGGER = 8;
37        /// Report known OS and component problems
38        /// (`DebugOption_ReportKnownOSandComponentProblems`).
39        ///
40        /// Also a modal dialog raised during shutdown.
41        const REPORT_KNOWN_OS_AND_COMPONENT_PROBLEMS = 16;
42
43        /// The bits that raise a modal dialog while the engine shuts down.
44        ///
45        /// Not an engine constant. This is the union [`Engine::new`] clears on
46        /// the station it connects to, so that a host with no one at the
47        /// keyboard cannot wedge at exit. Every other debug bit is left as the
48        /// operator set it.
49        ///
50        /// [`Engine::new`]: crate::Engine::new
51        const MODAL_ON_SHUTDOWN =
52            Self::REPORT_OBJECT_LEAKS.bits() | Self::REPORT_KNOWN_OS_AND_COMPONENT_PROBLEMS.bits();
53    }
54}
55
56#[cfg(test)]
57mod tests {
58    use super::DebugOptions;
59
60    #[test]
61    fn modal_bits_are_exactly_the_two_shutdown_dialogs() {
62        assert_eq!(DebugOptions::MODAL_ON_SHUTDOWN.bits(), 4 | 16);
63    }
64
65    #[test]
66    fn clearing_modal_bits_preserves_unrelated_options() {
67        // The engine hands back one mask for every debug setting, so the
68        // hardening step must subtract bits rather than overwrite the value.
69        let current = DebugOptions::STACK_CHECKING
70            | DebugOptions::BUFFER_CHECKING
71            | DebugOptions::SEND_OUTPUT_MESSAGES_TO_DEBUGGER
72            | DebugOptions::MODAL_ON_SHUTDOWN;
73
74        let quiet = current.difference(DebugOptions::MODAL_ON_SHUTDOWN);
75
76        assert!(quiet.contains(DebugOptions::STACK_CHECKING));
77        assert!(quiet.contains(DebugOptions::BUFFER_CHECKING));
78        assert!(quiet.contains(DebugOptions::SEND_OUTPUT_MESSAGES_TO_DEBUGGER));
79        assert!(!quiet.contains(DebugOptions::REPORT_OBJECT_LEAKS));
80        assert!(!quiet.contains(DebugOptions::REPORT_KNOWN_OS_AND_COMPONENT_PROBLEMS));
81    }
82
83    #[test]
84    fn unknown_bits_from_a_newer_engine_survive_a_round_trip() {
85        // A future engine may define debug bits this build does not name;
86        // clearing the modal ones must not discard them.
87        let unknown = DebugOptions::from_bits_retain(1 << 20);
88        let current = unknown | DebugOptions::MODAL_ON_SHUTDOWN;
89        let quiet = current.difference(DebugOptions::MODAL_ON_SHUTDOWN);
90        assert_eq!(quiet.bits(), 1 << 20);
91    }
92}