]> git.proxmox.com Git - proxmox.git/commitdiff
api: add test-harness feature
authorWolfgang Bumiller <w.bumiller@proxmox.com>
Wed, 8 Jan 2020 09:22:41 +0000 (10:22 +0100)
committerWolfgang Bumiller <w.bumiller@proxmox.com>
Wed, 8 Jan 2020 09:38:30 +0000 (10:38 +0100)
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 <w.bumiller@proxmox.com>
proxmox-api/Cargo.toml
proxmox-api/src/const_regex.rs
proxmox-api/src/router.rs
proxmox-api/src/schema.rs

index 827b83acad3cfd75a26bb487c10725b9497ca53d..dbc48e8376d0d8fba32844f775ec3db65c2a76e3 100644 (file)
@@ -28,3 +28,4 @@ lazy_static = "1.4"
 default = [ "router", "cli" ]
 router = [ "hyper", "tokio" ]
 cli = [ "router", "hyper", "tokio" ]
+test-harness = []
index 32d810c5bf2c72012abb33fb6bfe0ff8576b6d8f..f364498594a05cc76496c2d5fdaa65ae2af867c8 100644 (file)
@@ -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
+    }
+}
index 72b14f333e33a98940b2b6d42ecfcb450e71d032..e8aa60269d9e51cead8234abcb1399dfa06ba770 100644 (file)
@@ -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.
index ad31467817ab16013c3f4a88493a44b8b779aeb4..df0a0cab2b8b362d194d985581bb393e6f3965eb 100644 (file)
@@ -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<f64>, r: Option<f64>) -> 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`