use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ValidationResult {
pub format_version: String,
pub valid: bool,
pub error_count: u32,
pub warning_count: u32,
pub diagnostics: Vec<Diagnostic>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Diagnostic {
pub severity: String,
pub summary: String,
#[serde(default)]
pub detail: String,
pub range: Option<DiagnosticRange>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct DiagnosticRange {
pub filename: String,
pub start: DiagnosticPos,
pub end: DiagnosticPos,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct DiagnosticPos {
pub line: u32,
pub column: u32,
pub byte: u32,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn deserialize_valid_result() {
let json = r#"{
"format_version": "1.0",
"valid": true,
"error_count": 0,
"warning_count": 0,
"diagnostics": []
}"#;
let result: ValidationResult = serde_json::from_str(json).unwrap();
assert!(result.valid);
assert_eq!(result.error_count, 0);
assert!(result.diagnostics.is_empty());
}
#[test]
fn deserialize_invalid_result() {
let json = r#"{
"format_version": "1.0",
"valid": false,
"error_count": 1,
"warning_count": 0,
"diagnostics": [
{
"severity": "error",
"summary": "Missing required argument",
"detail": "The argument \"region\" is required.",
"range": {
"filename": "main.tf",
"start": {"line": 5, "column": 1, "byte": 42},
"end": {"line": 5, "column": 10, "byte": 51}
}
}
]
}"#;
let result: ValidationResult = serde_json::from_str(json).unwrap();
assert!(!result.valid);
assert_eq!(result.error_count, 1);
assert_eq!(result.diagnostics.len(), 1);
assert_eq!(result.diagnostics[0].severity, "error");
assert_eq!(result.diagnostics[0].summary, "Missing required argument");
let range = result.diagnostics[0].range.as_ref().unwrap();
assert_eq!(range.filename, "main.tf");
assert_eq!(range.start.line, 5);
}
#[test]
fn deserialize_diagnostic_without_range() {
let json = r#"{
"severity": "warning",
"summary": "Deprecated feature",
"detail": "",
"range": null
}"#;
let diag: Diagnostic = serde_json::from_str(json).unwrap();
assert_eq!(diag.severity, "warning");
assert!(diag.range.is_none());
}
}