Skip to main content

jugar_probar/assertion/
equation.rs

1//! Equation Verification Assertions (Feature 22 - EDD Compliance)
2//!
3//! Provides assertions for verifying physics equations and game invariants.
4//! Supports Equation-Driven Development (EDD) where game behavior is validated
5//! against mathematical models.
6//!
7//! ## EXTREME TDD: Tests written FIRST per spec
8//!
9//! ## Toyota Way Application
10//!
11//! - **Poka-Yoke**: Type-safe equation definitions prevent invalid formulas
12//! - **Muda**: Fail-fast on equation violations with detailed diagnostics
13//! - **Genchi Genbutsu**: Actual vs expected comparison with tolerance
14
15use crate::result::{ProbarError, ProbarResult};
16use std::collections::HashMap;
17use std::fmt;
18
19/// A variable binding for equation evaluation
20#[derive(Debug, Clone)]
21pub struct Variable {
22    /// Variable name
23    pub name: String,
24    /// Current value
25    pub value: f64,
26    /// Optional unit (for documentation)
27    pub unit: Option<String>,
28}
29
30impl Variable {
31    /// Create a new variable
32    #[must_use]
33    pub fn new(name: &str, value: f64) -> Self {
34        Self {
35            name: name.to_string(),
36            value,
37            unit: None,
38        }
39    }
40
41    /// Create a variable with unit
42    #[must_use]
43    pub fn with_unit(name: &str, value: f64, unit: &str) -> Self {
44        Self {
45            name: name.to_string(),
46            value,
47            unit: Some(unit.to_string()),
48        }
49    }
50}
51
52impl fmt::Display for Variable {
53    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
54        match &self.unit {
55            Some(unit) => write!(f, "{} = {} {}", self.name, self.value, unit),
56            None => write!(f, "{} = {}", self.name, self.value),
57        }
58    }
59}
60
61/// Context for equation evaluation
62#[derive(Debug, Clone, Default)]
63pub struct EquationContext {
64    variables: HashMap<String, f64>,
65}
66
67impl EquationContext {
68    /// Create a new empty context
69    #[must_use]
70    pub fn new() -> Self {
71        Self::default()
72    }
73
74    /// Set a variable value
75    pub fn set(&mut self, name: &str, value: f64) -> &mut Self {
76        self.variables.insert(name.to_string(), value);
77        self
78    }
79
80    /// Get a variable value
81    #[must_use]
82    pub fn get(&self, name: &str) -> Option<f64> {
83        self.variables.get(name).copied()
84    }
85
86    /// Check if a variable exists
87    #[must_use]
88    pub fn has(&self, name: &str) -> bool {
89        self.variables.contains_key(name)
90    }
91
92    /// Get all variable names
93    #[must_use]
94    pub fn variables(&self) -> Vec<&str> {
95        self.variables.keys().map(String::as_str).collect()
96    }
97
98    /// Create from a slice of variables
99    #[must_use]
100    pub fn from_variables(vars: &[Variable]) -> Self {
101        let mut ctx = Self::new();
102        for var in vars {
103            ctx.set(&var.name, var.value);
104        }
105        ctx
106    }
107}
108
109/// Result of an equation verification
110#[derive(Debug, Clone)]
111pub struct EquationResult {
112    /// Name of the equation
113    pub name: String,
114    /// Whether the equation holds within tolerance
115    pub passed: bool,
116    /// Expected value
117    pub expected: f64,
118    /// Actual value
119    pub actual: f64,
120    /// Tolerance used
121    pub tolerance: f64,
122    /// Absolute difference
123    pub difference: f64,
124    /// Relative difference (percentage)
125    pub relative_difference: f64,
126    /// Diagnostic message
127    pub message: String,
128}
129
130impl EquationResult {
131    /// Create a new equation result
132    #[must_use]
133    fn new(name: &str, expected: f64, actual: f64, tolerance: f64) -> Self {
134        let difference = (expected - actual).abs();
135        let relative_difference = if expected.abs() > f64::EPSILON {
136            (difference / expected.abs()) * 100.0
137        } else {
138            0.0
139        };
140        let passed = difference <= tolerance;
141
142        let message = if passed {
143            format!(
144                "{}: expected {} ≈ {} (diff: {:.6}, tolerance: {})",
145                name, expected, actual, difference, tolerance
146            )
147        } else {
148            format!(
149                "{}: FAILED - expected {} but got {} (diff: {:.6} > tolerance: {})",
150                name, expected, actual, difference, tolerance
151            )
152        };
153
154        Self {
155            name: name.to_string(),
156            passed,
157            expected,
158            actual,
159            tolerance,
160            difference,
161            relative_difference,
162            message,
163        }
164    }
165}
166
167impl fmt::Display for EquationResult {
168    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
169        write!(f, "{}", self.message)
170    }
171}
172
173/// Equation verifier for testing physics and game invariants
174#[derive(Debug)]
175pub struct EquationVerifier {
176    /// Name of the verification context
177    name: String,
178    /// Default tolerance for comparisons
179    tolerance: f64,
180    /// Results of verified equations
181    results: Vec<EquationResult>,
182}
183
184impl EquationVerifier {
185    /// Create a new equation verifier
186    #[must_use]
187    pub fn new(name: &str) -> Self {
188        Self {
189            name: name.to_string(),
190            tolerance: 1e-6,
191            results: Vec::new(),
192        }
193    }
194
195    /// Set the default tolerance
196    #[must_use]
197    pub fn with_tolerance(mut self, tolerance: f64) -> Self {
198        self.tolerance = tolerance;
199        self
200    }
201
202    /// Get the verifier name
203    #[must_use]
204    pub fn name(&self) -> &str {
205        &self.name
206    }
207
208    /// Get current tolerance
209    #[must_use]
210    pub fn tolerance(&self) -> f64 {
211        self.tolerance
212    }
213
214    /// Verify that two values are approximately equal
215    pub fn verify_eq(&mut self, name: &str, expected: f64, actual: f64) -> &mut Self {
216        let result = EquationResult::new(name, expected, actual, self.tolerance);
217        self.results.push(result);
218        self
219    }
220
221    /// Verify with custom tolerance
222    pub fn verify_eq_with_tolerance(
223        &mut self,
224        name: &str,
225        expected: f64,
226        actual: f64,
227        tolerance: f64,
228    ) -> &mut Self {
229        let result = EquationResult::new(name, expected, actual, tolerance);
230        self.results.push(result);
231        self
232    }
233
234    /// Verify a value is within a range
235    pub fn verify_in_range(&mut self, name: &str, value: f64, min: f64, max: f64) -> &mut Self {
236        let passed = value >= min && value <= max;
237        let midpoint = (min + max) / 2.0;
238        let difference = if passed {
239            0.0
240        } else if value < min {
241            min - value
242        } else {
243            value - max
244        };
245
246        let message = if passed {
247            format!("{}: {} is within [{}, {}]", name, value, min, max)
248        } else {
249            format!(
250                "{}: FAILED - {} is outside range [{}, {}]",
251                name, value, min, max
252            )
253        };
254
255        self.results.push(EquationResult {
256            name: name.to_string(),
257            passed,
258            expected: midpoint,
259            actual: value,
260            tolerance: (max - min) / 2.0,
261            difference,
262            relative_difference: 0.0,
263            message,
264        });
265        self
266    }
267
268    /// Verify that a value is non-negative
269    pub fn verify_non_negative(&mut self, name: &str, value: f64) -> &mut Self {
270        let passed = value >= 0.0;
271        let message = if passed {
272            format!("{}: {} >= 0", name, value)
273        } else {
274            format!("{}: FAILED - {} < 0", name, value)
275        };
276
277        self.results.push(EquationResult {
278            name: name.to_string(),
279            passed,
280            expected: 0.0,
281            actual: value,
282            tolerance: 0.0,
283            difference: if passed { 0.0 } else { -value },
284            relative_difference: 0.0,
285            message,
286        });
287        self
288    }
289
290    /// Verify that a value is positive
291    pub fn verify_positive(&mut self, name: &str, value: f64) -> &mut Self {
292        let passed = value > 0.0;
293        let message = if passed {
294            format!("{}: {} > 0", name, value)
295        } else {
296            format!("{}: FAILED - {} <= 0", name, value)
297        };
298
299        self.results.push(EquationResult {
300            name: name.to_string(),
301            passed,
302            expected: f64::EPSILON,
303            actual: value,
304            tolerance: 0.0,
305            difference: if passed { 0.0 } else { -value },
306            relative_difference: 0.0,
307            message,
308        });
309        self
310    }
311
312    /// Get all results
313    #[must_use]
314    pub fn results(&self) -> &[EquationResult] {
315        &self.results
316    }
317
318    /// Check if all verifications passed
319    #[must_use]
320    pub fn all_passed(&self) -> bool {
321        self.results.iter().all(|r| r.passed)
322    }
323
324    /// Get failed verifications
325    #[must_use]
326    pub fn failures(&self) -> Vec<&EquationResult> {
327        self.results.iter().filter(|r| !r.passed).collect()
328    }
329
330    /// Count passed verifications
331    #[must_use]
332    pub fn passed_count(&self) -> usize {
333        self.results.iter().filter(|r| r.passed).count()
334    }
335
336    /// Count failed verifications
337    #[must_use]
338    pub fn failed_count(&self) -> usize {
339        self.results.iter().filter(|r| !r.passed).count()
340    }
341
342    /// Assert all verifications passed
343    pub fn assert_all(&self) -> ProbarResult<()> {
344        if self.all_passed() {
345            Ok(())
346        } else {
347            let failures: Vec<String> = self.failures().iter().map(|r| r.message.clone()).collect();
348            Err(ProbarError::AssertionFailed {
349                message: format!(
350                    "Equation verification '{}' failed:\n{}",
351                    self.name,
352                    failures.join("\n")
353                ),
354            })
355        }
356    }
357
358    /// Clear all results
359    pub fn clear(&mut self) {
360        self.results.clear();
361    }
362}
363
364// =============================================================================
365// Common Physics Equations
366// =============================================================================
367
368/// Verify kinematic equations (constant acceleration)
369#[derive(Debug)]
370pub struct KinematicVerifier {
371    verifier: EquationVerifier,
372}
373
374impl KinematicVerifier {
375    /// Create a new kinematic verifier
376    #[must_use]
377    pub fn new() -> Self {
378        Self {
379            verifier: EquationVerifier::new("kinematics").with_tolerance(1e-4),
380        }
381    }
382
383    /// With custom tolerance
384    #[must_use]
385    pub fn with_tolerance(mut self, tolerance: f64) -> Self {
386        self.verifier = self.verifier.with_tolerance(tolerance);
387        self
388    }
389
390    /// Verify v = v0 + at
391    pub fn verify_velocity(
392        &mut self,
393        v: f64,  // final velocity
394        v0: f64, // initial velocity
395        a: f64,  // acceleration
396        t: f64,  // time
397    ) -> &mut Self {
398        let expected = v0 + a * t;
399        self.verifier.verify_eq("v = v0 + at", expected, v);
400        self
401    }
402
403    /// Verify x = x0 + v0*t + 0.5*a*t²
404    pub fn verify_position(
405        &mut self,
406        x: f64,  // final position
407        x0: f64, // initial position
408        v0: f64, // initial velocity
409        a: f64,  // acceleration
410        t: f64,  // time
411    ) -> &mut Self {
412        let expected = x0 + v0 * t + 0.5 * a * t * t;
413        self.verifier
414            .verify_eq("x = x0 + v0*t + 0.5*a*t²", expected, x);
415        self
416    }
417
418    /// Verify v² = v0² + 2a(x - x0)
419    pub fn verify_velocity_squared(
420        &mut self,
421        v: f64,  // final velocity
422        v0: f64, // initial velocity
423        a: f64,  // acceleration
424        x: f64,  // final position
425        x0: f64, // initial position
426    ) -> &mut Self {
427        let expected = v0 * v0 + 2.0 * a * (x - x0);
428        self.verifier
429            .verify_eq("v² = v0² + 2a(x-x0)", expected, v * v);
430        self
431    }
432
433    /// Get the underlying verifier
434    #[must_use]
435    pub fn verifier(&self) -> &EquationVerifier {
436        &self.verifier
437    }
438
439    /// Assert all kinematic equations hold
440    pub fn assert_all(&self) -> ProbarResult<()> {
441        self.verifier.assert_all()
442    }
443}
444
445impl Default for KinematicVerifier {
446    fn default() -> Self {
447        Self::new()
448    }
449}
450
451/// Verify energy conservation
452#[derive(Debug)]
453pub struct EnergyVerifier {
454    verifier: EquationVerifier,
455}
456
457impl EnergyVerifier {
458    /// Create a new energy verifier
459    #[must_use]
460    pub fn new() -> Self {
461        Self {
462            verifier: EquationVerifier::new("energy").with_tolerance(1e-4),
463        }
464    }
465
466    /// With custom tolerance
467    #[must_use]
468    pub fn with_tolerance(mut self, tolerance: f64) -> Self {
469        self.verifier = self.verifier.with_tolerance(tolerance);
470        self
471    }
472
473    /// Verify kinetic energy: KE = 0.5 * m * v²
474    pub fn verify_kinetic_energy(
475        &mut self,
476        ke: f64, // kinetic energy
477        m: f64,  // mass
478        v: f64,  // velocity
479    ) -> &mut Self {
480        let expected = 0.5 * m * v * v;
481        self.verifier.verify_eq("KE = 0.5*m*v²", expected, ke);
482        self
483    }
484
485    /// Verify potential energy: PE = m * g * h
486    pub fn verify_potential_energy(
487        &mut self,
488        pe: f64, // potential energy
489        m: f64,  // mass
490        g: f64,  // gravity
491        h: f64,  // height
492    ) -> &mut Self {
493        let expected = m * g * h;
494        self.verifier.verify_eq("PE = m*g*h", expected, pe);
495        self
496    }
497
498    /// Verify total mechanical energy conservation
499    pub fn verify_conservation(
500        &mut self,
501        ke_initial: f64,
502        pe_initial: f64,
503        ke_final: f64,
504        pe_final: f64,
505    ) -> &mut Self {
506        let total_initial = ke_initial + pe_initial;
507        let total_final = ke_final + pe_final;
508        self.verifier
509            .verify_eq("E_total conserved", total_initial, total_final);
510        self
511    }
512
513    /// Verify work-energy theorem: W = ΔKE
514    pub fn verify_work_energy(&mut self, work: f64, ke_initial: f64, ke_final: f64) -> &mut Self {
515        let delta_ke = ke_final - ke_initial;
516        self.verifier.verify_eq("W = ΔKE", work, delta_ke);
517        self
518    }
519
520    /// Get the underlying verifier
521    #[must_use]
522    pub fn verifier(&self) -> &EquationVerifier {
523        &self.verifier
524    }
525
526    /// Assert all energy equations hold
527    pub fn assert_all(&self) -> ProbarResult<()> {
528        self.verifier.assert_all()
529    }
530}
531
532impl Default for EnergyVerifier {
533    fn default() -> Self {
534        Self::new()
535    }
536}
537
538/// Verify momentum conservation
539#[derive(Debug)]
540pub struct MomentumVerifier {
541    verifier: EquationVerifier,
542}
543
544impl MomentumVerifier {
545    /// Create a new momentum verifier
546    #[must_use]
547    pub fn new() -> Self {
548        Self {
549            verifier: EquationVerifier::new("momentum").with_tolerance(1e-4),
550        }
551    }
552
553    /// With custom tolerance
554    #[must_use]
555    pub fn with_tolerance(mut self, tolerance: f64) -> Self {
556        self.verifier = self.verifier.with_tolerance(tolerance);
557        self
558    }
559
560    /// Verify momentum: p = m * v
561    pub fn verify_momentum(
562        &mut self,
563        p: f64, // momentum
564        m: f64, // mass
565        v: f64, // velocity
566    ) -> &mut Self {
567        let expected = m * v;
568        self.verifier.verify_eq("p = m*v", expected, p);
569        self
570    }
571
572    /// Verify momentum conservation in collision
573    pub fn verify_conservation(
574        &mut self,
575        m1: f64,
576        v1_initial: f64,
577        m2: f64,
578        v2_initial: f64,
579        v1_final: f64,
580        v2_final: f64,
581    ) -> &mut Self {
582        let p_initial = m1 * v1_initial + m2 * v2_initial;
583        let p_final = m1 * v1_final + m2 * v2_final;
584        self.verifier
585            .verify_eq("p_total conserved", p_initial, p_final);
586        self
587    }
588
589    /// Verify elastic collision (both momentum and KE conserved)
590    pub fn verify_elastic_collision(
591        &mut self,
592        m1: f64,
593        v1_initial: f64,
594        m2: f64,
595        v2_initial: f64,
596        v1_final: f64,
597        v2_final: f64,
598    ) -> &mut Self {
599        // Momentum conservation
600        self.verify_conservation(m1, v1_initial, m2, v2_initial, v1_final, v2_final);
601
602        // Kinetic energy conservation
603        let ke_initial = 0.5 * m1 * v1_initial * v1_initial + 0.5 * m2 * v2_initial * v2_initial;
604        let ke_final = 0.5 * m1 * v1_final * v1_final + 0.5 * m2 * v2_final * v2_final;
605        self.verifier
606            .verify_eq("KE conserved (elastic)", ke_initial, ke_final);
607        self
608    }
609
610    /// Get the underlying verifier
611    #[must_use]
612    pub fn verifier(&self) -> &EquationVerifier {
613        &self.verifier
614    }
615
616    /// Assert all momentum equations hold
617    pub fn assert_all(&self) -> ProbarResult<()> {
618        self.verifier.assert_all()
619    }
620}
621
622impl Default for MomentumVerifier {
623    fn default() -> Self {
624        Self::new()
625    }
626}
627
628/// Game-specific invariant verifier
629#[derive(Debug)]
630pub struct InvariantVerifier {
631    verifier: EquationVerifier,
632}
633
634impl InvariantVerifier {
635    /// Create a new invariant verifier
636    #[must_use]
637    pub fn new(name: &str) -> Self {
638        Self {
639            verifier: EquationVerifier::new(name).with_tolerance(1e-6),
640        }
641    }
642
643    /// With custom tolerance
644    #[must_use]
645    pub fn with_tolerance(mut self, tolerance: f64) -> Self {
646        self.verifier = self.verifier.with_tolerance(tolerance);
647        self
648    }
649
650    /// Verify score is non-negative
651    pub fn verify_score_non_negative(&mut self, score: f64) -> &mut Self {
652        self.verifier.verify_non_negative("score >= 0", score);
653        self
654    }
655
656    /// Verify health is in valid range [0, max_health]
657    pub fn verify_health(&mut self, health: f64, max_health: f64) -> &mut Self {
658        self.verifier
659            .verify_in_range("health", health, 0.0, max_health);
660        self
661    }
662
663    /// Verify position is within bounds
664    pub fn verify_position_bounds(
665        &mut self,
666        x: f64,
667        y: f64,
668        min_x: f64,
669        max_x: f64,
670        min_y: f64,
671        max_y: f64,
672    ) -> &mut Self {
673        self.verifier.verify_in_range("x position", x, min_x, max_x);
674        self.verifier.verify_in_range("y position", y, min_y, max_y);
675        self
676    }
677
678    /// Verify velocity is within speed limit
679    pub fn verify_speed_limit(&mut self, vx: f64, vy: f64, max_speed: f64) -> &mut Self {
680        let speed = (vx * vx + vy * vy).sqrt();
681        self.verifier
682            .verify_in_range("speed", speed, 0.0, max_speed);
683        self
684    }
685
686    /// Verify entity count invariant
687    pub fn verify_entity_count(&mut self, count: usize, expected: usize) -> &mut Self {
688        self.verifier
689            .verify_eq("entity count", expected as f64, count as f64);
690        self
691    }
692
693    /// Custom invariant check
694    pub fn verify_custom(&mut self, name: &str, expected: f64, actual: f64) -> &mut Self {
695        self.verifier.verify_eq(name, expected, actual);
696        self
697    }
698
699    /// Get the underlying verifier
700    #[must_use]
701    pub fn verifier(&self) -> &EquationVerifier {
702        &self.verifier
703    }
704
705    /// Assert all invariants hold
706    pub fn assert_all(&self) -> ProbarResult<()> {
707        self.verifier.assert_all()
708    }
709}
710
711#[cfg(test)]
712#[allow(clippy::unwrap_used, clippy::expect_used)]
713mod tests {
714    use super::*;
715
716    mod variable_tests {
717        use super::*;
718
719        #[test]
720        fn test_new() {
721            let var = Variable::new("x", 10.0);
722            assert_eq!(var.name, "x");
723            assert!((var.value - 10.0).abs() < f64::EPSILON);
724            assert!(var.unit.is_none());
725        }
726
727        #[test]
728        fn test_with_unit() {
729            let var = Variable::with_unit("velocity", 5.0, "m/s");
730            assert_eq!(var.unit, Some("m/s".to_string()));
731        }
732
733        #[test]
734        fn test_display() {
735            let var1 = Variable::new("x", 10.0);
736            assert_eq!(format!("{}", var1), "x = 10");
737
738            let var2 = Variable::with_unit("v", 5.0, "m/s");
739            assert_eq!(format!("{}", var2), "v = 5 m/s");
740        }
741    }
742
743    mod equation_context_tests {
744        use super::*;
745
746        #[test]
747        fn test_new() {
748            let ctx = EquationContext::new();
749            assert!(ctx.variables().is_empty());
750        }
751
752        #[test]
753        fn test_set_and_get() {
754            let mut ctx = EquationContext::new();
755            ctx.set("x", 10.0);
756
757            assert!(ctx.has("x"));
758            assert_eq!(ctx.get("x"), Some(10.0));
759            assert_eq!(ctx.get("y"), None);
760        }
761
762        #[test]
763        fn test_from_variables() {
764            let vars = vec![Variable::new("x", 1.0), Variable::new("y", 2.0)];
765            let ctx = EquationContext::from_variables(&vars);
766
767            assert_eq!(ctx.get("x"), Some(1.0));
768            assert_eq!(ctx.get("y"), Some(2.0));
769        }
770    }
771
772    mod equation_verifier_tests {
773        use super::*;
774
775        #[test]
776        fn test_new() {
777            let verifier = EquationVerifier::new("test");
778            assert_eq!(verifier.name(), "test");
779            assert!(verifier.results().is_empty());
780        }
781
782        #[test]
783        fn test_verify_eq_pass() {
784            let mut verifier = EquationVerifier::new("test");
785            verifier.verify_eq("1 + 1 = 2", 2.0, 2.0);
786
787            assert!(verifier.all_passed());
788            assert_eq!(verifier.passed_count(), 1);
789        }
790
791        #[test]
792        fn test_verify_eq_fail() {
793            let mut verifier = EquationVerifier::new("test");
794            verifier.verify_eq("1 + 1 = 3", 3.0, 2.0);
795
796            assert!(!verifier.all_passed());
797            assert_eq!(verifier.failed_count(), 1);
798        }
799
800        #[test]
801        fn test_verify_eq_with_tolerance() {
802            let mut verifier = EquationVerifier::new("test");
803            verifier.verify_eq_with_tolerance("approx", 1.0, 1.001, 0.01);
804
805            assert!(verifier.all_passed());
806        }
807
808        #[test]
809        fn test_verify_in_range_pass() {
810            let mut verifier = EquationVerifier::new("test");
811            verifier.verify_in_range("value", 5.0, 0.0, 10.0);
812
813            assert!(verifier.all_passed());
814        }
815
816        #[test]
817        fn test_verify_in_range_fail() {
818            let mut verifier = EquationVerifier::new("test");
819            verifier.verify_in_range("value", 15.0, 0.0, 10.0);
820
821            assert!(!verifier.all_passed());
822        }
823
824        #[test]
825        fn test_verify_non_negative_pass() {
826            let mut verifier = EquationVerifier::new("test");
827            verifier.verify_non_negative("positive", 5.0);
828            verifier.verify_non_negative("zero", 0.0);
829
830            assert!(verifier.all_passed());
831        }
832
833        #[test]
834        fn test_verify_non_negative_fail() {
835            let mut verifier = EquationVerifier::new("test");
836            verifier.verify_non_negative("negative", -5.0);
837
838            assert!(!verifier.all_passed());
839        }
840
841        #[test]
842        fn test_verify_positive_pass() {
843            let mut verifier = EquationVerifier::new("test");
844            verifier.verify_positive("positive", 5.0);
845
846            assert!(verifier.all_passed());
847        }
848
849        #[test]
850        fn test_verify_positive_fail() {
851            let mut verifier = EquationVerifier::new("test");
852            verifier.verify_positive("zero", 0.0);
853
854            assert!(!verifier.all_passed());
855        }
856
857        #[test]
858        fn test_assert_all_pass() {
859            let mut verifier = EquationVerifier::new("test");
860            verifier.verify_eq("test", 1.0, 1.0);
861
862            assert!(verifier.assert_all().is_ok());
863        }
864
865        #[test]
866        fn test_assert_all_fail() {
867            let mut verifier = EquationVerifier::new("test");
868            verifier.verify_eq("test", 1.0, 2.0);
869
870            assert!(verifier.assert_all().is_err());
871        }
872
873        #[test]
874        fn test_clear() {
875            let mut verifier = EquationVerifier::new("test");
876            verifier.verify_eq("test", 1.0, 1.0);
877            verifier.clear();
878
879            assert!(verifier.results().is_empty());
880        }
881    }
882
883    mod kinematic_verifier_tests {
884        use super::*;
885
886        #[test]
887        fn test_verify_velocity() {
888            let mut verifier = KinematicVerifier::new();
889            // v = v0 + at = 10 + 2*5 = 20
890            verifier.verify_velocity(20.0, 10.0, 2.0, 5.0);
891
892            assert!(verifier.assert_all().is_ok());
893        }
894
895        #[test]
896        fn test_verify_position() {
897            let mut verifier = KinematicVerifier::new();
898            // x = x0 + v0*t + 0.5*a*t² = 0 + 10*5 + 0.5*2*25 = 50 + 25 = 75
899            verifier.verify_position(75.0, 0.0, 10.0, 2.0, 5.0);
900
901            assert!(verifier.assert_all().is_ok());
902        }
903
904        #[test]
905        fn test_verify_velocity_squared() {
906            let mut verifier = KinematicVerifier::new();
907            // v² = v0² + 2a(x-x0) = 100 + 2*2*50 = 100 + 200 = 300
908            // v = sqrt(300) ≈ 17.32
909            let v = (300.0_f64).sqrt();
910            verifier.verify_velocity_squared(v, 10.0, 2.0, 50.0, 0.0);
911
912            assert!(verifier.assert_all().is_ok());
913        }
914
915        #[test]
916        fn test_free_fall() {
917            let mut verifier = KinematicVerifier::new();
918            let g = 9.81;
919            let t = 2.0;
920
921            // Object dropped from rest
922            let v = g * t; // v = 0 + g*t = 19.62 m/s
923            let y = 0.5 * g * t * t; // y = 0 + 0 + 0.5*g*t² = 19.62 m
924
925            verifier.verify_velocity(v, 0.0, g, t);
926            verifier.verify_position(y, 0.0, 0.0, g, t);
927
928            assert!(verifier.assert_all().is_ok());
929        }
930    }
931
932    mod energy_verifier_tests {
933        use super::*;
934
935        #[test]
936        fn test_verify_kinetic_energy() {
937            let mut verifier = EnergyVerifier::new();
938            // KE = 0.5 * m * v² = 0.5 * 2 * 9 = 9
939            verifier.verify_kinetic_energy(9.0, 2.0, 3.0);
940
941            assert!(verifier.assert_all().is_ok());
942        }
943
944        #[test]
945        fn test_verify_potential_energy() {
946            let mut verifier = EnergyVerifier::new();
947            // PE = m * g * h = 1 * 10 * 5 = 50
948            verifier.verify_potential_energy(50.0, 1.0, 10.0, 5.0);
949
950            assert!(verifier.assert_all().is_ok());
951        }
952
953        #[test]
954        fn test_verify_conservation() {
955            let mut verifier = EnergyVerifier::new();
956            // Total energy should be conserved
957            // Initial: KE=50, PE=100, Total=150
958            // Final: KE=100, PE=50, Total=150
959            verifier.verify_conservation(50.0, 100.0, 100.0, 50.0);
960
961            assert!(verifier.assert_all().is_ok());
962        }
963
964        #[test]
965        fn test_pendulum_energy() {
966            let mut verifier = EnergyVerifier::new().with_tolerance(0.01);
967            let m = 1.0;
968            let g = 9.81;
969
970            // At highest point: v=0, h=1m
971            let pe_top = m * g * 1.0;
972            let ke_top = 0.0;
973
974            // At lowest point: h=0, v=sqrt(2gh)
975            let v_bottom = (2.0_f64 * g * 1.0).sqrt();
976            let ke_bottom = 0.5 * m * v_bottom * v_bottom;
977            let pe_bottom = 0.0;
978
979            verifier.verify_conservation(ke_top, pe_top, ke_bottom, pe_bottom);
980
981            assert!(verifier.assert_all().is_ok());
982        }
983    }
984
985    mod momentum_verifier_tests {
986        use super::*;
987
988        #[test]
989        fn test_verify_momentum() {
990            let mut verifier = MomentumVerifier::new();
991            // p = m * v = 2 * 5 = 10
992            verifier.verify_momentum(10.0, 2.0, 5.0);
993
994            assert!(verifier.assert_all().is_ok());
995        }
996
997        #[test]
998        fn test_verify_conservation() {
999            let mut verifier = MomentumVerifier::new();
1000            // m1=1, v1=10, m2=1, v2=0
1001            // After collision: v1'=0, v2'=10 (perfect elastic)
1002            verifier.verify_conservation(1.0, 10.0, 1.0, 0.0, 0.0, 10.0);
1003
1004            assert!(verifier.assert_all().is_ok());
1005        }
1006
1007        #[test]
1008        fn test_verify_elastic_collision() {
1009            let mut verifier = MomentumVerifier::new();
1010            // Equal masses, one at rest: velocities exchange
1011            verifier.verify_elastic_collision(1.0, 10.0, 1.0, 0.0, 0.0, 10.0);
1012
1013            assert!(verifier.assert_all().is_ok());
1014        }
1015
1016        #[test]
1017        fn test_pong_collision() {
1018            let mut verifier = MomentumVerifier::new().with_tolerance(0.1);
1019
1020            // Pong ball hitting paddle (paddle effectively infinite mass)
1021            // Ball reverses direction, paddle doesn't move
1022            let ball_mass = 1.0;
1023            let ball_v_initial = 10.0;
1024            let ball_v_final = -10.0; // Reverses
1025
1026            // For infinite mass paddle: momentum of ball alone isn't conserved
1027            // but this simulates elastic collision with immovable object
1028            let ke_initial = 0.5 * ball_mass * ball_v_initial * ball_v_initial;
1029            let ke_final = 0.5 * ball_mass * ball_v_final * ball_v_final;
1030
1031            verifier
1032                .verifier
1033                .verify_eq("KE conserved", ke_initial, ke_final);
1034            assert!(verifier.assert_all().is_ok());
1035        }
1036    }
1037
1038    mod invariant_verifier_tests {
1039        use super::*;
1040
1041        #[test]
1042        fn test_verify_score_non_negative() {
1043            let mut verifier = InvariantVerifier::new("game");
1044            verifier.verify_score_non_negative(100.0);
1045
1046            assert!(verifier.assert_all().is_ok());
1047        }
1048
1049        #[test]
1050        fn test_verify_health() {
1051            let mut verifier = InvariantVerifier::new("game");
1052            verifier.verify_health(50.0, 100.0);
1053
1054            assert!(verifier.assert_all().is_ok());
1055        }
1056
1057        #[test]
1058        fn test_verify_position_bounds() {
1059            let mut verifier = InvariantVerifier::new("game");
1060            verifier.verify_position_bounds(400.0, 300.0, 0.0, 800.0, 0.0, 600.0);
1061
1062            assert!(verifier.assert_all().is_ok());
1063        }
1064
1065        #[test]
1066        fn test_verify_speed_limit() {
1067            let mut verifier = InvariantVerifier::new("game");
1068            verifier.verify_speed_limit(3.0, 4.0, 10.0); // speed = 5, limit = 10
1069
1070            assert!(verifier.assert_all().is_ok());
1071        }
1072
1073        #[test]
1074        fn test_verify_entity_count() {
1075            let mut verifier = InvariantVerifier::new("game");
1076            verifier.verify_entity_count(10, 10);
1077
1078            assert!(verifier.assert_all().is_ok());
1079        }
1080
1081        #[test]
1082        fn test_game_frame_invariants() {
1083            let mut verifier = InvariantVerifier::new("pong").with_tolerance(0.001);
1084
1085            // Typical Pong game state
1086            let score = 5.0;
1087            let ball_x = 400.0;
1088            let ball_y = 300.0;
1089            let ball_vx = 5.0;
1090            let ball_vy = -3.0;
1091            let max_speed = 10.0;
1092
1093            verifier
1094                .verify_score_non_negative(score)
1095                .verify_position_bounds(ball_x, ball_y, 0.0, 800.0, 0.0, 600.0)
1096                .verify_speed_limit(ball_vx, ball_vy, max_speed);
1097
1098            assert!(verifier.assert_all().is_ok());
1099        }
1100
1101        #[test]
1102        fn test_verify_custom() {
1103            let mut verifier = InvariantVerifier::new("custom");
1104            verifier.verify_custom("custom_check", 42.0, 42.0);
1105            assert!(verifier.assert_all().is_ok());
1106        }
1107
1108        #[test]
1109        fn test_invariant_verifier_accessor() {
1110            let verifier = InvariantVerifier::new("test");
1111            assert_eq!(verifier.verifier().name(), "test");
1112        }
1113    }
1114
1115    // Additional coverage tests for edge cases and uncovered branches
1116    mod additional_coverage_tests {
1117        use super::*;
1118
1119        #[test]
1120        fn test_equation_result_display() {
1121            // Test Display trait for EquationResult
1122            let result = EquationResult::new("test_eq", 1.0, 1.0, 0.001);
1123            let display = format!("{}", result);
1124            assert!(display.contains("test_eq"));
1125            assert!(display.contains("expected"));
1126        }
1127
1128        #[test]
1129        fn test_equation_result_relative_difference_zero_expected() {
1130            // Cover the branch when expected is near zero (relative_difference = 0.0)
1131            let result = EquationResult::new("zero_expected", 0.0, 0.0001, 0.001);
1132            assert!((result.relative_difference - 0.0).abs() < f64::EPSILON);
1133        }
1134
1135        #[test]
1136        fn test_equation_result_failed_message() {
1137            // Cover the failed message branch in EquationResult::new
1138            let result = EquationResult::new("fail_test", 10.0, 5.0, 0.001);
1139            assert!(!result.passed);
1140            assert!(result.message.contains("FAILED"));
1141            assert!(result.message.contains('>'));
1142        }
1143
1144        #[test]
1145        fn test_equation_verifier_tolerance_accessor() {
1146            // Test the tolerance() accessor method
1147            let verifier = EquationVerifier::new("test").with_tolerance(0.01);
1148            assert!((verifier.tolerance() - 0.01).abs() < f64::EPSILON);
1149        }
1150
1151        #[test]
1152        fn test_equation_verifier_failures() {
1153            // Test the failures() method
1154            let mut verifier = EquationVerifier::new("test");
1155            verifier.verify_eq("pass", 1.0, 1.0);
1156            verifier.verify_eq("fail1", 10.0, 5.0);
1157            verifier.verify_eq("fail2", 20.0, 15.0);
1158
1159            let failures = verifier.failures();
1160            assert_eq!(failures.len(), 2);
1161            assert!(failures.iter().any(|f| f.name == "fail1"));
1162            assert!(failures.iter().any(|f| f.name == "fail2"));
1163        }
1164
1165        #[test]
1166        fn test_verify_in_range_below_min() {
1167            // Test the branch when value < min in verify_in_range
1168            let mut verifier = EquationVerifier::new("test");
1169            verifier.verify_in_range("below_min", -5.0, 0.0, 10.0);
1170
1171            assert!(!verifier.all_passed());
1172            let result = &verifier.results()[0];
1173            assert!(!result.passed);
1174            assert!((result.difference - 5.0).abs() < f64::EPSILON);
1175            assert!(result.message.contains("outside range"));
1176        }
1177
1178        #[test]
1179        fn test_verify_positive_negative_value() {
1180            // Test verify_positive with a negative value (covers difference calculation)
1181            let mut verifier = EquationVerifier::new("test");
1182            verifier.verify_positive("negative", -5.0);
1183
1184            assert!(!verifier.all_passed());
1185            let result = &verifier.results()[0];
1186            assert!(!result.passed);
1187            assert!((result.difference - 5.0).abs() < f64::EPSILON);
1188        }
1189
1190        #[test]
1191        fn test_kinematic_verifier_default() {
1192            // Test Default implementation for KinematicVerifier
1193            let verifier = KinematicVerifier::default();
1194            assert_eq!(verifier.verifier().name(), "kinematics");
1195        }
1196
1197        #[test]
1198        fn test_kinematic_verifier_accessor() {
1199            // Test verifier() accessor for KinematicVerifier
1200            let verifier = KinematicVerifier::new();
1201            let inner = verifier.verifier();
1202            assert_eq!(inner.name(), "kinematics");
1203        }
1204
1205        #[test]
1206        fn test_energy_verifier_default() {
1207            // Test Default implementation for EnergyVerifier
1208            let verifier = EnergyVerifier::default();
1209            assert_eq!(verifier.verifier().name(), "energy");
1210        }
1211
1212        #[test]
1213        fn test_energy_verifier_work_energy() {
1214            // Test verify_work_energy method
1215            let mut verifier = EnergyVerifier::new();
1216            // Work = ΔKE = KE_final - KE_initial = 100 - 50 = 50
1217            verifier.verify_work_energy(50.0, 50.0, 100.0);
1218            assert!(verifier.assert_all().is_ok());
1219        }
1220
1221        #[test]
1222        fn test_energy_verifier_accessor() {
1223            // Test verifier() accessor for EnergyVerifier
1224            let verifier = EnergyVerifier::new();
1225            let inner = verifier.verifier();
1226            assert_eq!(inner.name(), "energy");
1227        }
1228
1229        #[test]
1230        fn test_momentum_verifier_default() {
1231            // Test Default implementation for MomentumVerifier
1232            let verifier = MomentumVerifier::default();
1233            assert_eq!(verifier.verifier().name(), "momentum");
1234        }
1235
1236        #[test]
1237        fn test_momentum_verifier_accessor() {
1238            // Test verifier() accessor for MomentumVerifier
1239            let verifier = MomentumVerifier::new();
1240            let inner = verifier.verifier();
1241            assert_eq!(inner.name(), "momentum");
1242        }
1243
1244        #[test]
1245        fn test_equation_context_chaining() {
1246            // Test chaining set() calls
1247            let mut ctx = EquationContext::new();
1248            ctx.set("a", 1.0).set("b", 2.0).set("c", 3.0);
1249
1250            assert_eq!(ctx.get("a"), Some(1.0));
1251            assert_eq!(ctx.get("b"), Some(2.0));
1252            assert_eq!(ctx.get("c"), Some(3.0));
1253        }
1254
1255        #[test]
1256        fn test_equation_context_has_missing() {
1257            // Test has() for non-existent variable
1258            let ctx = EquationContext::new();
1259            assert!(!ctx.has("missing"));
1260        }
1261
1262        #[test]
1263        fn test_equation_result_relative_difference_calculation() {
1264            // Test relative_difference calculation for non-zero expected
1265            let result = EquationResult::new("rel_diff", 100.0, 90.0, 1.0);
1266            // difference = 10, relative_difference = (10 / 100) * 100 = 10%
1267            assert!((result.relative_difference - 10.0).abs() < f64::EPSILON);
1268        }
1269
1270        #[test]
1271        fn test_verifier_chaining() {
1272            // Test chaining of verify methods
1273            let mut verifier = EquationVerifier::new("chain");
1274            verifier
1275                .verify_eq("eq1", 1.0, 1.0)
1276                .verify_eq("eq2", 2.0, 2.0)
1277                .verify_non_negative("nn", 5.0)
1278                .verify_positive("pos", 1.0)
1279                .verify_in_range("range", 5.0, 0.0, 10.0);
1280
1281            assert!(verifier.all_passed());
1282            assert_eq!(verifier.results().len(), 5);
1283        }
1284
1285        #[test]
1286        fn test_invariant_verifier_health_out_of_range() {
1287            // Test health verification when health is out of range
1288            let mut verifier = InvariantVerifier::new("game");
1289            verifier.verify_health(150.0, 100.0);
1290            assert!(verifier.assert_all().is_err());
1291        }
1292
1293        #[test]
1294        fn test_invariant_verifier_speed_exceeds_limit() {
1295            // Test speed limit verification when speed exceeds limit
1296            let mut verifier = InvariantVerifier::new("game");
1297            verifier.verify_speed_limit(8.0, 6.0, 5.0); // speed = 10, limit = 5
1298            assert!(verifier.assert_all().is_err());
1299        }
1300
1301        #[test]
1302        fn test_kinematic_verifier_with_tolerance() {
1303            // Test KinematicVerifier with custom tolerance
1304            let mut verifier = KinematicVerifier::new().with_tolerance(0.1);
1305            verifier.verify_velocity(20.05, 10.0, 2.0, 5.0);
1306            assert!(verifier.assert_all().is_ok());
1307        }
1308
1309        #[test]
1310        fn test_momentum_verifier_with_tolerance() {
1311            // Test MomentumVerifier with custom tolerance
1312            let mut verifier = MomentumVerifier::new().with_tolerance(0.1);
1313            verifier.verify_momentum(10.05, 2.0, 5.0);
1314            assert!(verifier.assert_all().is_ok());
1315        }
1316
1317        #[test]
1318        fn test_invariant_verifier_with_tolerance() {
1319            // Test InvariantVerifier with custom tolerance
1320            let mut verifier = InvariantVerifier::new("test").with_tolerance(0.1);
1321            verifier.verify_custom("approx", 10.0, 10.05);
1322            assert!(verifier.assert_all().is_ok());
1323        }
1324
1325        #[test]
1326        fn test_kinematic_verifier_failed_assertion() {
1327            // Test KinematicVerifier assert_all when failing
1328            let mut verifier = KinematicVerifier::new();
1329            verifier.verify_velocity(100.0, 10.0, 2.0, 5.0); // Expected: 20, got: 100
1330            assert!(verifier.assert_all().is_err());
1331        }
1332
1333        #[test]
1334        fn test_energy_verifier_failed_assertion() {
1335            // Test EnergyVerifier assert_all when failing
1336            let mut verifier = EnergyVerifier::new();
1337            verifier.verify_kinetic_energy(100.0, 2.0, 3.0); // Expected: 9, got: 100
1338            assert!(verifier.assert_all().is_err());
1339        }
1340
1341        #[test]
1342        fn test_momentum_verifier_failed_assertion() {
1343            // Test MomentumVerifier assert_all when failing
1344            let mut verifier = MomentumVerifier::new();
1345            verifier.verify_momentum(100.0, 2.0, 5.0); // Expected: 10, got: 100
1346            assert!(verifier.assert_all().is_err());
1347        }
1348
1349        #[test]
1350        fn test_invariant_verifier_failed_assertion() {
1351            // Test InvariantVerifier assert_all when failing
1352            let mut verifier = InvariantVerifier::new("test");
1353            verifier.verify_score_non_negative(-10.0);
1354            assert!(verifier.assert_all().is_err());
1355        }
1356
1357        #[test]
1358        fn test_verify_in_range_at_boundaries() {
1359            // Test verify_in_range at exact boundary values
1360            let mut verifier = EquationVerifier::new("boundaries");
1361            verifier.verify_in_range("at_min", 0.0, 0.0, 10.0);
1362            verifier.verify_in_range("at_max", 10.0, 0.0, 10.0);
1363            assert!(verifier.all_passed());
1364        }
1365
1366        #[test]
1367        fn test_equation_context_variables_list() {
1368            // Test variables() accessor
1369            let mut ctx = EquationContext::new();
1370            ctx.set("x", 1.0).set("y", 2.0);
1371
1372            let vars = ctx.variables();
1373            assert_eq!(vars.len(), 2);
1374            assert!(vars.contains(&"x"));
1375            assert!(vars.contains(&"y"));
1376        }
1377
1378        #[test]
1379        fn test_equation_verifier_empty_results() {
1380            // Test all_passed and failures on empty verifier
1381            let verifier = EquationVerifier::new("empty");
1382            assert!(verifier.all_passed()); // No failures means all passed
1383            assert!(verifier.failures().is_empty());
1384            assert_eq!(verifier.passed_count(), 0);
1385            assert_eq!(verifier.failed_count(), 0);
1386        }
1387
1388        #[test]
1389        fn test_equation_context_from_empty_variables() {
1390            // Test from_variables with empty slice
1391            let vars: Vec<Variable> = vec![];
1392            let ctx = EquationContext::from_variables(&vars);
1393            assert!(ctx.variables().is_empty());
1394        }
1395
1396        #[test]
1397        fn test_variable_clone() {
1398            // Test Clone for Variable
1399            let var1 = Variable::with_unit("velocity", 10.0, "m/s");
1400            let var2 = var1;
1401            assert_eq!(var2.name, "velocity");
1402            assert!((var2.value - 10.0).abs() < f64::EPSILON);
1403            assert_eq!(var2.unit, Some("m/s".to_string()));
1404        }
1405
1406        #[test]
1407        fn test_equation_context_clone() {
1408            // Test Clone for EquationContext
1409            let mut ctx1 = EquationContext::new();
1410            ctx1.set("x", 5.0);
1411            let ctx2 = ctx1.clone();
1412            assert_eq!(ctx2.get("x"), Some(5.0));
1413        }
1414
1415        #[test]
1416        fn test_equation_result_clone() {
1417            // Test Clone for EquationResult
1418            let result1 = EquationResult::new("clone_test", 10.0, 10.0, 0.001);
1419            let result2 = result1;
1420            assert_eq!(result2.name, "clone_test");
1421            assert!(result2.passed);
1422        }
1423
1424        #[test]
1425        fn test_equation_verifier_multiple_failures() {
1426            // Test verifier with multiple failures shows all in assert_all error
1427            let mut verifier = EquationVerifier::new("multi_fail");
1428            verifier.verify_eq("fail1", 1.0, 100.0);
1429            verifier.verify_eq("fail2", 2.0, 200.0);
1430            verifier.verify_eq("fail3", 3.0, 300.0);
1431
1432            let result = verifier.assert_all();
1433            assert!(result.is_err());
1434            if let Err(ProbarError::AssertionFailed { message }) = result {
1435                assert!(message.contains("fail1"));
1436                assert!(message.contains("fail2"));
1437                assert!(message.contains("fail3"));
1438            }
1439        }
1440
1441        #[test]
1442        fn test_verify_in_range_message_passed() {
1443            // Verify the message format when in_range passes
1444            let mut verifier = EquationVerifier::new("test");
1445            verifier.verify_in_range("in_bounds", 5.0, 0.0, 10.0);
1446
1447            let result = &verifier.results()[0];
1448            assert!(result.message.contains("is within"));
1449        }
1450
1451        #[test]
1452        fn test_verify_non_negative_message() {
1453            // Verify message format for non_negative
1454            let mut verifier = EquationVerifier::new("test");
1455            verifier.verify_non_negative("positive_val", 5.0);
1456
1457            let result = &verifier.results()[0];
1458            assert!(result.message.contains(">= 0"));
1459        }
1460
1461        #[test]
1462        fn test_verify_positive_message() {
1463            // Verify message format for positive
1464            let mut verifier = EquationVerifier::new("test");
1465            verifier.verify_positive("pos_val", 5.0);
1466
1467            let result = &verifier.results()[0];
1468            assert!(result.message.contains("> 0"));
1469        }
1470
1471        #[test]
1472        fn test_equation_result_all_fields() {
1473            // Test all fields of EquationResult are correctly set
1474            let result = EquationResult::new("field_test", 100.0, 95.0, 1.0);
1475            assert_eq!(result.name, "field_test");
1476            assert!(!result.passed); // 5.0 > 1.0 tolerance
1477            assert!((result.expected - 100.0).abs() < f64::EPSILON);
1478            assert!((result.actual - 95.0).abs() < f64::EPSILON);
1479            assert!((result.tolerance - 1.0).abs() < f64::EPSILON);
1480            assert!((result.difference - 5.0).abs() < f64::EPSILON);
1481            assert!((result.relative_difference - 5.0).abs() < f64::EPSILON); // 5%
1482        }
1483
1484        #[test]
1485        fn test_energy_verifier_conservation_fails() {
1486            // Test energy conservation failure
1487            let mut verifier = EnergyVerifier::new();
1488            verifier.verify_conservation(50.0, 100.0, 80.0, 80.0); // 150 != 160
1489            assert!(verifier.assert_all().is_err());
1490        }
1491
1492        #[test]
1493        fn test_kinematic_verifier_position_fails() {
1494            // Test position verification failure
1495            let mut verifier = KinematicVerifier::new();
1496            verifier.verify_position(100.0, 0.0, 10.0, 2.0, 5.0); // Expected: 75, got: 100
1497            assert!(verifier.assert_all().is_err());
1498        }
1499
1500        #[test]
1501        fn test_kinematic_verifier_velocity_squared_fails() {
1502            // Test velocity squared verification failure
1503            let mut verifier = KinematicVerifier::new();
1504            verifier.verify_velocity_squared(100.0, 10.0, 2.0, 50.0, 0.0); // Expected v²=300, v=100 gives v²=10000
1505            assert!(verifier.assert_all().is_err());
1506        }
1507
1508        #[test]
1509        fn test_momentum_conservation_fails() {
1510            // Test momentum conservation failure
1511            let mut verifier = MomentumVerifier::new();
1512            verifier.verify_conservation(1.0, 10.0, 1.0, 0.0, 5.0, 3.0); // p_initial=10, p_final=8
1513            assert!(verifier.assert_all().is_err());
1514        }
1515
1516        #[test]
1517        fn test_elastic_collision_ke_fails() {
1518            // Test elastic collision where KE is not conserved
1519            let mut verifier = MomentumVerifier::new();
1520            // Momentum conserved but KE not (inelastic collision)
1521            verifier.verify_elastic_collision(1.0, 10.0, 1.0, 0.0, 5.0, 5.0);
1522            assert!(verifier.assert_all().is_err());
1523        }
1524
1525        #[test]
1526        fn test_invariant_entity_count_fails() {
1527            // Test entity count mismatch
1528            let mut verifier = InvariantVerifier::new("game");
1529            verifier.verify_entity_count(5, 10);
1530            assert!(verifier.assert_all().is_err());
1531        }
1532
1533        #[test]
1534        fn test_invariant_position_out_of_bounds() {
1535            // Test position bounds failure
1536            let mut verifier = InvariantVerifier::new("game");
1537            verifier.verify_position_bounds(900.0, 700.0, 0.0, 800.0, 0.0, 600.0);
1538            assert!(verifier.assert_all().is_err());
1539        }
1540
1541        #[test]
1542        fn test_verify_negative_value_non_negative() {
1543            // Verify the difference calculation for negative values in non_negative
1544            let mut verifier = EquationVerifier::new("test");
1545            verifier.verify_non_negative("neg", -10.0);
1546
1547            let result = &verifier.results()[0];
1548            assert!((result.difference - 10.0).abs() < f64::EPSILON);
1549            assert!(result.message.contains("< 0"));
1550        }
1551
1552        #[test]
1553        fn test_verifier_debug_impl() {
1554            // Test Debug implementation for EquationVerifier
1555            let verifier = EquationVerifier::new("debug_test");
1556            let debug_str = format!("{:?}", verifier);
1557            assert!(debug_str.contains("debug_test"));
1558        }
1559
1560        #[test]
1561        fn test_kinematic_verifier_debug_impl() {
1562            // Test Debug implementation for KinematicVerifier
1563            let verifier = KinematicVerifier::new();
1564            let debug_str = format!("{:?}", verifier);
1565            assert!(debug_str.contains("KinematicVerifier"));
1566        }
1567
1568        #[test]
1569        fn test_energy_verifier_debug_impl() {
1570            // Test Debug implementation for EnergyVerifier
1571            let verifier = EnergyVerifier::new();
1572            let debug_str = format!("{:?}", verifier);
1573            assert!(debug_str.contains("EnergyVerifier"));
1574        }
1575
1576        #[test]
1577        fn test_momentum_verifier_debug_impl() {
1578            // Test Debug implementation for MomentumVerifier
1579            let verifier = MomentumVerifier::new();
1580            let debug_str = format!("{:?}", verifier);
1581            assert!(debug_str.contains("MomentumVerifier"));
1582        }
1583
1584        #[test]
1585        fn test_invariant_verifier_debug_impl() {
1586            // Test Debug implementation for InvariantVerifier
1587            let verifier = InvariantVerifier::new("test");
1588            let debug_str = format!("{:?}", verifier);
1589            assert!(debug_str.contains("InvariantVerifier"));
1590        }
1591
1592        #[test]
1593        fn test_variable_debug_impl() {
1594            // Test Debug implementation for Variable
1595            let var = Variable::new("x", 5.0);
1596            let debug_str = format!("{:?}", var);
1597            assert!(debug_str.contains("Variable"));
1598        }
1599
1600        #[test]
1601        fn test_equation_context_debug_impl() {
1602            // Test Debug implementation for EquationContext
1603            let ctx = EquationContext::new();
1604            let debug_str = format!("{:?}", ctx);
1605            assert!(debug_str.contains("EquationContext"));
1606        }
1607
1608        #[test]
1609        fn test_equation_result_debug_impl() {
1610            // Test Debug implementation for EquationResult
1611            let result = EquationResult::new("test", 1.0, 1.0, 0.001);
1612            let debug_str = format!("{:?}", result);
1613            assert!(debug_str.contains("EquationResult"));
1614        }
1615
1616        #[test]
1617        fn test_equation_context_default() {
1618            // Test Default implementation for EquationContext
1619            let ctx = EquationContext::default();
1620            assert!(ctx.variables().is_empty());
1621        }
1622
1623        #[test]
1624        fn test_energy_work_energy_fails() {
1625            // Test work-energy theorem failure
1626            let mut verifier = EnergyVerifier::new();
1627            verifier.verify_work_energy(100.0, 50.0, 100.0); // W=100, ΔKE=50, should fail
1628            assert!(verifier.assert_all().is_err());
1629        }
1630    }
1631}