ant_quic/compliance_validator/
mod.rs

1/// IETF Compliance Validator Framework
2///
3/// This module provides comprehensive validation of QUIC implementation
4/// against IETF specifications including RFC 9000, draft-ietf-quic-address-discovery,
5/// and draft-seemann-quic-nat-traversal.
6use std::collections::HashMap;
7use std::fmt;
8use std::path::Path;
9
10pub mod endpoint_tester;
11pub mod report_generator;
12pub mod rfc_parser;
13pub mod spec_validator;
14
15#[cfg(test)]
16mod tests;
17
18/// Represents a compliance requirement from an IETF specification
19#[derive(Debug, Clone, PartialEq)]
20pub struct ComplianceRequirement {
21    /// Specification ID (e.g., "RFC9000", "draft-ietf-quic-address-discovery-00")
22    pub spec_id: String,
23    /// Section reference (e.g., "7.2.1")
24    pub section: String,
25    /// Requirement level (MUST, SHOULD, MAY)
26    pub level: RequirementLevel,
27    /// Human-readable description
28    pub description: String,
29    /// Category of requirement
30    pub category: RequirementCategory,
31}
32
33/// Requirement levels from RFC 2119
34#[derive(Debug, Clone, PartialEq, Eq, Hash)]
35pub enum RequirementLevel {
36    /// Absolute requirement
37    Must,
38    /// Absolute prohibition
39    MustNot,
40    /// Recommended
41    Should,
42    /// Not recommended
43    ShouldNot,
44    /// Optional
45    May,
46}
47
48impl fmt::Display for RequirementLevel {
49    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50        match self {
51            Self::Must => write!(f, "MUST"),
52            Self::MustNot => write!(f, "MUST NOT"),
53            Self::Should => write!(f, "SHOULD"),
54            Self::ShouldNot => write!(f, "SHOULD NOT"),
55            Self::May => write!(f, "MAY"),
56        }
57    }
58}
59
60/// Categories of requirements for organized testing
61#[derive(Debug, Clone, PartialEq, Eq, Hash)]
62pub enum RequirementCategory {
63    /// Transport protocol requirements
64    Transport,
65    /// Frame encoding/decoding
66    FrameFormat,
67    /// Transport parameters
68    TransportParameters,
69    /// Connection establishment
70    ConnectionEstablishment,
71    /// NAT traversal
72    NatTraversal,
73    /// Address discovery
74    AddressDiscovery,
75    /// Error handling
76    ErrorHandling,
77    /// Security requirements
78    Security,
79    /// Performance requirements
80    Performance,
81}
82
83/// Result of a compliance validation
84#[derive(Debug, Clone)]
85pub struct ComplianceResult {
86    /// The requirement being validated
87    pub requirement: ComplianceRequirement,
88    /// Whether the requirement is met
89    pub compliant: bool,
90    /// Detailed explanation
91    pub details: String,
92    /// Evidence (e.g., test results, packet captures)
93    pub evidence: Vec<Evidence>,
94}
95
96/// Evidence supporting compliance validation
97#[derive(Debug, Clone)]
98pub enum Evidence {
99    /// Test result
100    TestResult {
101        test_name: String,
102        passed: bool,
103        output: String,
104    },
105    /// Packet capture showing behavior
106    PacketCapture {
107        description: String,
108        packets: Vec<u8>,
109    },
110    /// Code reference
111    CodeReference {
112        file: String,
113        line: usize,
114        snippet: String,
115    },
116    /// External endpoint test
117    EndpointTest { endpoint: String, result: String },
118}
119
120/// Main compliance validator
121pub struct ComplianceValidator {
122    /// Parsed requirements from specifications
123    requirements: Vec<ComplianceRequirement>,
124    /// Validators for specific specs
125    validators: HashMap<String, Box<dyn SpecValidator>>,
126    /// Test endpoints for real-world validation
127    test_endpoints: Vec<String>,
128}
129
130impl Default for ComplianceValidator {
131    fn default() -> Self {
132        Self::new()
133    }
134}
135
136impl ComplianceValidator {
137    /// Create a new compliance validator
138    pub fn new() -> Self {
139        Self {
140            requirements: Vec::new(),
141            validators: HashMap::new(),
142            test_endpoints: Vec::new(),
143        }
144    }
145
146    /// Load requirements from RFC documents
147    pub fn load_requirements(&mut self, rfc_path: &Path) -> Result<(), ValidationError> {
148        let parser = rfc_parser::RfcParser::new();
149        let requirements = parser.parse_file(rfc_path)?;
150        self.requirements.extend(requirements);
151        Ok(())
152    }
153
154    /// Register a specification validator
155    pub fn register_validator(&mut self, spec_id: String, validator: Box<dyn SpecValidator>) {
156        self.validators.insert(spec_id, validator);
157    }
158
159    /// Add test endpoint for real-world validation
160    pub fn add_test_endpoint(&mut self, endpoint: String) {
161        self.test_endpoints.push(endpoint);
162    }
163
164    /// Run all compliance validations
165    pub fn validate_all(&self) -> ComplianceReport {
166        let mut results = Vec::new();
167
168        for requirement in &self.requirements {
169            if let Some(validator) = self.validators.get(&requirement.spec_id) {
170                let result = validator.validate(requirement);
171                results.push(result);
172            } else {
173                results.push(ComplianceResult {
174                    requirement: requirement.clone(),
175                    compliant: false,
176                    details: format!("No validator registered for {}", requirement.spec_id),
177                    evidence: vec![],
178                });
179            }
180        }
181
182        ComplianceReport::new(results)
183    }
184
185    /// Validate against real endpoints
186    pub async fn validate_endpoints(&self) -> EndpointValidationReport {
187        let mut tester = endpoint_tester::EndpointTester::new();
188        for endpoint in &self.test_endpoints {
189            tester.add_endpoint(endpoint.clone());
190        }
191        tester.test_all_endpoints().await
192    }
193}
194
195/// Trait for specification-specific validators
196pub trait SpecValidator: Send + Sync {
197    /// Validate a specific requirement
198    fn validate(&self, requirement: &ComplianceRequirement) -> ComplianceResult;
199
200    /// Get the specification ID this validator handles
201    fn spec_id(&self) -> &str;
202}
203
204/// Compliance validation report
205#[derive(Debug)]
206pub struct ComplianceReport {
207    /// All validation results
208    pub results: Vec<ComplianceResult>,
209    /// Summary statistics
210    pub summary: ComplianceSummary,
211    /// Timestamp
212    pub timestamp: std::time::SystemTime,
213}
214
215impl ComplianceReport {
216    fn new(results: Vec<ComplianceResult>) -> Self {
217        let summary = ComplianceSummary::from_results(&results);
218        Self {
219            results,
220            summary,
221            timestamp: std::time::SystemTime::now(),
222        }
223    }
224
225    /// Generate HTML report
226    pub fn to_html(&self) -> String {
227        report_generator::generate_html_report(self)
228    }
229
230    /// Generate JSON report
231    pub fn to_json(&self) -> serde_json::Value {
232        report_generator::generate_json_report(self)
233    }
234}
235
236/// Summary of compliance results
237#[derive(Debug)]
238pub struct ComplianceSummary {
239    /// Total requirements tested
240    pub total_requirements: usize,
241    /// Requirements passed
242    pub passed: usize,
243    /// Requirements failed
244    pub failed: usize,
245    /// Pass rate by requirement level
246    pub pass_rate_by_level: HashMap<RequirementLevel, f64>,
247    /// Pass rate by category
248    pub pass_rate_by_category: HashMap<RequirementCategory, f64>,
249}
250
251impl ComplianceSummary {
252    fn from_results(results: &[ComplianceResult]) -> Self {
253        let total_requirements = results.len();
254        let passed = results.iter().filter(|r| r.compliant).count();
255        let failed = total_requirements - passed;
256
257        let mut pass_rate_by_level = HashMap::new();
258        let mut pass_rate_by_category = HashMap::new();
259
260        // Calculate pass rates by level
261        for level in &[
262            RequirementLevel::Must,
263            RequirementLevel::MustNot,
264            RequirementLevel::Should,
265            RequirementLevel::ShouldNot,
266            RequirementLevel::May,
267        ] {
268            let level_results: Vec<_> = results
269                .iter()
270                .filter(|r| &r.requirement.level == level)
271                .collect();
272
273            if !level_results.is_empty() {
274                let level_passed = level_results.iter().filter(|r| r.compliant).count();
275                let pass_rate = level_passed as f64 / level_results.len() as f64;
276                pass_rate_by_level.insert(level.clone(), pass_rate);
277            }
278        }
279
280        // Calculate pass rates by category
281        for category in &[
282            RequirementCategory::Transport,
283            RequirementCategory::FrameFormat,
284            RequirementCategory::TransportParameters,
285            RequirementCategory::ConnectionEstablishment,
286            RequirementCategory::NatTraversal,
287            RequirementCategory::AddressDiscovery,
288            RequirementCategory::ErrorHandling,
289            RequirementCategory::Security,
290            RequirementCategory::Performance,
291        ] {
292            let category_results: Vec<_> = results
293                .iter()
294                .filter(|r| &r.requirement.category == category)
295                .collect();
296
297            if !category_results.is_empty() {
298                let category_passed = category_results.iter().filter(|r| r.compliant).count();
299                let pass_rate = category_passed as f64 / category_results.len() as f64;
300                pass_rate_by_category.insert(category.clone(), pass_rate);
301            }
302        }
303
304        Self {
305            total_requirements,
306            passed,
307            failed,
308            pass_rate_by_level,
309            pass_rate_by_category,
310        }
311    }
312
313    /// Overall compliance percentage
314    pub fn compliance_percentage(&self) -> f64 {
315        if self.total_requirements == 0 {
316            0.0
317        } else {
318            (self.passed as f64 / self.total_requirements as f64) * 100.0
319        }
320    }
321
322    /// Check if MUST requirements are met (minimum for compliance)
323    pub fn must_requirements_met(&self) -> bool {
324        self.pass_rate_by_level
325            .get(&RequirementLevel::Must)
326            .map(|&rate| rate == 1.0)
327            .unwrap_or(true)
328    }
329}
330
331/// Report from endpoint validation
332#[derive(Debug)]
333pub struct EndpointValidationReport {
334    /// Results per endpoint
335    pub endpoint_results: HashMap<String, EndpointResult>,
336    /// Overall success rate
337    pub success_rate: f64,
338    /// Common issues found
339    pub common_issues: Vec<String>,
340}
341
342/// Result of testing against a specific endpoint
343#[derive(Debug)]
344pub struct EndpointResult {
345    /// Endpoint URL
346    pub endpoint: String,
347    /// Whether connection succeeded
348    pub connected: bool,
349    /// Supported QUIC versions
350    pub quic_versions: Vec<u32>,
351    /// Supported extensions
352    pub extensions: Vec<String>,
353    /// Compliance issues found
354    pub issues: Vec<String>,
355}
356
357/// Errors that can occur during validation
358#[derive(Debug)]
359pub enum ValidationError {
360    /// Error parsing RFC
361    RfcParseError(String),
362    /// Error loading specification
363    SpecLoadError(String),
364    /// Error running validation
365    ValidationError(String),
366    /// IO error
367    IoError(std::io::Error),
368}
369
370impl fmt::Display for ValidationError {
371    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
372        match self {
373            Self::RfcParseError(e) => write!(f, "RFC parse error: {e}"),
374            Self::SpecLoadError(e) => write!(f, "Specification load error: {e}"),
375            Self::ValidationError(e) => write!(f, "Validation error: {e}"),
376            Self::IoError(e) => write!(f, "IO error: {e}"),
377        }
378    }
379}
380
381impl std::error::Error for ValidationError {}
382
383impl From<std::io::Error> for ValidationError {
384    fn from(err: std::io::Error) -> Self {
385        Self::IoError(err)
386    }
387}