mdbook_validator/
host_validator.rs

1//! Host-side validator execution
2//!
3//! Runs validator scripts on the host machine, enabling use of jq
4//! and other host tools for JSON parsing.
5
6use anyhow::Result;
7
8use crate::command::CommandRunner;
9
10/// Result of running a host validator
11#[derive(Debug)]
12#[must_use]
13pub struct HostValidationResult {
14    /// Exit code from the validator (0 = success)
15    pub exit_code: i32,
16    /// Standard output from the validator
17    pub stdout: String,
18    /// Standard error from the validator
19    pub stderr: String,
20}
21
22/// Run a validator script on the host with JSON input.
23///
24/// # Arguments
25///
26/// * `runner` - Command runner for executing scripts (enables mocking)
27/// * `script_path` - Path to validator script (e.g., "validators/validate-sqlite.sh")
28/// * `json_input` - JSON output from container to validate
29/// * `assertions` - Optional assertion rules
30/// * `expect` - Optional expected output
31/// * `container_stderr` - Optional stderr output from container (for warning detection)
32///
33/// # Errors
34///
35/// Returns error if the validator script cannot be spawned or if stdin write fails.
36pub fn run_validator<R: CommandRunner>(
37    runner: &R,
38    script_path: &str,
39    json_input: &str,
40    assertions: Option<&str>,
41    expect: Option<&str>,
42    container_stderr: Option<&str>,
43) -> Result<HostValidationResult> {
44    // Build environment variables
45    let mut env_vars: Vec<(&str, &str)> = Vec::new();
46
47    if let Some(a) = assertions {
48        env_vars.push(("VALIDATOR_ASSERTIONS", a));
49    }
50    if let Some(e) = expect {
51        env_vars.push(("VALIDATOR_EXPECT", e));
52    }
53    if let Some(stderr) = container_stderr {
54        env_vars.push(("VALIDATOR_CONTAINER_STDERR", stderr));
55    }
56
57    let output = runner.run_script(script_path, json_input, &env_vars)?;
58
59    Ok(HostValidationResult {
60        exit_code: output.status.code().unwrap_or(-1),
61        stdout: String::from_utf8_lossy(&output.stdout).to_string(),
62        stderr: String::from_utf8_lossy(&output.stderr).to_string(),
63    })
64}