public inbox for pdm-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Lukas Wagner <l.wagner@proxmox.com>
To: pdm-devel@lists.proxmox.com
Subject: [pdm-devel] [PATCH datacenter-manager 3/3] views: tests: use full section-config format for test cases
Date: Mon, 17 Nov 2025 15:11:22 +0100	[thread overview]
Message-ID: <20251117141122.328559-4-l.wagner@proxmox.com> (raw)
In-Reply-To: <20251117141122.328559-1-l.wagner@proxmox.com>

The config structure should be more stable than the actual rust types,
so this should lead to less maintenance burden over time. Also, the
tests are a bit easier to read this way.

Signed-off-by: Lukas Wagner <l.wagner@proxmox.com>
---
 server/src/views/tests.rs | 378 +++++++++++++++++++-------------------
 1 file changed, 186 insertions(+), 192 deletions(-)

diff --git a/server/src/views/tests.rs b/server/src/views/tests.rs
index 0d83ae70..9f496207 100644
--- a/server/src/views/tests.rs
+++ b/server/src/views/tests.rs
@@ -1,7 +1,8 @@
 use pdm_api_types::{
-    resource::{PveLxcResource, PveQemuResource, PveStorageResource, Resource, ResourceType},
-    views::{EnumMatcher, FilterRule, StringMatcher, ViewConfig},
+    resource::{PveLxcResource, PveQemuResource, PveStorageResource, Resource},
+    views::{ViewConfig, ViewConfigEntry},
 };
+use proxmox_section_config::typed::ApiSectionDataEntry;
 
 use super::View;
 
@@ -79,20 +80,26 @@ fn run_test(config: ViewConfig, tests: &[((&str, &Resource), bool)]) {
     }
 }
 
