From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gate001.proxmox.com (gate001.proxmox.com [45.144.208.40]) by lore.proxmox.com (Postfix) with ESMTPS id 8936C1FF0B7 for ; Fri, 02 Oct 2026 11:36:52 +0200 (CEST) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id 53FC421770; Fri, 02 Oct 2026 11:36:38 +0200 (CEST) From: Lukas Wagner To: pdm-devel@lists.proxmox.com Subject: [PATCH datacenter-manager v6 16/21] tests: add example tests for SDN API routes Date: Fri, 2 Oct 2026 11:36:11 +0200 Message-ID: <20261002093616.206933-17-l.wagner@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20261002093616.206933-1-l.wagner@proxmox.com> References: <20261002093616.206933-1-l.wagner@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1790933783889 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.377 Adjusted score from AWL reputation of From: address DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment (newer systems) RCVD_IN_DNSWL_MED -2.3 Sender listed at https://www.dnswl.org/, medium trust SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Message-ID-Hash: 44HZIZWLPIORJAQYXC5HARTH4JM5KAC7 X-Message-ID-Hash: 44HZIZWLPIORJAQYXC5HARTH4JM5KAC7 X-MailFrom: l.wagner@proxmox.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox Datacenter Manager development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: Using the previously added dependency-injected abstractions for accessing remotes and clients, and by using the test helpers, we can now fairly trivially create test cases that call the API handler directly. These tests also demonstrate how previously captured API responses from real PVE nodes can be used to build test cases. Signed-off-by: Lukas Wagner --- server/src/api/sdn/vnets.rs | 2 +- .../pve/remote-a/list_vnets.json | 8 ++ .../pve/remote-a/list_zones.json | 8 ++ .../pve/remote-b/list_vnets.json | 8 ++ .../pve/remote-b/list_zones.json | 8 ++ server/tests/test_sdn.rs | 86 +++++++++++++++++++ 6 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 server/tests/api_responses/pve/remote-a/list_vnets.json create mode 100644 server/tests/api_responses/pve/remote-a/list_zones.json create mode 100644 server/tests/api_responses/pve/remote-b/list_vnets.json create mode 100644 server/tests/api_responses/pve/remote-b/list_zones.json create mode 100644 server/tests/test_sdn.rs diff --git a/server/src/api/sdn/vnets.rs b/server/src/api/sdn/vnets.rs index 312d46b6..e42fcab7 100644 --- a/server/src/api/sdn/vnets.rs +++ b/server/src/api/sdn/vnets.rs @@ -59,7 +59,7 @@ pub const ROUTER: Router = Router::new() } )] /// Query VNets of PVE remotes with optional filtering options -async fn list_vnets( +pub async fn list_vnets( pending: Option, running: Option, remotes: Option>, diff --git a/server/tests/api_responses/pve/remote-a/list_vnets.json b/server/tests/api_responses/pve/remote-a/list_vnets.json new file mode 100644 index 00000000..a105de13 --- /dev/null +++ b/server/tests/api_responses/pve/remote-a/list_vnets.json @@ -0,0 +1,8 @@ +[ + { + "digest" : "3458032372eb62efb730fec12b34d36627a9e6e8", + "type" : "vnet", + "vnet" : "aaaavnet", + "zone" : "aaaa" + } +] diff --git a/server/tests/api_responses/pve/remote-a/list_zones.json b/server/tests/api_responses/pve/remote-a/list_zones.json new file mode 100644 index 00000000..f7932bd9 --- /dev/null +++ b/server/tests/api_responses/pve/remote-a/list_zones.json @@ -0,0 +1,8 @@ +[ + { + "digest" : "142f8be078a0fb61fa28a89cffdb17f64b05e3f9", + "ipam" : "pve", + "type" : "simple", + "zone" : "aaaa" + } +] diff --git a/server/tests/api_responses/pve/remote-b/list_vnets.json b/server/tests/api_responses/pve/remote-b/list_vnets.json new file mode 100644 index 00000000..4a59edc7 --- /dev/null +++ b/server/tests/api_responses/pve/remote-b/list_vnets.json @@ -0,0 +1,8 @@ +[ + { + "digest" : "56e0d24671dca1e6cc30a2cfdfab79a037e66a44", + "type" : "vnet", + "vnet" : "bbbbvnet", + "zone" : "bbbb" + } +] diff --git a/server/tests/api_responses/pve/remote-b/list_zones.json b/server/tests/api_responses/pve/remote-b/list_zones.json new file mode 100644 index 00000000..75fd763a --- /dev/null +++ b/server/tests/api_responses/pve/remote-b/list_zones.json @@ -0,0 +1,8 @@ +[ + { + "digest" : "bd994284b5d766ab58b5cb69f7363153d42816f7", + "ipam" : "pve", + "type" : "simple", + "zone" : "bbbb" + } +] diff --git a/server/tests/test_sdn.rs b/server/tests/test_sdn.rs new file mode 100644 index 00000000..204a94cd --- /dev/null +++ b/server/tests/test_sdn.rs @@ -0,0 +1,86 @@ +use pve_api_types::{ListZonesType, SdnVnet, SdnVnetType, SdnZone}; +use server::context::ContextFactory; + +use crate::common::{TestApplication, rpcenv}; + +pub mod common; + +common::test_pve_client!(SdnPveClient { + async fn list_zones( + &self, + _pending: Option, + _running: Option, + _ty: Option, + ) -> Result, proxmox_client::Error> { + common::read_captured_response(&format!( + "tests/api_responses/pve/{}/list_zones.json", + self.remote(), + )).await + } + + async fn list_vnets( + &self, + _pending: Option, + _running: Option, + ) -> Result, proxmox_client::Error> { + common::read_captured_response(&format!( + "tests/api_responses/pve/{}/list_vnets.json", + self.remote(), + )).await + } +}); + +#[tokio::test] +async fn test_lists_zones() { + common::test_setup(); + + let test_app = TestApplication::new() + .with_pve_remote("remote-a", Default::default(), SdnPveClient) + .with_pve_remote("remote-b", Default::default(), SdnPveClient); + + let app = test_app.make_pdm_application().unwrap(); + + let mut result = + server::api::sdn::zones::list_zones(None, None, None, None, &mut rpcenv(), app) + .await + .unwrap(); + + // We don't guarantee any ordering + result.sort_by(|a, b| a.remote.cmp(&b.remote)); + + assert_eq!(result.len(), 2); + + assert_eq!(result[0].remote, "remote-a"); + assert_eq!(result[0].zone.zone, "aaaa"); + assert_eq!(result[0].zone.ty, ListZonesType::Simple); + assert_eq!(result[1].remote, "remote-b"); + assert_eq!(result[1].zone.zone, "bbbb"); + assert_eq!(result[1].zone.ty, ListZonesType::Simple); +} + +#[tokio::test] +async fn test_lists_vnets() { + common::test_setup(); + + let test_app = TestApplication::new() + .with_pve_remote("remote-a", Default::default(), SdnPveClient) + .with_pve_remote("remote-b", Default::default(), SdnPveClient); + + let app = test_app.make_pdm_application().unwrap(); + + let mut result = server::api::sdn::vnets::list_vnets(None, None, None, &mut rpcenv(), app) + .await + .unwrap(); + + // We don't guarantee any ordering + result.sort_by(|a, b| a.remote.cmp(&b.remote)); + + assert_eq!(result.len(), 2); + + assert_eq!(result[0].remote, "remote-a"); + assert_eq!(result[0].vnet.vnet, "aaaavnet"); + assert_eq!(result[0].vnet.ty, SdnVnetType::Vnet); + assert_eq!(result[1].remote, "remote-b"); + assert_eq!(result[1].vnet.vnet, "bbbbvnet"); + assert_eq!(result[1].vnet.ty, SdnVnetType::Vnet); +} -- 2.47.3