Skip to main content

debugger/testing/
config.rs

1//! Test scenario configuration types
2//!
3//! Defines the data structures for deserializing YAML test scenarios.
4
5use serde::Deserialize;
6use std::path::PathBuf;
7
8/// A complete test scenario loaded from a YAML file
9#[derive(Deserialize, Debug)]
10pub struct TestScenario {
11    /// Name of the test scenario
12    pub name: String,
13    /// Optional description of what the test verifies
14    pub description: Option<String>,
15    /// Optional setup steps to run before the test (e.g., compilation)
16    pub setup: Option<Vec<SetupStep>>,
17    /// Configuration for the debug target
18    pub target: TargetConfig,
19    /// The sequence of test steps to execute
20    pub steps: Vec<TestStep>,
21}
22
23/// A setup step that runs before the test
24#[derive(Deserialize, Debug)]
25pub struct SetupStep {
26    /// Shell command to execute
27    pub shell: String,
28}
29
30/// Configuration for the debug target
31#[derive(Deserialize, Debug)]
32pub struct TargetConfig {
33    /// Path to the program to debug
34    pub program: PathBuf,
35    /// Arguments to pass to the program
36    pub args: Option<Vec<String>>,
37    /// Debug mode: "launch" (default) or "attach"
38    #[serde(default = "default_mode")]
39    pub mode: String,
40    /// PID to attach to (for attach mode)
41    pub pid: Option<u32>,
42    /// Path to file containing PID (for attach mode with setup-generated PIDs)
43    pub pid_file: Option<PathBuf>,
44    /// Debug adapter to use (e.g., "lldb-dap", "codelldb", "debugpy")
45    pub adapter: Option<String>,
46    /// Whether to stop at the program entry point
47    #[serde(default)]
48    pub stop_on_entry: bool,
49}
50
51fn default_mode() -> String {
52    "launch".to_string()
53}
54
55/// A single test step in the execution flow
56#[derive(Deserialize, Debug)]
57#[serde(tag = "action", rename_all = "snake_case")]
58pub enum TestStep {
59    /// Execute a debugger command
60    Command {
61        /// The command to execute (e.g., "break add main", "continue")
62        command: String,
63        /// Optional expectations for the command result
64        expect: Option<CommandExpectation>,
65    },
66    /// Wait for a stop event (breakpoint, step completion, etc.)
67    Await {
68        /// Timeout in seconds (default: 30)
69        timeout: Option<u64>,
70        /// Expected stop event properties
71        expect: Option<StopExpectation>,
72    },
73    /// Inspect local variables and make assertions
74    InspectLocals {
75        /// Variable assertions to check
76        asserts: Vec<VariableAssertion>,
77    },
78    /// Inspect the call stack
79    InspectStack {
80        /// Frame assertions to check
81        asserts: Vec<FrameAssertion>,
82    },
83    /// Check program output
84    CheckOutput {
85        /// Expected substring in output
86        contains: Option<String>,
87        /// Expected exact output
88        equals: Option<String>,
89    },
90    /// Evaluate an expression
91    Evaluate {
92        /// Expression to evaluate
93        expression: String,
94        /// Expected result
95        expect: Option<EvaluateExpectation>,
96    },
97}
98
99/// Expectations for a command result
100#[derive(Deserialize, Debug)]
101pub struct CommandExpectation {
102    /// Whether the command should succeed
103    pub success: Option<bool>,
104    /// Substring that should be in the output
105    pub output_contains: Option<String>,
106}
107
108/// Expectations for a stop event
109#[derive(Deserialize, Debug)]
110pub struct StopExpectation {
111    /// Expected stop reason (e.g., "breakpoint", "step", "exited")
112    pub reason: Option<String>,
113    /// Expected source file name (partial match)
114    pub file: Option<String>,
115    /// Expected line number
116    pub line: Option<u32>,
117    /// Expected exit code (for "exited" reason)
118    pub exit_code: Option<i64>,
119    /// Expected thread ID
120    pub thread_id: Option<i64>,
121}
122
123/// Assertion for a variable
124#[derive(Deserialize, Debug)]
125pub struct VariableAssertion {
126    /// Variable name to check
127    pub name: String,
128    /// Expected value (exact match)
129    pub value: Option<String>,
130    /// Expected value substring (partial match)
131    pub value_contains: Option<String>,
132    /// Expected type name
133    #[serde(rename = "type")]
134    pub type_name: Option<String>,
135}
136
137/// Assertion for a stack frame
138#[derive(Deserialize, Debug)]
139pub struct FrameAssertion {
140    /// Frame index (0 = current/innermost)
141    pub index: usize,
142    /// Expected function name
143    pub function: Option<String>,
144    /// Expected source file (partial match)
145    pub file: Option<String>,
146    /// Expected line number
147    pub line: Option<u32>,
148}
149
150/// Expectations for an evaluate result
151#[derive(Deserialize, Debug)]
152pub struct EvaluateExpectation {
153    /// Whether the evaluation should succeed (default: true)
154    /// Set to false to test error scenarios (undefined variables, syntax errors)
155    pub success: Option<bool>,
156    /// Expected result value
157    pub result: Option<String>,
158    /// Expected result substring
159    pub result_contains: Option<String>,
160    /// Expected type name
161    #[serde(rename = "type")]
162    pub type_name: Option<String>,
163}