Skip to main content

lexicon_spec/
conformance.rs

1use serde::{Deserialize, Serialize};
2
3use crate::common::ConformanceStyle;
4use crate::version::SchemaVersion;
5
6/// Definition of a conformance test suite tied to a contract.
7///
8/// Conformance suites define reusable test harnesses that verify
9/// implementations against a contract's invariants and semantics.
10///
11/// Stored at `specs/conformance/<id>.toml`.
12#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct ConformanceSuite {
14    pub schema_version: SchemaVersion,
15    /// Unique identifier for this suite.
16    pub id: String,
17    /// The contract this suite verifies.
18    pub contract_id: String,
19    /// Style of conformance harness.
20    pub style: ConformanceStyle,
21    /// Module path for the generated harness, e.g. "tests::conformance::store".
22    pub harness_module: String,
23    /// Tests that must pass for conformance.
24    #[serde(default)]
25    pub required_tests: Vec<ConformanceTest>,
26    /// Optional tests that improve coverage but don't block.
27    #[serde(default)]
28    pub optional_tests: Vec<ConformanceTest>,
29    /// Shared fixtures referenced by tests.
30    #[serde(default)]
31    pub fixtures: Vec<FixtureRef>,
32}
33
34/// A single conformance test case.
35#[derive(Debug, Clone, Serialize, Deserialize)]
36pub struct ConformanceTest {
37    /// Unique identifier within the suite.
38    pub id: String,
39    pub description: String,
40    /// Tags for categorization and filtering.
41    #[serde(default)]
42    pub tags: Vec<String>,
43    /// References to contract clause IDs this test verifies.
44    #[serde(default)]
45    pub clause_refs: Vec<String>,
46}
47
48/// Reference to a shared test fixture.
49#[derive(Debug, Clone, Serialize, Deserialize)]
50pub struct FixtureRef {
51    pub id: String,
52    pub description: String,
53    /// Module path where the fixture is defined.
54    pub module_path: String,
55}
56
57#[cfg(test)]
58mod tests {
59    use super::*;
60
61    #[test]
62    fn test_conformance_suite_roundtrip() {
63        let suite = ConformanceSuite {
64            schema_version: SchemaVersion::CURRENT,
65            id: "kv-store-conformance".to_string(),
66            contract_id: "key-value-store".to_string(),
67            style: ConformanceStyle::TraitBased,
68            harness_module: "tests::conformance::kv_store".to_string(),
69            required_tests: vec![ConformanceTest {
70                id: "test-get-set".to_string(),
71                description: "Setting a key then getting it returns the value".to_string(),
72                tags: vec!["basic".to_string()],
73                clause_refs: vec!["inv-001".to_string()],
74            }],
75            optional_tests: vec![],
76            fixtures: vec![],
77        };
78        let toml_str = toml::to_string_pretty(&suite).unwrap();
79        let parsed: ConformanceSuite = toml::from_str(&toml_str).unwrap();
80        assert_eq!(parsed.contract_id, "key-value-store");
81        assert_eq!(parsed.required_tests.len(), 1);
82    }
83}