use mockall::mock; use mockall::predicate::{always, eq}; use paste::paste; mod common; macro_rules! impl_test { ($fn: ident) => { paste! { #[test] fn []() { let mut a = NamedStructSameType { x: MockA::new(), y: MockA::new(), z: MockA::new(), }; let b = NamedStructSameType { x: MockA::new(), y: MockA::new(), z: MockA::new(), }; a.x.[]() .with(always(), eq(0.1)) .times(1) .return_const(true); a.y.[]() .with(always(), eq(0.1)) .times(1) .return_const(true); a.z.[]() .with(always(), eq(0.1)) .times(1) .return_const(true); assert!(a.[](&b, &0.1_f32)); a.x.checkpoint(); a.y.checkpoint(); a.z.checkpoint(); a.x.[]() .with(always(), eq(0.1)) .times(1) .return_const(false); a.y.[]().times(0); a.z.[]().times(0); assert!(!a.[](&b, &0.1_f32)); a.x.checkpoint(); a.y.checkpoint(); a.z.checkpoint(); a.x.[]() .with(always(), eq(0.1)) .times(1) .return_const(true); a.y.[]() .with(always(), eq(0.1)) .times(1) .return_const(false); a.z.[]().times(0); assert!(!a.[](&b, &0.1_f32)); a.x.checkpoint(); a.y.checkpoint(); a.z.checkpoint(); a.x.[]() .with(always(), eq(0.1)) .times(1) .return_const(true); a.y.[]() .with(always(), eq(0.1)) .times(1) .return_const(true); a.z.[]() .with(always(), eq(0.1)) .times(1) .return_const(false); assert!(!a.[](&b, &0.1_f32)); } #[test] fn []() { let mut a = UnnamedStructSameType(MockA::new(), MockA::new(), MockA::new()); let b = UnnamedStructSameType(MockA::new(), MockA::new(), MockA::new()); a.0.[]() .with(always(), eq(0.1)) .times(1) .return_const(true); a.1.[]() .with(always(), eq(0.1)) .times(1) .return_const(true); a.2.[]() .with(always(), eq(0.1)) .times(1) .return_const(true); assert!(a.[](&b, &0.1_f32)); a.0.checkpoint(); a.1.checkpoint(); a.2.checkpoint(); a.0.[]() .with(always(), eq(0.1)) .times(1) .return_const(false); a.1.[]().times(0); a.2.[]().times(0); assert!(!a.[](&b, &0.1_f32)); a.0.checkpoint(); a.1.checkpoint(); a.2.checkpoint(); a.0.[]() .with(always(), eq(0.1)) .times(1) .return_const(true); a.1.[]() .with(always(), eq(0.1)) .times(1) .return_const(false); a.2.[]().times(0); assert!(!a.[](&b, &0.1_f32)); a.0.checkpoint(); a.1.checkpoint(); a.2.checkpoint(); a.0.[]() .with(always(), eq(0.1)) .times(1) .return_const(true); a.1.[]() .with(always(), eq(0.1)) .times(1) .return_const(true); a.2.[]() .with(always(), eq(0.1)) .times(1) .return_const(false); assert!(!a.[](&b, &0.1_f32)); } #[test] fn []() { let mut a = NamedStructDifferentType { x: MockA::new(), y: MockB::new(), z: NamedPair { a: MockA::new(), b: MockB::new(), }, }; let b = NamedStructDifferentType { x: MockA::new(), y: MockB::new(), z: NamedPair { a: MockA::new(), b: MockB::new(), }, }; let eps = (0.1_f32, 0.01_f64, (0.2_f32, 0.02_f64)); a.x.[]() .with(always(), eq(0.1)) .times(1) .return_const(true); a.y.[]() .with(always(), eq(0.01)) .times(1) .return_const(true); a.z.a .[]() .with(always(), eq(0.2)) .times(1) .return_const(true); a.z.b .[]() .with(always(), eq(0.02)) .times(1) .return_const(true); assert!(a.[](&b, &eps)); a.x.checkpoint(); a.y.checkpoint(); a.z.a.checkpoint(); a.z.b.checkpoint(); a.x.[]() .with(always(), eq(0.1)) .times(1) .return_const(false); a.y.[]().times(0); a.z.a.[]().times(0); a.z.b.[]().times(0); assert!(!a.[](&b, &eps)); a.x.checkpoint(); a.y.checkpoint(); a.z.a.checkpoint(); a.z.b.checkpoint(); a.x.[]() .with(always(), eq(0.1)) .times(1) .return_const(true); a.y.[]() .with(always(), eq(0.01)) .times(1) .return_const(false); a.z.a.[]().times(0); a.z.b.[]().times(0); assert!(!a.[](&b, &eps)); a.x.checkpoint(); a.y.checkpoint(); a.z.a.checkpoint(); a.z.b.checkpoint(); a.x.[]() .with(always(), eq(0.1)) .times(1) .return_const(true); a.y.[]() .with(always(), eq(0.01)) .times(1) .return_const(true); a.z.a .[]() .with(always(), eq(0.2)) .times(1) .return_const(false); a.z.b.[]().times(0); assert!(!a.[](&b, &eps)); a.x.checkpoint(); a.y.checkpoint(); a.z.a.checkpoint(); a.z.b.checkpoint(); a.x.[]() .with(always(), eq(0.1)) .times(1) .return_const(true); a.y.[]() .with(always(), eq(0.01)) .times(1) .return_const(true); a.z.a .[]() .with(always(), eq(0.2)) .times(1) .return_const(true); a.z.b .[]() .with(always(), eq(0.02)) .times(1) .return_const(false); assert!(!a.[](&b, &eps)); } #[test] fn []() { let mut a = UnnamedStructDifferentType( MockA::new(), MockB::new(), UnnamedPair(MockA::new(), MockB::new()), ); let b = UnnamedStructDifferentType( MockA::new(), MockB::new(), UnnamedPair(MockA::new(), MockB::new()), ); let eps = (0.1_f32, 0.01_f64, (0.2_f32, 0.02_f64)); a.0.[]() .with(always(), eq(0.1)) .times(1) .return_const(true); a.1.[]() .with(always(), eq(0.01)) .times(1) .return_const(true); a.2 .0 .[]() .with(always(), eq(0.2)) .times(1) .return_const(true); a.2 .1 .[]() .with(always(), eq(0.02)) .times(1) .return_const(true); assert!(a.[](&b, &eps)); a.0.checkpoint(); a.1.checkpoint(); a.2 .0.checkpoint(); a.2 .1.checkpoint(); a.0.[]() .with(always(), eq(0.1)) .times(1) .return_const(false); a.1.[]().times(0); a.2 .0.[]().times(0); a.2 .1.[]().times(0); assert!(!a.[](&b, &eps)); a.0.checkpoint(); a.1.checkpoint(); a.2 .0.checkpoint(); a.2 .1.checkpoint(); a.0.[]() .with(always(), eq(0.1)) .times(1) .return_const(true); a.1.[]() .with(always(), eq(0.01)) .times(1) .return_const(false); a.2 .0.[]().times(0); a.2 .1.[]().times(0); assert!(!a.[](&b, &eps)); a.0.checkpoint(); a.1.checkpoint(); a.2 .0.checkpoint(); a.2 .1.checkpoint(); a.0.[]() .with(always(), eq(0.1)) .times(1) .return_const(true); a.1.[]() .with(always(), eq(0.01)) .times(1) .return_const(true); a.2 .0 .[]() .with(always(), eq(0.2)) .times(1) .return_const(false); a.2 .1.[]().times(0); assert!(!a.[](&b, &eps)); a.0.checkpoint(); a.1.checkpoint(); a.2 .0.checkpoint(); a.2 .1.checkpoint(); a.0.[]() .with(always(), eq(0.1)) .times(1) .return_const(true); a.1.[]() .with(always(), eq(0.01)) .times(1) .return_const(true); a.2 .0 .[]() .with(always(), eq(0.2)) .times(1) .return_const(true); a.2 .1 .[]() .with(always(), eq(0.02)) .times(1) .return_const(false); assert!(!a.[](&b, &eps)); } #[test] fn []() { let a = UnitStruct; let b = UnitStruct; assert!(a.[](&b, &())); } #[test] fn []() { let mut a = EnumSameType::X(MockA::new()); let mut b = EnumSameType::X(MockA::new()); let c = EnumSameType::Y; let d = EnumSameType::Y; let mut e = EnumSameType::Z(MockA::new()); let f = EnumSameType::Z(MockA::new()); inner_value!(a, EnumSameType::X) .[]() .with(always(), eq(0.1)) .times(1) .return_const(true); assert!(a.[](&b, &0.1_f32)); inner_value!(a, EnumSameType::X).checkpoint(); inner_value!(a, EnumSameType::X) .[]() .with(always(), eq(0.1)) .times(1) .return_const(false); assert!(!a.[](&b, &0.1_f32)); inner_value!(b, EnumSameType::X) .[]() .times(0); assert!(!b.[](&c, &0.1_f32)); assert!(c.[](&d, &0.1_f32)); assert!(!b.[](&e, &0.1_f32)); assert!(!c.[](&e, &0.1_f32)); inner_value!(e, EnumSameType::Z) .[]() .with(always(), eq(0.1)) .times(1) .return_const(true); assert!(e.[](&f, &0.1_f32)); inner_value!(e, EnumSameType::Z).checkpoint(); inner_value!(e, EnumSameType::Z) .[]() .with(always(), eq(0.1)) .times(1) .return_const(false); assert!(!e.[](&f, &0.1_f32)); } #[test] fn []() { let mut a = EnumDifferentType::X(MockA::new()); let mut b = EnumDifferentType::X(MockA::new()); let c = EnumDifferentType::Y; let d = EnumDifferentType::Y; let mut e = EnumDifferentType::Z(MockB::new()); let f = EnumDifferentType::Z(MockB::new()); let eps = (0.1_f32, 0.01_f64); inner_value!(a, EnumDifferentType::X) .[]() .with(always(), eq(0.1)) .times(1) .return_const(true); assert!(a.[](&b, &eps)); inner_value!(a, EnumDifferentType::X).checkpoint(); inner_value!(a, EnumDifferentType::X) .[]() .with(always(), eq(0.1)) .times(1) .return_const(false); assert!(!a.[](&b, &eps)); inner_value!(b, EnumDifferentType::X) .[]() .times(0); assert!(!b.[](&c, &eps)); assert!(c.[](&d, &eps)); assert!(!b.[](&e, &eps)); assert!(!c.[](&e, &eps)); inner_value!(e, EnumDifferentType::Z) .[]() .with(always(), eq(0.01)) .times(1) .return_const(true); assert!(e.[](&f, &eps)); inner_value!(e, EnumDifferentType::Z).checkpoint(); inner_value!(e, EnumDifferentType::Z) .[]() .with(always(), eq(0.01)) .times(1) .return_const(false); assert!(!e.[](&f, &eps)); } } }; } mod nearly_eq { use super::*; use nearly::{EpsTolerance, EpsToleranceType, NearlyEqEps}; mock!( pub A{} impl EpsTolerance for A { type T = f32; const DEFAULT: f32 = 0.5; } impl NearlyEqEps for A { fn nearly_eq_eps(&self, other: &Self, eps: &EpsToleranceType) -> bool; } ); mock!( pub B{} impl EpsTolerance for B { type T = f64; const DEFAULT: f64 = 0.05; } impl NearlyEqEps for B { fn nearly_eq_eps(&self, other: &Self, eps: &EpsToleranceType) -> bool; } ); #[derive(NearlyEqEps)] struct NamedStructSameType { x: MockA, y: MockA, z: MockA, } #[derive(NearlyEqEps)] struct UnnamedStructSameType(MockA, MockA, MockA); #[derive(NearlyEqEps)] struct NamedPair { a: MockA, b: MockB, } #[derive(NearlyEqEps)] struct NamedStructDifferentType { x: MockA, y: MockB, z: NamedPair, } #[derive(NearlyEqEps)] struct UnnamedPair(MockA, MockB); #[derive(NearlyEqEps)] struct UnnamedStructDifferentType(MockA, MockB, UnnamedPair); #[derive(NearlyEqEps)] struct UnitStruct; #[derive(NearlyEqEps)] enum EnumSameType { X(MockA), Y, Z(MockA), } #[derive(NearlyEqEps)] enum EnumDifferentType { X(MockA), Y, Z(MockB), } impl_test!(eq); } mod nearly_ord { use super::*; use nearly::{EpsTolerance, EpsToleranceType, NearlyEqEps, NearlyOrdEps}; mock!( pub A{} impl EpsTolerance for A { type T = f32; const DEFAULT: f32 = 0.5; } impl NearlyEqEps for A { fn nearly_eq_eps(&self, other: &Self, eps: &EpsToleranceType) -> bool; } impl NearlyOrdEps for A { fn nearly_lt_eps(&self, other: &Self, eps: &EpsToleranceType) -> bool; fn nearly_le_eps(&self, other: &Self, eps: &EpsToleranceType) -> bool; fn nearly_gt_eps(&self, other: &Self, eps: &EpsToleranceType) -> bool; fn nearly_ge_eps(&self, other: &Self, eps: &EpsToleranceType) -> bool; } ); mock!( pub B{} impl EpsTolerance for B { type T = f64; const DEFAULT: f64 = 0.05; } impl NearlyEqEps for B { fn nearly_eq_eps(&self, other: &Self, eps: &EpsToleranceType) -> bool; } impl NearlyOrdEps for B { fn nearly_lt_eps(&self, other: &Self, eps: &EpsToleranceType) -> bool; fn nearly_le_eps(&self, other: &Self, eps: &EpsToleranceType) -> bool; fn nearly_gt_eps(&self, other: &Self, eps: &EpsToleranceType) -> bool; fn nearly_ge_eps(&self, other: &Self, eps: &EpsToleranceType) -> bool; } ); #[derive(NearlyEqEps, NearlyOrdEps)] struct NamedStructSameType { x: MockA, y: MockA, z: MockA, } #[derive(NearlyEqEps, NearlyOrdEps)] struct UnnamedStructSameType(MockA, MockA, MockA); #[derive(NearlyEqEps, NearlyOrdEps)] struct NamedPair { a: MockA, b: MockB, } #[derive(NearlyEqEps, NearlyOrdEps)] struct NamedStructDifferentType { x: MockA, y: MockB, z: NamedPair, } #[derive(NearlyEqEps, NearlyOrdEps)] struct UnnamedPair(MockA, MockB); #[derive(NearlyEqEps, NearlyOrdEps)] struct UnnamedStructDifferentType(MockA, MockB, UnnamedPair); #[derive(NearlyEqEps, NearlyOrdEps)] struct UnitStruct; #[derive(NearlyEqEps, NearlyOrdEps)] enum EnumSameType { X(MockA), Y, Z(MockA), } #[derive(NearlyEqEps, NearlyOrdEps)] enum EnumDifferentType { X(MockA), Y, Z(MockB), } impl_test!(lt); impl_test!(le); impl_test!(gt); impl_test!(ge); }