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