public inbox for pbs-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Christian Ebner <c.ebner@proxmox.com>
To: pbs-devel@lists.proxmox.com
Subject: [pbs-devel] [PATCH v2 proxmox-backup 2/3] api types: version: implement traits to allow for version comparison
Date: Thu, 28 Nov 2024 17:07:20 +0100	[thread overview]
Message-ID: <20241128160721.583578-2-c.ebner@proxmox.com> (raw)
In-Reply-To: <20241128160721.583578-1-c.ebner@proxmox.com>

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 <c.ebner@proxmox.com>
---
changes since version 1:
- implement traits for operator based version comparison
- add basic regression tests

 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 bd4c517da..09e725eb6 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<ApiVersionInfo> for ApiVersion {
         })
     }
 }
+
+impl PartialOrd for ApiVersion {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        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);
+}
-- 
2.39.5



_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel


  reply	other threads:[~2024-11-28 16:07 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-11-28 16:07 [pbs-devel] [PATCH v2 proxmox-backup 1/3] api types: version: drop unused `repoid` field Christian Ebner
2024-11-28 16:07 ` Christian Ebner [this message]
2024-11-28 16:07 ` [pbs-devel] [PATCH v2 proxmox-backup 3/3] sync: push: use direct api version comparison in compatibility checks Christian Ebner
2024-12-02 14:30 ` [pbs-devel] applied-series: [PATCH v2 proxmox-backup 1/3] api types: version: drop unused `repoid` field Thomas Lamprecht

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20241128160721.583578-2-c.ebner@proxmox.com \
    --to=c.ebner@proxmox.com \
    --cc=pbs-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal