From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [IPv6:2a01:7e0:0:424::9]) by lore.proxmox.com (Postfix) with ESMTPS id 3E8261FF141 for ; Mon, 30 Mar 2026 20:24:11 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id EF8B063C2; Mon, 30 Mar 2026 20:24:37 +0200 (CEST) From: Thomas Lamprecht To: pbs-devel@lists.proxmox.com Subject: [PATCH v2 1/5] client: repository: add tests for BackupRepository parsing Date: Mon, 30 Mar 2026 20:20:37 +0200 Message-ID: <20260330182352.2346420-2-t.lamprecht@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260330182352.2346420-1-t.lamprecht@proxmox.com> References: <20260330182352.2346420-1-t.lamprecht@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1774894989337 X-SPAM-LEVEL: Spam detection results: 0 AWL -1.508 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment RCVD_IN_VALIDITY_CERTIFIED_BLOCKED 1 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. RCVD_IN_VALIDITY_RPBL_BLOCKED 1 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. RCVD_IN_VALIDITY_SAFE_BLOCKED 1 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. 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: 4KZX3V7WDGFJHQQMX5NK7KCN65RMCGYC X-Message-ID-Hash: 4KZX3V7WDGFJHQQMX5NK7KCN65RMCGYC X-MailFrom: t.lamprecht@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 Backup Server development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: Add tests for BackupRepository, covering URL parsing with various combinations of user, host, port, datastore, IPv4, IPv6, and API tokens. Signed-off-by: Thomas Lamprecht --- new in v2. pbs-client/src/backup_repo.rs | 79 +++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/pbs-client/src/backup_repo.rs b/pbs-client/src/backup_repo.rs index 458f89dc2..45c859d67 100644 --- a/pbs-client/src/backup_repo.rs +++ b/pbs-client/src/backup_repo.rs @@ -115,3 +115,82 @@ impl std::str::FromStr for BackupRepository { }) } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn parse_datastore_only() { + let repo: BackupRepository = "mystore".parse().unwrap(); + assert_eq!(repo.store(), "mystore"); + assert_eq!(repo.host(), "localhost"); + assert_eq!(repo.port(), 8007); + assert_eq!(repo.auth_id().to_string(), "root@pam"); + } + + #[test] + fn parse_host_and_datastore() { + let repo: BackupRepository = "myhost:mystore".parse().unwrap(); + assert_eq!(repo.host(), "myhost"); + assert_eq!(repo.store(), "mystore"); + } + + #[test] + fn parse_full_with_port() { + let repo: BackupRepository = "admin@pam@backuphost:8008:tank".parse().unwrap(); + assert_eq!(repo.auth_id().to_string(), "admin@pam"); + assert_eq!(repo.host(), "backuphost"); + assert_eq!(repo.port(), 8008); + assert_eq!(repo.store(), "tank"); + } + + #[test] + fn parse_ipv4_with_port() { + let repo: BackupRepository = "192.168.1.1:1234:mystore".parse().unwrap(); + assert_eq!(repo.host(), "192.168.1.1"); + assert_eq!(repo.port(), 1234); + } + + #[test] + fn parse_ipv6_with_port() { + let repo: BackupRepository = "[ff80::1]:9007:mystore".parse().unwrap(); + assert_eq!(repo.host(), "[ff80::1]"); + assert_eq!(repo.port(), 9007); + } + + #[test] + fn parse_api_token() { + let repo: BackupRepository = "user@pbs!token@myhost:mystore".parse().unwrap(); + assert_eq!(repo.auth_id().to_string(), "user@pbs!token"); + } + + #[test] + fn parse_invalid_url_errors() { + assert!("".parse::().is_err()); + } + + #[test] + fn display_round_trip() { + for url in [ + "mystore", + "myhost:mystore", + "admin@pam@backuphost:8008:tank", + ] { + let repo: BackupRepository = url.parse().unwrap(); + assert_eq!(repo.to_string(), url, "round-trip failed for '{url}'"); + } + } + + #[test] + fn new_wraps_bare_ipv6_in_brackets() { + let repo = BackupRepository::new(None, Some("ff80::1".into()), None, "s".into()); + assert_eq!(repo.host(), "[ff80::1]"); + } + + #[test] + fn new_preserves_already_bracketed_ipv6() { + let repo = BackupRepository::new(None, Some("[ff80::1]".into()), None, "s".into()); + assert_eq!(repo.host(), "[ff80::1]"); + } +} -- 2.47.3