From 00254d60e31b5c14d9a3e5cc176648700a4cb59d Mon Sep 17 00:00:00 2001 From: Christian Ebner Date: Thu, 28 Nov 2024 17:07:20 +0100 Subject: [PATCH] api types: version: implement traits to allow for version comparison Derive and implement the traits to allow comparison of two `ApiVersion` instances for more direct and easy api version comparisons. Further, add some basic test cases to reduce risk of regressions. This is useful for e.g. feature compatibility checks by comparing api versions of remote instances. Example comparison: ``` api_version >= ApiVersion::new(3, 3, 0) ``` Signed-off-by: Christian Ebner --- pbs-api-types/src/version.rs | 122 +++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) diff --git a/pbs-api-types/src/version.rs b/pbs-api-types/src/version.rs index bd4c517d..09e725eb 100644 --- a/pbs-api-types/src/version.rs +++ b/pbs-api-types/src/version.rs @@ -1,4 +1,5 @@ //! Defines the types for the api version info endpoint +use std::cmp::Ordering; use std::convert::TryFrom; use anyhow::{format_err, Context}; @@ -33,6 +34,7 @@ pub type ApiVersionMajor = u64; pub type ApiVersionMinor = u64; pub type ApiVersionRelease = u64; +#[derive(PartialEq, Eq)] pub struct ApiVersion { pub major: ApiVersionMajor, pub minor: ApiVersionMinor, @@ -66,3 +68,123 @@ impl TryFrom for ApiVersion { }) } } + +impl PartialOrd for ApiVersion { + fn partial_cmp(&self, other: &Self) -> Option { + let ordering = match ( + self.major.cmp(&other.major), + self.minor.cmp(&other.minor), + self.release.cmp(&other.release), + ) { + (Ordering::Equal, Ordering::Equal, ordering) => ordering, + (Ordering::Equal, ordering, _) => ordering, + (ordering, _, _) => ordering, + }; + + Some(ordering) + } +} + +impl ApiVersion { + pub fn new(major: ApiVersionMajor, minor: ApiVersionMinor, release: ApiVersionRelease) -> Self { + Self { + major, + minor, + release, + } + } +} + +#[test] +fn same_level_version_comarison() { + let major_base = ApiVersion::new(2, 0, 0); + let major_less = ApiVersion::new(1, 0, 0); + let major_greater = ApiVersion::new(3, 0, 0); + + let minor_base = ApiVersion::new(2, 2, 0); + let minor_less = ApiVersion::new(2, 1, 0); + let minor_greater = ApiVersion::new(2, 3, 0); + + let release_base = ApiVersion::new(2, 2, 2); + let release_less = ApiVersion::new(2, 2, 1); + let release_greater = ApiVersion::new(2, 2, 3); + + assert!(major_base == major_base); + assert!(minor_base == minor_base); + assert!(release_base == release_base); + + assert!(major_base > major_less); + assert!(major_base >= major_less); + assert!(major_base != major_less); + + assert!(major_base < major_greater); + assert!(major_base <= major_greater); + assert!(major_base != major_greater); + + assert!(minor_base > minor_less); + assert!(minor_base >= minor_less); + assert!(minor_base != minor_less); + + assert!(minor_base < minor_greater); + assert!(minor_base <= minor_greater); + assert!(minor_base != minor_greater); + + assert!(release_base > release_less); + assert!(release_base >= release_less); + assert!(release_base != release_less); + + assert!(release_base < release_greater); + assert!(release_base <= release_greater); + assert!(release_base != release_greater); +} + +#[test] +fn mixed_level_version_comarison() { + let major_base = ApiVersion::new(2, 0, 0); + let major_less = ApiVersion::new(1, 0, 0); + let major_greater = ApiVersion::new(3, 0, 0); + + let minor_base = ApiVersion::new(2, 2, 0); + let minor_less = ApiVersion::new(2, 1, 0); + let minor_greater = ApiVersion::new(2, 3, 0); + + let release_base = ApiVersion::new(2, 2, 2); + let release_less = ApiVersion::new(2, 2, 1); + let release_greater = ApiVersion::new(2, 2, 3); + + assert!(major_base < minor_base); + assert!(major_base < minor_less); + assert!(major_base < minor_greater); + + assert!(major_base < release_base); + assert!(major_base < release_less); + assert!(major_base < release_greater); + + assert!(major_less < minor_base); + assert!(major_less < minor_less); + assert!(major_less < minor_greater); + + assert!(major_less < release_base); + assert!(major_less < release_less); + assert!(major_less < release_greater); + + assert!(major_greater > minor_base); + assert!(major_greater > minor_less); + assert!(major_greater > minor_greater); + + assert!(major_greater > release_base); + assert!(major_greater > release_less); + assert!(major_greater > release_greater); + + assert!(minor_base < release_base); + assert!(minor_base < release_less); + assert!(minor_base < release_greater); + + assert!(minor_greater > release_base); + assert!(minor_greater > release_less); + assert!(minor_greater > release_greater); + + assert!(minor_less < release_base); + assert!(minor_less < release_less); + assert!(minor_less < release_greater); +}