From b0ef405186651e8ab54e283c44ccc5bb22bee0dd Mon Sep 17 00:00:00 2001 From: Wolfgang Bumiller Date: Wed, 8 Jan 2020 10:22:41 +0100 Subject: [PATCH] api: add test-harness feature If enabled, the Schema type implements Eq and PartialEq for testing the api macro better. Note that these implementations don't make all too much since since they also compare `dyn Fn` types which do not implement Eq. Since they're also `&'static` they can't really be runtime closures, so this should be fine, we know they'll always point to some regular function. Signed-off-by: Wolfgang Bumiller --- proxmox-api/Cargo.toml | 1 + proxmox-api/src/const_regex.rs | 10 ++++++++ proxmox-api/src/router.rs | 24 ++++++++++++++++++ proxmox-api/src/schema.rs | 45 ++++++++++++++++++++++++++++++++++ 4 files changed, 80 insertions(+) diff --git a/proxmox-api/Cargo.toml b/proxmox-api/Cargo.toml index 827b83ac..dbc48e83 100644 --- a/proxmox-api/Cargo.toml +++ b/proxmox-api/Cargo.toml @@ -28,3 +28,4 @@ lazy_static = "1.4" default = [ "router", "cli" ] router = [ "hyper", "tokio" ] cli = [ "router", "hyper", "tokio" ] +test-harness = [] diff --git a/proxmox-api/src/const_regex.rs b/proxmox-api/src/const_regex.rs index 32d810c5..f3644985 100644 --- a/proxmox-api/src/const_regex.rs +++ b/proxmox-api/src/const_regex.rs @@ -67,3 +67,13 @@ macro_rules! const_regex { $crate::const_regex! { $($rest)* } }; } + +#[cfg(feature = "test-harness")] +impl Eq for ConstRegexPattern {} + +#[cfg(feature = "test-harness")] +impl PartialEq for ConstRegexPattern { + fn eq(&self, rhs: &Self) -> bool { + self.regex_string == rhs.regex_string + } +} diff --git a/proxmox-api/src/router.rs b/proxmox-api/src/router.rs index 72b14f33..e8aa6026 100644 --- a/proxmox-api/src/router.rs +++ b/proxmox-api/src/router.rs @@ -124,6 +124,29 @@ pub enum ApiHandler { AsyncHttp(ApiAsyncHttpHandlerFn), } +#[cfg(feature = "test-harness")] +impl Eq for ApiHandler {} + +#[cfg(feature = "test-harness")] +impl PartialEq for ApiHandler { + fn eq(&self, rhs: &Self) -> bool { + unsafe { + match (self, rhs) { + (ApiHandler::Sync(l), ApiHandler::Sync(r)) => { + core::mem::transmute::<_, usize>(l) == core::mem::transmute::<_, usize>(r) + } + (ApiHandler::Async(l), ApiHandler::Async(r)) => { + core::mem::transmute::<_, usize>(l) == core::mem::transmute::<_, usize>(r) + } + (ApiHandler::AsyncHttp(l), ApiHandler::AsyncHttp(r)) => { + core::mem::transmute::<_, usize>(l) == core::mem::transmute::<_, usize>(r) + } + _ => false, + } + } + } +} + /// Lookup table to child `Router`s /// /// Stores a sorted list of `(name, router)` tuples: @@ -361,6 +384,7 @@ fn dummy_handler_fn( const DUMMY_HANDLER: ApiHandler = ApiHandler::Sync(&dummy_handler_fn); /// This struct defines synchronous API call which returns the restulkt as json `Value` +#[cfg_attr(feature = "test-harness", derive(Eq, PartialEq))] pub struct ApiMethod { /// The protected flag indicates that the provides function should be forwarded /// to the deaemon running in priviledged mode. diff --git a/proxmox-api/src/schema.rs b/proxmox-api/src/schema.rs index ad314678..df0a0cab 100644 --- a/proxmox-api/src/schema.rs +++ b/proxmox-api/src/schema.rs @@ -65,6 +65,7 @@ impl fmt::Display for ParameterError { /// Data type to describe boolean values #[derive(Debug)] +#[cfg_attr(feature = "test-harness", derive(Eq, PartialEq))] pub struct BooleanSchema { pub description: &'static str, /// Optional default value. @@ -91,6 +92,7 @@ impl BooleanSchema { /// Data type to describe integer values. #[derive(Debug)] +#[cfg_attr(feature = "test-harness", derive(Eq, PartialEq))] pub struct IntegerSchema { pub description: &'static str, /// Optional minimum. @@ -221,8 +223,30 @@ impl NumberSchema { } } +#[cfg(feature = "test-harness")] +impl Eq for NumberSchema {} + +#[cfg(feature = "test-harness")] +impl PartialEq for NumberSchema { + fn eq(&self, rhs: &Self) -> bool { + fn f64_eq(l: Option, r: Option) -> bool { + match (l, r) { + (None, None) => true, + (Some(l), Some(r)) => (l - r).abs() < 0.0001, + _ => false, + } + } + + self.description == rhs.description + && f64_eq(self.minimum, rhs.minimum) + && f64_eq(self.maximum, rhs.maximum) + && f64_eq(self.default, rhs.default) + } +} + /// Data type to describe string values. #[derive(Debug)] +#[cfg_attr(feature = "test-harness", derive(Eq, PartialEq))] pub struct StringSchema { pub description: &'static str, /// Optional default value. @@ -319,6 +343,7 @@ impl StringSchema { /// All array elements are of the same type, as defined in the `items` /// schema. #[derive(Debug)] +#[cfg_attr(feature = "test-harness", derive(Eq, PartialEq))] pub struct ArraySchema { pub description: &'static str, /// Element type schema. @@ -386,6 +411,7 @@ pub type SchemaPropertyMap = &'static [(&'static str, bool, &'static Schema)]; /// Data type to describe objects (maps). #[derive(Debug)] +#[cfg_attr(feature = "test-harness", derive(Eq, PartialEq))] pub struct ObjectSchema { pub description: &'static str, /// If set, allow additional properties which are not defined in @@ -464,6 +490,7 @@ impl ObjectSchema { /// ).schema(); /// ``` #[derive(Debug)] +#[cfg_attr(feature = "test-harness", derive(Eq, PartialEq))] pub enum Schema { Null, Boolean(BooleanSchema), @@ -556,6 +583,24 @@ impl std::fmt::Debug for ApiStringFormat { } } +#[cfg(feature = "test-harness")] +impl Eq for ApiStringFormat {} + +#[cfg(feature = "test-harness")] +impl PartialEq for ApiStringFormat { + fn eq(&self, rhs: &Self) -> bool { + match (self, rhs) { + (ApiStringFormat::Enum(l), ApiStringFormat::Enum(r)) => l == r, + (ApiStringFormat::Pattern(l), ApiStringFormat::Pattern(r)) => l == r, + (ApiStringFormat::PropertyString(l), ApiStringFormat::PropertyString(r)) => l == r, + (ApiStringFormat::VerifyFn(l), ApiStringFormat::VerifyFn(r)) => { + (l as *const fn(&str) -> _ as usize) == (r as *const fn(&str) -> _ as usize) + } + (_, _) => false, + } + } +} + /// Helper function to parse boolean values /// /// - true: `1 | on | yes | true` -- 2.39.5