Skip to content

Commit 4d26e76

Browse files
authored
test(secrets): table-ify the credential snapshot and key-path tests (#2734)
1 parent 181a56d commit 4d26e76

4 files changed

Lines changed: 314 additions & 250 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/secrets/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ bmc-vendor = { path = "../bmc-vendor" }
5555
carbide-uuid = { path = "../uuid" }
5656

5757
[dev-dependencies]
58+
carbide-test-support = { path = "../test-support" }
5859
serial_test = { workspace = true }
5960
tempfile = { workspace = true }
6061

crates/secrets/src/credentials.rs

Lines changed: 230 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,8 @@ impl CredentialKey {
543543

544544
#[cfg(test)]
545545
mod tests {
546+
use carbide_test_support::{Check, check_values};
547+
546548
use super::*;
547549
use crate::test_support::credentials::TestCredentialManager;
548550

@@ -666,145 +668,255 @@ mod tests {
666668
let rack_id = RackId::new("rack-01");
667669
let mac: MacAddress = MacAddress::new([0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF]);
668670

669-
let cases: Vec<(CredentialKey, &str)> = vec![
670-
(CredentialKey::DpuHbn { machine_id }, "machines/"),
671-
(
672-
CredentialKey::DpuRedfish {
673-
credential_type: CredentialType::DpuHardwareDefault,
671+
// Each row is a key and the path prefix its `to_key_str()` must carry. A
672+
// path is well-formed when it is non-empty, has no leading or trailing
673+
// slash, and starts with that prefix.
674+
struct Row {
675+
key: CredentialKey,
676+
expected_prefix: &'static str,
677+
}
678+
679+
// The four invariants of a well-formed key path, checked as named fields
680+
// rather than folded into one bool so a failing row names the invariant
681+
// it broke. A well-formed path holds all four.
682+
#[derive(Debug, PartialEq)]
683+
struct PathChecks {
684+
non_empty: bool,
685+
no_leading_slash: bool,
686+
no_trailing_slash: bool,
687+
has_expected_prefix: bool,
688+
}
689+
690+
impl PathChecks {
691+
const fn all_hold() -> Self {
692+
Self {
693+
non_empty: true,
694+
no_leading_slash: true,
695+
no_trailing_slash: true,
696+
has_expected_prefix: true,
697+
}
698+
}
699+
}
700+
701+
check_values(
702+
[
703+
Check {
704+
scenario: "dpu hbn",
705+
input: Row {
706+
key: CredentialKey::DpuHbn { machine_id },
707+
expected_prefix: "machines/",
708+
},
709+
expect: PathChecks::all_hold(),
674710
},
675-
"machines/all_dpus/",
676-
),
677-
(
678-
CredentialKey::DpuRedfish {
679-
credential_type: CredentialType::SiteDefault,
711+
Check {
712+
scenario: "dpu redfish hardware default",
713+
input: Row {
714+
key: CredentialKey::DpuRedfish {
715+
credential_type: CredentialType::DpuHardwareDefault,
716+
},
717+
expected_prefix: "machines/all_dpus/",
718+
},
719+
expect: PathChecks::all_hold(),
680720
},
681-
"machines/all_dpus/",
682-
),
683-
(
684-
CredentialKey::HostRedfish {
685-
credential_type: CredentialType::HostHardwareDefault {
686-
vendor: bmc_vendor::BMCVendor::Nvidia,
721+
Check {
722+
scenario: "dpu redfish site default",
723+
input: Row {
724+
key: CredentialKey::DpuRedfish {
725+
credential_type: CredentialType::SiteDefault,
726+
},
727+
expected_prefix: "machines/all_dpus/",
687728
},
729+
expect: PathChecks::all_hold(),
688730
},
689-
"machines/all_hosts/",
690-
),
691-
(
692-
CredentialKey::HostRedfish {
693-
credential_type: CredentialType::SiteDefault,
731+
Check {
732+
scenario: "host redfish hardware default",
733+
input: Row {
734+
key: CredentialKey::HostRedfish {
735+
credential_type: CredentialType::HostHardwareDefault {
736+
vendor: bmc_vendor::BMCVendor::Nvidia,
737+
},
738+
},
739+
expected_prefix: "machines/all_hosts/",
740+
},
741+
expect: PathChecks::all_hold(),
694742
},
695-
"machines/all_hosts/",
696-
),
697-
(
698-
CredentialKey::UfmAuth {
699-
fabric: "test-fabric".to_string(),
743+
Check {
744+
scenario: "host redfish site default",
745+
input: Row {
746+
key: CredentialKey::HostRedfish {
747+
credential_type: CredentialType::SiteDefault,
748+
},
749+
expected_prefix: "machines/all_hosts/",
750+
},
751+
expect: PathChecks::all_hold(),
700752
},
701-
"ufm/",
702-
),
703-
(
704-
CredentialKey::DpuUefi {
705-
credential_type: CredentialType::DpuHardwareDefault,
753+
Check {
754+
scenario: "ufm auth",
755+
input: Row {
756+
key: CredentialKey::UfmAuth {
757+
fabric: "test-fabric".to_string(),
758+
},
759+
expected_prefix: "ufm/",
760+
},
761+
expect: PathChecks::all_hold(),
706762
},
707-
"machines/all_dpus/",
708-
),
709-
(
710-
CredentialKey::DpuUefi {
711-
credential_type: CredentialType::SiteDefault,
763+
Check {
764+
scenario: "dpu uefi hardware default",
765+
input: Row {
766+
key: CredentialKey::DpuUefi {
767+
credential_type: CredentialType::DpuHardwareDefault,
768+
},
769+
expected_prefix: "machines/all_dpus/",
770+
},
771+
expect: PathChecks::all_hold(),
712772
},
713-
"machines/all_dpus/",
714-
),
715-
(
716-
CredentialKey::HostUefi {
717-
credential_type: CredentialType::SiteDefault,
773+
Check {
774+
scenario: "dpu uefi site default",
775+
input: Row {
776+
key: CredentialKey::DpuUefi {
777+
credential_type: CredentialType::SiteDefault,
778+
},
779+
expected_prefix: "machines/all_dpus/",
780+
},
781+
expect: PathChecks::all_hold(),
718782
},
719-
"machines/all_hosts/",
720-
),
721-
(
722-
CredentialKey::BmcCredentials {
723-
credential_type: BmcCredentialType::SiteWideRoot,
783+
Check {
784+
scenario: "host uefi site default",
785+
input: Row {
786+
key: CredentialKey::HostUefi {
787+
credential_type: CredentialType::SiteDefault,
788+
},
789+
expected_prefix: "machines/all_hosts/",
790+
},
791+
expect: PathChecks::all_hold(),
724792
},
725-
"machines/bmc/",
726-
),
727-
(
728-
CredentialKey::BmcCredentials {
729-
credential_type: BmcCredentialType::BmcRoot {
730-
bmc_mac_address: mac,
793+
Check {
794+
scenario: "bmc site wide root",
795+
input: Row {
796+
key: CredentialKey::BmcCredentials {
797+
credential_type: BmcCredentialType::SiteWideRoot,
798+
},
799+
expected_prefix: "machines/bmc/",
731800
},
801+
expect: PathChecks::all_hold(),
732802
},
733-
"machines/bmc/",
734-
),
735-
(
736-
CredentialKey::BmcCredentials {
737-
credential_type: BmcCredentialType::BmcForgeAdmin {
738-
bmc_mac_address: mac,
803+
Check {
804+
scenario: "bmc root",
805+
input: Row {
806+
key: CredentialKey::BmcCredentials {
807+
credential_type: BmcCredentialType::BmcRoot {
808+
bmc_mac_address: mac,
809+
},
810+
},
811+
expected_prefix: "machines/bmc/",
739812
},
813+
expect: PathChecks::all_hold(),
740814
},
741-
"machines/bmc/",
742-
),
743-
(
744-
CredentialKey::NicLockdownIkm {
745-
credential_type: NicLockdownIkm::SiteWide { version: 0 },
815+
Check {
816+
scenario: "bmc forge admin",
817+
input: Row {
818+
key: CredentialKey::BmcCredentials {
819+
credential_type: BmcCredentialType::BmcForgeAdmin {
820+
bmc_mac_address: mac,
821+
},
822+
},
823+
expected_prefix: "machines/bmc/",
824+
},
825+
expect: PathChecks::all_hold(),
746826
},
747-
"machines/nic_lockdown_ikm/",
748-
),
749-
(
750-
CredentialKey::ExtensionService {
751-
service_id: "svc1".to_string(),
752-
version: "v1".to_string(),
827+
Check {
828+
scenario: "nic lockdown ikm",
829+
input: Row {
830+
key: CredentialKey::NicLockdownIkm {
831+
credential_type: NicLockdownIkm::SiteWide { version: 0 },
832+
},
833+
expected_prefix: "machines/nic_lockdown_ikm/",
834+
},
835+
expect: PathChecks::all_hold(),
753836
},
754-
"machines/extension-services/",
755-
),
756-
(
757-
CredentialKey::NmxM {
758-
nmxm_id: "nmxm1".to_string(),
837+
Check {
838+
scenario: "extension service",
839+
input: Row {
840+
key: CredentialKey::ExtensionService {
841+
service_id: "svc1".to_string(),
842+
version: "v1".to_string(),
843+
},
844+
expected_prefix: "machines/extension-services/",
845+
},
846+
expect: PathChecks::all_hold(),
759847
},
760-
"nmxm/",
761-
),
762-
(
763-
CredentialKey::SwitchNvosAdmin {
764-
bmc_mac_address: mac,
848+
Check {
849+
scenario: "nmxm",
850+
input: Row {
851+
key: CredentialKey::NmxM {
852+
nmxm_id: "nmxm1".to_string(),
853+
},
854+
expected_prefix: "nmxm/",
855+
},
856+
expect: PathChecks::all_hold(),
765857
},
766-
"switch_nvos/",
767-
),
768-
(
769-
CredentialKey::MqttAuth {
770-
credential_type: MqttCredentialType::Dpa,
858+
Check {
859+
scenario: "switch nvos admin",
860+
input: Row {
861+
key: CredentialKey::SwitchNvosAdmin {
862+
bmc_mac_address: mac,
863+
},
864+
expected_prefix: "switch_nvos/",
865+
},
866+
expect: PathChecks::all_hold(),
771867
},
772-
"mqtt/",
773-
),
774-
(
775-
CredentialKey::MqttAuth {
776-
credential_type: MqttCredentialType::DsxExchangeEventBus,
868+
Check {
869+
scenario: "mqtt dpa",
870+
input: Row {
871+
key: CredentialKey::MqttAuth {
872+
credential_type: MqttCredentialType::Dpa,
873+
},
874+
expected_prefix: "mqtt/",
875+
},
876+
expect: PathChecks::all_hold(),
777877
},
778-
"mqtt/",
779-
),
780-
(
781-
CredentialKey::MqttAuth {
782-
credential_type: MqttCredentialType::DsxExchangeConsumer,
878+
Check {
879+
scenario: "mqtt dsx exchange event bus",
880+
input: Row {
881+
key: CredentialKey::MqttAuth {
882+
credential_type: MqttCredentialType::DsxExchangeEventBus,
883+
},
884+
expected_prefix: "mqtt/",
885+
},
886+
expect: PathChecks::all_hold(),
783887
},
784-
"mqtt/",
785-
),
786-
(
787-
CredentialKey::RackMaintenanceAccessToken { rack_id },
788-
"racks/",
789-
),
790-
];
791-
792-
for (key, expected_prefix) in &cases {
793-
let path = key.to_key_str();
794-
assert!(!path.is_empty(), "{key:?} produced an empty path");
795-
assert!(
796-
!path.starts_with('/'),
797-
"{key:?} path {path:?} should not start with /"
798-
);
799-
assert!(
800-
!path.ends_with('/'),
801-
"{key:?} path {path:?} should not end with /"
802-
);
803-
assert!(
804-
path.starts_with(expected_prefix),
805-
"{key:?} path {path:?} should start with {expected_prefix:?}"
806-
);
807-
}
888+
Check {
889+
scenario: "mqtt dsx exchange consumer",
890+
input: Row {
891+
key: CredentialKey::MqttAuth {
892+
credential_type: MqttCredentialType::DsxExchangeConsumer,
893+
},
894+
expected_prefix: "mqtt/",
895+
},
896+
expect: PathChecks::all_hold(),
897+
},
898+
Check {
899+
scenario: "rack maintenance access token",
900+
input: Row {
901+
key: CredentialKey::RackMaintenanceAccessToken { rack_id },
902+
expected_prefix: "racks/",
903+
},
904+
expect: PathChecks::all_hold(),
905+
},
906+
],
907+
|Row {
908+
key,
909+
expected_prefix,
910+
}| {
911+
let path = key.to_key_str();
912+
PathChecks {
913+
non_empty: !path.is_empty(),
914+
no_leading_slash: !path.starts_with('/'),
915+
no_trailing_slash: !path.ends_with('/'),
916+
has_expected_prefix: path.starts_with(expected_prefix),
917+
}
918+
},
919+
);
808920
}
809921

810922
// Verifies that every CredentialKey's to_key_str()

0 commit comments

Comments
 (0)