+fn parse_config(config: &str) -> ViewConfig {
+    let config = ViewConfigEntry::parse_section_config("views.cfg", config).unwrap();
+    let ViewConfigEntry::View(config) = config.get("test").unwrap();
+    config.clone()
+}
+
 const NODE: &str = "somenode";
 const STORAGE: &str = "somestorage";
 const REMOTE: &str = "someremote";
 
 #[test]
 fn include_remotes() {
-    let config = ViewConfig {
-        id: "only-includes".into(),
-        include: vec![
-            FilterRule::Remote(StringMatcher::Exact("remote-a".into())),
-            FilterRule::Remote(StringMatcher::Exact("remote-b".into())),
-        ],
-        ..Default::default()
-    };
+    let config = parse_config(
+        "
+view: test
+    include remote=remote-a
+    include remote=remote-b
+",
+    );
+
     run_test(
         config.clone(),
         &[
@@ -129,15 +136,14 @@ fn include_remotes() {
 
 #[test]
 fn exclude_remotes() {
-    let config = ViewConfig {
-        id: "only-excludes".into(),
-        exclude: vec![
-            FilterRule::Remote(StringMatcher::Exact("remote-a".into())),
-            FilterRule::Remote(StringMatcher::Exact("remote-b".into())),
-        ],
-        include_all: Some(true),
-        ..Default::default()
-    };
+    let config = parse_config(
+        "
+view: test
+    include-all true
+    exclude remote=remote-a
+    exclude remote=remote-b
+",
+    );
 
     run_test(
         config.clone(),
@@ -175,19 +181,16 @@ fn exclude_remotes() {
 
 #[test]
 fn include_exclude_remotes() {
-    let config = ViewConfig {
-        id: "both".into(),
-        include: vec![
-            FilterRule::Remote(StringMatcher::Exact("remote-a".into())),
-            FilterRule::Remote(StringMatcher::Exact("remote-b".into())),
-        ],
-        exclude: vec![
-            FilterRule::Remote(StringMatcher::Exact("remote-b".into())),
-            FilterRule::Remote(StringMatcher::Exact("remote-c".into())),
-        ],
+    let config = parse_config(
+        "
+view: test
+    include remote=remote-a
+    include remote=remote-b
+    exclude remote=remote-b
+    exclude remote=remote-c
+",
+    );
 
-        ..Default::default()
-    };
     run_test(
         config.clone(),
         &[
@@ -225,11 +228,12 @@ fn include_exclude_remotes() {
 
 #[test]
 fn empty_config() {
-    let config = ViewConfig {
-        id: "empty".into(),
-        include_all: Some(true),
-        ..Default::default()
-    };
+    let config = parse_config(
+        "
+view: test
+    include-all true
+",
+    );
     run_test(
         config.clone(),
         &[
@@ -270,15 +274,15 @@ fn empty_config() {
 
 #[test]
 fn include_type() {
+    let config = parse_config(
+        "
+view: test
+    include resource-type=storage
+    include resource-type=qemu
+",
+    );
     run_test(
-        ViewConfig {
-            id: "include-resource-type".into(),
-            include: vec![
-                FilterRule::ResourceType(EnumMatcher(ResourceType::PveStorage)),
-                FilterRule::ResourceType(EnumMatcher(ResourceType::PveQemu)),
-            ],
-            ..Default::default()
-        },
+        config,
         &[
             (
                 (REMOTE, &make_storage_resource(REMOTE, NODE, STORAGE)),
@@ -298,16 +302,16 @@ fn include_type() {
 
 #[test]
 fn exclude_type() {
+    let config = parse_config(
+        "
+view: test
+    include-all true
+    exclude resource-type=storage
+    exclude resource-type=qemu
+",
+    );
     run_test(
-        ViewConfig {
-            id: "exclude-resource-type".into(),
-            exclude: vec![
-                FilterRule::ResourceType(EnumMatcher(ResourceType::PveStorage)),
-                FilterRule::ResourceType(EnumMatcher(ResourceType::PveQemu)),
-            ],
-            include_all: Some(true),
-            ..Default::default()
-        },
+        config,
         &[
             (
                 (REMOTE, &make_storage_resource(REMOTE, NODE, STORAGE)),
@@ -327,15 +331,16 @@ fn exclude_type() {
 
 #[test]
 fn include_exclude_type() {
+    let config = parse_config(
+        "
+view: test
+    include resource-type=qemu
+    exclude resource-type=storage
+",
+    );
+
     run_test(
-        ViewConfig {
-            id: "exclude-resource-type".into(),
-            include: vec![FilterRule::ResourceType(EnumMatcher(ResourceType::PveQemu))],
-            exclude: vec![FilterRule::ResourceType(EnumMatcher(
-                ResourceType::PveStorage,
-            ))],
-            ..Default::default()
-        },
+        config,
         &[
             (
                 (REMOTE, &make_storage_resource(REMOTE, NODE, STORAGE)),
@@ -355,16 +360,16 @@ fn include_exclude_type() {
 
 #[test]
 fn include_exclude_tags() {
+    let config = parse_config(
+        "
+view: test
+    include tag=tag1
+    include tag=tag2
+    exclude tag=tag3
+",
+    );
     run_test(
-        ViewConfig {
-            id: "include-tags".into(),
-            include: vec![
-                FilterRule::Tag(StringMatcher::Exact("tag1".to_string())),
-                FilterRule::Tag(StringMatcher::Exact("tag2".to_string())),
-            ],
-            exclude: vec![FilterRule::Tag(StringMatcher::Exact("tag3".to_string()))],
-            ..Default::default()
-        },
+        config,
         &[
             (
                 (REMOTE, &make_storage_resource(REMOTE, NODE, STORAGE)),
@@ -401,18 +406,16 @@ fn include_exclude_tags() {
 
 #[test]
 fn include_exclude_resource_pool() {
+    let config = parse_config(
+        "
+view: test
+    include resource-pool=pool1
+    include resource-pool=pool2
+    exclude resource-pool=pool2
+",
+    );
     run_test(
-        ViewConfig {
-            id: "pools".into(),
-            include: vec![
-                FilterRule::ResourcePool(StringMatcher::Exact("pool1".to_string())),
-                FilterRule::ResourcePool(StringMatcher::Exact("pool2".to_string())),
-            ],
-            exclude: vec![FilterRule::ResourcePool(StringMatcher::Exact(
-                "pool2".to_string(),
-            ))],
-            ..Default::default()
-        },
+        config,
         &[
             (
                 (REMOTE, &make_storage_resource(REMOTE, NODE, STORAGE)),
@@ -449,26 +452,18 @@ fn include_exclude_resource_pool() {
 
 #[test]
 fn include_exclude_resource_id() {
+    let config = parse_config(
+        "
+view: test
+    include resource-id=remote/someremote/guest/100
+    include resource-id=remote/someremote/storage/somenode/somestorage
+    exclude resource-id=remote/someremote/guest/101
+    exclude resource-id=remote/otherremote/guest/101
+    exclude resource-id=remote/someremote/storage/somenode/otherstorage
+",
+    );
     run_test(
-        ViewConfig {
-            id: "resource-id".into(),
-            include: vec![
-                FilterRule::ResourceId(StringMatcher::Exact(format!("remote/{REMOTE}/guest/100"))),
-                FilterRule::ResourceId(StringMatcher::Exact(format!(
-                    "remote/{REMOTE}/storage/{NODE}/{STORAGE}"
-                ))),
-            ],
-            exclude: vec![
-                FilterRule::ResourceId(StringMatcher::Exact(format!("remote/{REMOTE}/guest/101"))),
-                FilterRule::ResourceId(StringMatcher::Exact(
-                    "remote/otherremote/guest/101".to_string(),
-                )),
-                FilterRule::ResourceId(StringMatcher::Exact(format!(
-                    "remote/{REMOTE}/storage/{NODE}/otherstorage"
-                ))),
-            ],
-            ..Default::default()
-        },
+        config,
         &[
             (
                 (REMOTE, &make_storage_resource(REMOTE, NODE, STORAGE)),
@@ -506,20 +501,16 @@ fn include_exclude_resource_id() {
 
 #[test]
 fn node_included() {
-    let view = View::new(ViewConfig {
-        id: "both".into(),
+    let config = parse_config(
+        "
+view: test
+    include remote=remote-a
+    include resource-id=remote/someremote/node/test
+    exclude remote=remote-b
+",
+    );
 
-        include: vec![
-            FilterRule::Remote(StringMatcher::Exact("remote-a".to_string())),
-            FilterRule::ResourceId(StringMatcher::Exact(
-                "remote/someremote/node/test".to_string(),
-            )),
-        ],
-        exclude: vec![FilterRule::Remote(StringMatcher::Exact(
-            "remote-b".to_string(),
-        ))],
-        ..Default::default()
-    });
+    let view = View::new(config);
 
     assert!(view.is_node_included("remote-a", "somenode"));
     assert!(view.is_node_included("remote-a", "somenode2"));
@@ -527,19 +518,19 @@ fn node_included() {
     assert!(!view.is_node_included("remote-b", "somenode2"));
     assert!(view.is_node_included("someremote", "test"));
 
-    assert_eq!(view.name(), "both");
+    assert_eq!(view.name(), "test");
 }
 
 #[test]
 fn can_skip_remote_if_excluded() {
-    let view = View::new(ViewConfig {
-        id: "abc".into(),
-        include: vec![],
-        exclude: vec![FilterRule::Remote(StringMatcher::Exact(
-            "remote-b".to_string(),
-        ))],
-        include_all: Some(true),
-    });
+    let config = parse_config(
+        "
+view: test
+    include-all true
+    exclude remote=remote-b
+",
+    );
+    let view = View::new(config);
 
     assert!(!view.can_skip_remote("remote-a"));
     assert!(view.can_skip_remote("remote-b"));
@@ -547,14 +538,14 @@ fn can_skip_remote_if_excluded() {
 
 #[test]
 fn can_skip_remote_if_included() {
-    let view = View::new(ViewConfig {
-        id: "abc".into(),
-        include: vec![FilterRule::Remote(StringMatcher::Exact(
-            "remote-b".to_string(),
-        ))],
-        exclude: vec![],
-        ..Default::default()
-    });
+    let config = parse_config(
+        "
+view: test
+    include remote=remote-b
+",
+    );
+
+    let view = View::new(config);
 
     assert!(!view.can_skip_remote("remote-b"));
     assert!(view.can_skip_remote("remote-a"));
@@ -562,17 +553,15 @@ fn can_skip_remote_if_included() {
 
 #[test]
 fn can_skip_remote_cannot_skip_if_any_other_include() {
-    let view = View::new(ViewConfig {
-        id: "abc".into(),
-        include: vec![
-            FilterRule::Remote(StringMatcher::Exact("remote-b".to_string())),
-            FilterRule::ResourceId(StringMatcher::Exact(
-                "resource/remote-a/guest/100".to_string(),
-            )),
-        ],
-        exclude: vec![],
-        ..Default::default()
-    });
+    let config = parse_config(
+        "
+view: test
+    include remote=remote-b
+    include resource-id=remote/remote-a/guest/100
+",
+    );
+
+    let view = View::new(config);
 
     assert!(!view.can_skip_remote("remote-b"));
     assert!(!view.can_skip_remote("remote-a"));
@@ -580,26 +569,28 @@ fn can_skip_remote_cannot_skip_if_any_other_include() {
 
 #[test]
 fn can_skip_remote_explicit_remote_exclude() {
-    let view = View::new(ViewConfig {
-        id: "abc".into(),
-        include: vec![FilterRule::ResourceId(StringMatcher::Exact(
-            "resource/remote-a/guest/100".to_string(),
-        ))],
-        exclude: vec![FilterRule::Remote(StringMatcher::Exact(
-            "remote-a".to_string(),
-        ))],
-        ..Default::default()
-    });
+    let config = parse_config(
+        "
+view: test
+    exclude remote=remote-a
+    include resource-id=remote/remote-a/guest/100
+",
+    );
+
+    let view = View::new(config);
 
     assert!(view.can_skip_remote("remote-a"));
 }
 
 #[test]
 fn can_skip_remote_with_empty_config() {
-    let view = View::new(ViewConfig {
-        id: "abc".into(),
-        ..Default::default()
-    });
+    let config = parse_config(
+        "
+view: test
+",
+    );
+
+    let view = View::new(config);
 
     assert!(view.can_skip_remote("remote-a"));
     assert!(view.can_skip_remote("remote-b"));
@@ -607,11 +598,14 @@ fn can_skip_remote_with_empty_config() {
 
 #[test]
 fn can_skip_remote_cannot_skip_if_all_included() {
-    let view = View::new(ViewConfig {
-        id: "abc".into(),
-        include_all: Some(true),
-        ..Default::default()
-    });
+    let config = parse_config(
+        "
+view: test
+    include-all true
+",
+    );
+
+    let view = View::new(config);
 
     assert!(!view.can_skip_remote("remote-a"));
     assert!(!view.can_skip_remote("remote-b"));
@@ -619,14 +613,14 @@ fn can_skip_remote_cannot_skip_if_all_included() {
 
 #[test]
 fn can_skip_remote_with_no_remote_includes() {
-    let view = View::new(ViewConfig {
-        id: "abc".into(),
-        include: vec![FilterRule::ResourceId(StringMatcher::Exact(
-            "resource/remote-a/guest/100".to_string(),
-        ))],
-        exclude: vec![],
-        ..Default::default()
-    });
+    let config = parse_config(
+        "
+view: test
+    include resource-id=remote/remote-a/guest/100
+",
+    );
+
+    let view = View::new(config);
 
     assert!(!view.can_skip_remote("remote-a"));
     assert!(!view.can_skip_remote("remote-b"));
@@ -634,42 +628,42 @@ fn can_skip_remote_with_no_remote_includes() {
 
 #[test]
 fn explicitly_included_remote() {
-    let view = View::new(ViewConfig {
-        id: "abc".into(),
-        include: vec![FilterRule::Remote(StringMatcher::Exact(
-            "remote-b".to_string(),
-        ))],
-        exclude: vec![],
-        ..Default::default()
-    });
+    let config = parse_config(
+        "
+view: test
+    include remote=remote-b
+",
+    );
+
+    let view = View::new(config);
 
     assert!(view.is_remote_explicitly_included("remote-b"));
 }
 
 #[test]
 fn included_and_excluded_same_remote() {
-    let view = View::new(ViewConfig {
-        id: "abc".into(),
-        include: vec![FilterRule::Remote(StringMatcher::Exact(
-            "remote-b".to_string(),
-        ))],
-        exclude: vec![FilterRule::Remote(StringMatcher::Exact(
-            "remote-b".to_string(),
-        ))],
-        ..Default::default()
-    });
+    let config = parse_config(
+        "
+view: test
+    include remote=remote-b
+    exclude remote=remote-b
+",
+    );
+
+    let view = View::new(config);
 
     assert!(!view.is_remote_explicitly_included("remote-b"));
 }
 
 #[test]
 fn not_explicitly_included_remote() {
-    let view = View::new(ViewConfig {
-        id: "abc".into(),
-        include: vec![],
-        exclude: vec![],
-        include_all: Some(true),
-    });
+    let config = parse_config(
+        "
+view: test
+    include-all true
+",
+    );
+    let view = View::new(config);
 
     // Assert that is not *explicitly* included
     assert!(view.is_remote_explicitly_included("remote-b"));
-- 
2.47.3



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


      parent reply	other threads:[~2025-11-17 14:12 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-11-17 14:11 [pdm-devel] [PATCH datacenter-manager 0/3] views: preparations for regex/glob, include-all param Lukas Wagner
2025-11-17 14:11 ` [pdm-devel] [PATCH datacenter-manager 1/3] pdm-api-types: views: preparations for future glob/regex support Lukas Wagner
2025-11-17 14:11 ` [pdm-devel] [PATCH datacenter-manager 2/3] views: add 'include-all' param; change semantics when there are no includes Lukas Wagner
2025-11-17 14:11 ` Lukas Wagner [this message]

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=20251117141122.328559-4-l.wagner@proxmox.com \
    --to=l.wagner@proxmox.com \
    --cc=pdm-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