use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::collections::BTreeMap;
use crate::vm_runner::VmTraceEvent;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SimRunInput {
#[serde(default = "crate::schema::default_schema_version")]
pub schema_version: String,
pub scenario: Value,
pub global_type: Value,
pub local_types: BTreeMap<String, Value>,
#[serde(default)]
pub initial_states: BTreeMap<String, Vec<Value>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SimRunOutput {
#[serde(default = "crate::schema::default_schema_version")]
pub schema_version: String,
#[serde(default)]
pub trace: Vec<VmTraceEvent>,
#[serde(default)]
pub violations: Vec<Value>,
#[serde(default)]
pub artifacts: Value,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct SimulationStructuredError {
pub code: String,
#[serde(default)]
pub path: Option<String>,
pub message: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SimTraceValidation {
pub valid: bool,
#[serde(default)]
pub errors: Vec<SimulationStructuredError>,
#[serde(default)]
pub artifacts: Value,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn sim_input_legacy_decode_defaults_schema_version() {
let legacy = serde_json::json!({
"scenario": {"name": "s"},
"global_type": {"kind": "end"},
"local_types": {},
"initial_states": {}
});
let input: SimRunInput = serde_json::from_value(legacy).expect("decode SimRunInput");
assert_eq!(
input.schema_version,
crate::schema::LEAN_BRIDGE_SCHEMA_VERSION
);
}
#[test]
fn sim_output_legacy_decode_defaults_schema_version() {
let legacy = serde_json::json!({
"trace": [],
"violations": []
});
let output: SimRunOutput = serde_json::from_value(legacy).expect("decode SimRunOutput");
assert_eq!(
output.schema_version,
crate::schema::LEAN_BRIDGE_SCHEMA_VERSION
);
}
#[test]
fn sim_trace_validation_roundtrip() {
let validation = SimTraceValidation {
valid: false,
errors: vec![SimulationStructuredError {
code: "sim.trace.mismatch".to_string(),
path: Some("trace[0]".to_string()),
message: "event mismatch".to_string(),
}],
artifacts: serde_json::json!({"kind": "diff"}),
};
let encoded = serde_json::to_value(&validation).expect("encode");
let decoded: SimTraceValidation = serde_json::from_value(encoded).expect("decode");
assert!(!decoded.valid);
assert_eq!(decoded.errors.len(), 1);
assert_eq!(decoded.errors[0].code, "sim.trace.mismatch");
}
}