From dabef53e22bcbbac0d0b6269397acfe6b3857363 Mon Sep 17 00:00:00 2001 From: David Pacheco Date: Tue, 25 Nov 2025 15:07:15 -0800 Subject: [PATCH 1/2] replace test_setup* with a builder --- nexus/benches/setup_benchmark.rs | 6 +- nexus/src/app/sagas/instance_start.rs | 5 +- nexus/test-utils-macros/src/lib.rs | 8 +- nexus/test-utils/src/lib.rs | 3 +- nexus/test-utils/src/nexus_test.rs | 129 ++++++++++++------ nexus/tests/integration_tests/certificates.rs | 23 ++-- nexus/tests/integration_tests/console_api.rs | 42 +++--- nexus/tests/integration_tests/device_auth.rs | 37 ++--- .../multicast/cache_invalidation.rs | 88 ++++++------ .../integration_tests/multicast/enablement.rs | 25 ++-- nexus/tests/integration_tests/oximeter.rs | 4 +- .../tests/integration_tests/target_release.rs | 5 +- nexus/tests/integration_tests/unauthorized.rs | 5 +- nexus/tests/integration_tests/updates.rs | 32 +++-- 14 files changed, 222 insertions(+), 190 deletions(-) diff --git a/nexus/benches/setup_benchmark.rs b/nexus/benches/setup_benchmark.rs index 29a89465044..1dd39ffced4 100644 --- a/nexus/benches/setup_benchmark.rs +++ b/nexus/benches/setup_benchmark.rs @@ -12,9 +12,9 @@ use omicron_test_utils::dev; // This is the default wrapper around most Nexus integration tests. // Benchmark how long an "empty test" would take. async fn do_full_setup() { - let ctx = - nexus_test_utils::test_setup::("full_setup", 0) - .await; + let ctx = nexus_test_utils::ControlPlaneBuilder::new("full_setup") + .start::() + .await; ctx.teardown().await; } diff --git a/nexus/src/app/sagas/instance_start.rs b/nexus/src/app/sagas/instance_start.rs index 0d8168b8f02..54b648bc2e1 100644 --- a/nexus/src/app/sagas/instance_start.rs +++ b/nexus/src/app/sagas/instance_start.rs @@ -1015,10 +1015,11 @@ mod test { #[tokio::test] async fn should_start_with_dead_switch() { - let cptestctx = nexus_test_utils::test_setup::( + let cptestctx = nexus_test_utils::ControlPlaneBuilder::new( "should_start_with_dead_switch", - 3, ) + .extra_sled_agents(3) + .start::() .await; let client = &cptestctx.external_client; diff --git a/nexus/test-utils-macros/src/lib.rs b/nexus/test-utils-macros/src/lib.rs index f45501478d0..fa7aa825919 100644 --- a/nexus/test-utils-macros/src/lib.rs +++ b/nexus/test-utils-macros/src/lib.rs @@ -126,10 +126,12 @@ pub fn nexus_test(attrs: TokenStream, input: TokenStream) -> TokenStream { { #input_func - let ctx = ::nexus_test_utils::test_setup::<#which_nexus>( + let ctx = ::nexus_test_utils::ControlPlaneBuilder::new( #func_ident_string, - #extra_sled_agents, - ).await; + ) + .extra_sled_agents(#extra_sled_agents) + .start::<#which_nexus>() + .await; #func_ident(&ctx).await; ctx.teardown().await; } diff --git a/nexus/test-utils/src/lib.rs b/nexus/test-utils/src/lib.rs index 4ea9e1e1c1e..cb2ca7be03e 100644 --- a/nexus/test-utils/src/lib.rs +++ b/nexus/test-utils/src/lib.rs @@ -25,12 +25,11 @@ pub mod resource_helpers; pub mod sql; mod starter; +pub use nexus_test::ControlPlaneBuilder; pub use nexus_test::ControlPlaneTestContext; pub use nexus_test::load_test_config; #[cfg(feature = "omicron-dev")] pub use nexus_test::omicron_dev_setup_with_config; -pub use nexus_test::test_setup; -pub use nexus_test::test_setup_with_config; pub use starter::ControlPlaneStarter; pub use starter::ControlPlaneTestContextSledAgent; pub use starter::register_test_producer; diff --git a/nexus/test-utils/src/nexus_test.rs b/nexus/test-utils/src/nexus_test.rs index 9ed1fda60e0..f604926deb4 100644 --- a/nexus/test-utils/src/nexus_test.rs +++ b/nexus/test-utils/src/nexus_test.rs @@ -38,6 +38,97 @@ use std::collections::HashMap; use std::sync::{Arc, RwLock}; use std::time::Duration; +pub struct ControlPlaneBuilder<'a> { + // required + test_name: &'a str, + + // fields with defaults that are cheap to construct + nextra_sled_agents: u16, + sim_mode: sim::SimMode, + tls_cert: Option, + gateway_config_file: Utf8PathBuf, + + // fields with defaults that need to be constructed lazily + nexus_config: Option, +} + +impl<'a> ControlPlaneBuilder<'a> { + pub fn new(test_name: &'a str) -> ControlPlaneBuilder<'a> { + ControlPlaneBuilder { + test_name, + nextra_sled_agents: 0, + sim_mode: sim::SimMode::Explicit, + tls_cert: None, + gateway_config_file: DEFAULT_SP_SIM_CONFIG.into(), + nexus_config: None, + } + } + + pub fn extra_sled_agents(mut self, nextra: u16) -> ControlPlaneBuilder<'a> { + self.nextra_sled_agents = nextra; + self + } + + pub fn sim_mode( + mut self, + sim_mode: sim::SimMode, + ) -> ControlPlaneBuilder<'a> { + self.sim_mode = sim_mode; + self + } + + pub fn tls_cert( + mut self, + tls_cert: Option, + ) -> ControlPlaneBuilder<'a> { + self.tls_cert = tls_cert; + self + } + + pub fn mgs_config_file( + mut self, + path: Utf8PathBuf, + ) -> ControlPlaneBuilder<'a> { + self.gateway_config_file = path; + self + } + + pub fn nexus_config( + mut self, + config: NexusConfig, + ) -> ControlPlaneBuilder<'a> { + self.nexus_config = Some(config); + self + } + + pub fn with_modified_default_config( + mut self, + f: &dyn Fn(&mut NexusConfig) -> (), + ) -> ControlPlaneBuilder<'a> { + let mut config = load_test_config(); + f(&mut config); + self.nexus_config = Some(config); + self + } + + pub async fn start(self) -> ControlPlaneTestContext { + let mut nexus_config = + self.nexus_config.unwrap_or_else(|| load_test_config()); + let starter = + ControlPlaneStarter::::new(self.test_name, &mut nexus_config); + setup_with_config_impl( + starter, + PopulateCrdb::FromEnvironmentSeed, + self.sim_mode, + self.tls_cert, + self.nextra_sled_agents, + self.gateway_config_file, + false, + ) + .await + } +} + pub struct ControlPlaneTestContext { pub start_time: chrono::DateTime, pub external_client: ClientTestContext, @@ -212,44 +303,6 @@ pub fn load_test_config() -> NexusConfig { .expect("failed to load config.test.toml") } -pub async fn test_setup( - test_name: &str, - extra_sled_agents: u16, -) -> ControlPlaneTestContext { - let mut config = load_test_config(); - test_setup_with_config::( - test_name, - &mut config, - sim::SimMode::Explicit, - None, - extra_sled_agents, - DEFAULT_SP_SIM_CONFIG.into(), - ) - .await -} - -/// Setup routine to use for tests. -pub async fn test_setup_with_config( - test_name: &str, - config: &mut NexusConfig, - sim_mode: sim::SimMode, - initial_cert: Option, - extra_sled_agents: u16, - gateway_config_file: Utf8PathBuf, -) -> ControlPlaneTestContext { - let starter = ControlPlaneStarter::::new(test_name, config); - setup_with_config_impl( - starter, - PopulateCrdb::FromEnvironmentSeed, - sim_mode, - initial_cert, - extra_sled_agents, - gateway_config_file, - false, - ) - .await -} - /// Setup routine to use for `omicron-dev`. Use [`test_setup_with_config`] for /// tests. /// diff --git a/nexus/tests/integration_tests/certificates.rs b/nexus/tests/integration_tests/certificates.rs index 848a869eeca..7324398c1bc 100644 --- a/nexus/tests/integration_tests/certificates.rs +++ b/nexus/tests/integration_tests/certificates.rs @@ -8,13 +8,11 @@ use display_error_chain::ErrorChainExt; use dropshot::HttpErrorResponseBody; use dropshot::test_util::ClientTestContext; use futures::TryStreamExt; -use gateway_test_utils::setup::DEFAULT_SP_SIM_CONFIG; use http::StatusCode; use http::method::Method; use internal_dns_types::names::DNS_ZONE_EXTERNAL_TESTING; use nexus_test_utils::http_testing::AuthnMode; use nexus_test_utils::http_testing::NexusRequest; -use nexus_test_utils::load_test_config; use nexus_test_utils::resource_helpers::create_certificate; use nexus_test_utils::resource_helpers::delete_certificate; use nexus_test_utils_macros::nexus_test; @@ -345,19 +343,14 @@ async fn test_silo_certificates() { let silo3 = SiloCert::new("silo3".parse().unwrap()); // Start Nexus with a TLS server instead of its usual HTTP server. - let cptestctx = { - let mut config = load_test_config(); - config.deployment.dropshot_external.tls = true; - nexus_test_utils::test_setup_with_config::( - "test_silo_certificates", - &mut config, - omicron_sled_agent::sim::SimMode::Explicit, - Some(silo1.cert.clone()), - 0, - DEFAULT_SP_SIM_CONFIG.into(), - ) - .await - }; + let cptestctx = + nexus_test_utils::ControlPlaneBuilder::new("test_silo_certificates") + .with_modified_default_config(&|config| { + config.deployment.dropshot_external.tls = true; + }) + .tls_cert(Some(silo1.cert.clone())) + .start::() + .await; let nexus_port = cptestctx.external_client.bind_address.port(); diff --git a/nexus/tests/integration_tests/console_api.rs b/nexus/tests/integration_tests/console_api.rs index 760af15717e..c22a5f3e12f 100644 --- a/nexus/tests/integration_tests/console_api.rs +++ b/nexus/tests/integration_tests/console_api.rs @@ -6,7 +6,6 @@ use anyhow::Context; use camino::Utf8PathBuf; use dropshot::ResultsPage; use dropshot::test_util::ClientTestContext; -use gateway_test_utils::setup::DEFAULT_SP_SIM_CONFIG; use http::{StatusCode, header, method::Method}; use nexus_auth::context::OpContext; use std::env::current_dir; @@ -22,7 +21,6 @@ use nexus_test_utils::resource_helpers::create_console_session; use nexus_test_utils::resource_helpers::{ create_silo, grant_iam, object_create, }; -use nexus_test_utils::{load_test_config, test_setup_with_config}; use nexus_test_utils_macros::nexus_test; use nexus_types::external_api::params::{self, ProjectCreate}; use nexus_types::external_api::shared::{ @@ -30,7 +28,6 @@ use nexus_types::external_api::shared::{ }; use nexus_types::external_api::{shared, views}; use omicron_common::api::external::{Error, IdentityMetadataCreateParams}; -use omicron_sled_agent::sim; use omicron_test_utils::dev::poll::{CondCheckError, wait_for_condition}; type ControlPlaneTestContext = @@ -387,20 +384,16 @@ async fn test_assets(cptestctx: &ControlPlaneTestContext) { #[tokio::test] async fn test_absolute_static_dir() { - let mut config = load_test_config(); - config.pkg.console.static_dir = - Utf8PathBuf::try_from(current_dir().unwrap()) - .unwrap() - .join("tests/static"); - let cptestctx = test_setup_with_config::( - "test_absolute_static_dir", - &mut config, - sim::SimMode::Explicit, - None, - 0, - DEFAULT_SP_SIM_CONFIG.into(), - ) - .await; + let cptestctx = + nexus_test_utils::ControlPlaneBuilder::new("test_absolute_static_dir") + .with_modified_default_config(&|config| { + config.pkg.console.static_dir = + Utf8PathBuf::try_from(current_dir().unwrap()) + .unwrap() + .join("tests/static"); + }) + .start::() + .await; let testctx = &cptestctx.external_client; // existing file is returned @@ -941,17 +934,14 @@ async fn expect_redirect(testctx: &ClientTestContext, from: &str, to: &str) { /// the session was found but is expired. vs not found at all #[tokio::test] async fn test_session_idle_timeout_deletes_session() { - // set idle timeout to 0 so we can test expiration - let mut config = load_test_config(); - config.pkg.console.session_idle_timeout_minutes = 0; - let cptestctx = test_setup_with_config::( + let cptestctx = nexus_test_utils::ControlPlaneBuilder::new( "test_session_idle_timeout_deletes_session", - &mut config, - sim::SimMode::Explicit, - None, - 0, - DEFAULT_SP_SIM_CONFIG.into(), ) + .with_modified_default_config(&|config| { + // set idle timeout to 0 so we can test expiration + config.pkg.console.session_idle_timeout_minutes = 0; + }) + .start::() .await; let testctx = &cptestctx.external_client; diff --git a/nexus/tests/integration_tests/device_auth.rs b/nexus/tests/integration_tests/device_auth.rs index 99d38fec1a5..52685e4ec91 100644 --- a/nexus/tests/integration_tests/device_auth.rs +++ b/nexus/tests/integration_tests/device_auth.rs @@ -7,7 +7,6 @@ use std::num::NonZeroU32; use chrono::Utc; use dropshot::test_util::ClientTestContext; use dropshot::{HttpErrorResponseBody, ResultsPage}; -use gateway_test_utils::setup::DEFAULT_SP_SIM_CONFIG; use nexus_auth::authn::USER_TEST_UNPRIVILEGED; use nexus_config::NexusConfig; use nexus_db_queries::db::fixed_data::silo::DEFAULT_SILO; @@ -21,7 +20,6 @@ use nexus_test_utils::{ http_testing::{AuthnMode, NexusRequest, RequestBuilder}, resource_helpers::grant_iam, }; -use nexus_test_utils::{load_test_config, test_setup_with_config}; use nexus_test_utils_macros::nexus_test; use nexus_types::external_api::{params, views}; use nexus_types::external_api::{ @@ -33,7 +31,6 @@ use nexus_types::external_api::{ use omicron_uuid_kinds::SiloUserUuid; use http::{StatusCode, header, method::Method}; -use omicron_sled_agent::sim; use oxide_client::types::{FleetRole, SiloRole}; use serde::Deserialize; use tokio::time::{Duration, sleep}; @@ -994,34 +991,38 @@ async fn test_admin_logout_deletes_tokens_and_sessions( #[tokio::test] async fn test_session_list_excludes_expired() { // Test with default TTL - session should not be expired - let mut config = load_test_config(); - test_session_list_with_config(&mut config, 1).await; + test_session_list_with_config(&|_config| (), 1).await; // Test with idle TTL = 0 - session should be expired immediately - let mut config = load_test_config(); - config.pkg.console.session_idle_timeout_minutes = 0; - test_session_list_with_config(&mut config, 0).await; + test_session_list_with_config( + &|config| { + config.pkg.console.session_idle_timeout_minutes = 0; + }, + 0, + ) + .await; // Test with abs TTL = 0 - session should be expired immediately - let mut config = load_test_config(); - config.pkg.console.session_absolute_timeout_minutes = 0; - test_session_list_with_config(&mut config, 0).await; + test_session_list_with_config( + &|config| { + config.pkg.console.session_absolute_timeout_minutes = 0; + }, + 0, + ) + .await; } /// Set up a test context with the given config, create a user in the test suite /// silo, and create a session, and assert about the length of the session list async fn test_session_list_with_config( - config: &mut NexusConfig, + modify_config: &dyn Fn(&mut NexusConfig) -> (), expected_sessions: usize, ) { - let cptestctx = test_setup_with_config::( + let cptestctx = nexus_test_utils::ControlPlaneBuilder::new( "test_session_list_excludes_expired", - config, - sim::SimMode::Explicit, - None, - 0, - DEFAULT_SP_SIM_CONFIG.into(), ) + .with_modified_default_config(modify_config) + .start::() .await; let testctx = &cptestctx.external_client; diff --git a/nexus/tests/integration_tests/multicast/cache_invalidation.rs b/nexus/tests/integration_tests/multicast/cache_invalidation.rs index e50da7d2539..f05b0b03240 100644 --- a/nexus/tests/integration_tests/multicast/cache_invalidation.rs +++ b/nexus/tests/integration_tests/multicast/cache_invalidation.rs @@ -287,29 +287,26 @@ async fn test_cache_ttl_driven_refresh() { const GROUP_NAME: &str = "ttl-test-group"; const INSTANCE_NAME: &str = "ttl-test-instance"; - // Load default test config and customize TTLs - let mut config = nexus_test_utils::load_test_config(); - - // Set short cache TTLs for testing (2 seconds for sled cache) - config.pkg.background_tasks.multicast_reconciler.sled_cache_ttl_secs = - chrono::TimeDelta::seconds(2).to_std().unwrap(); - config.pkg.background_tasks.multicast_reconciler.backplane_cache_ttl_secs = - chrono::TimeDelta::seconds(1).to_std().unwrap(); - - // Ensure multicast is enabled - config.pkg.multicast.enabled = true; - // Start test server with custom config - let cptestctx = - nexus_test_utils::test_setup_with_config::( - "test_cache_ttl_driven_refresh", - &mut config, - omicron_sled_agent::sim::SimMode::Explicit, - None, - 0, - gateway_test_utils::setup::DEFAULT_SP_SIM_CONFIG.into(), - ) - .await; + let cptestctx = nexus_test_utils::ControlPlaneBuilder::new( + "test_cache_ttl_driven_refresh", + ) + .with_modified_default_config(&|config| { + // Set short cache TTLs for testing (2 seconds for sled cache) + config.pkg.background_tasks.multicast_reconciler.sled_cache_ttl_secs = + chrono::TimeDelta::seconds(2).to_std().unwrap(); + config + .pkg + .background_tasks + .multicast_reconciler + .backplane_cache_ttl_secs = + chrono::TimeDelta::seconds(1).to_std().unwrap(); + + // Ensure multicast is enabled + config.pkg.multicast.enabled = true; + }) + .start::() + .await; ensure_multicast_test_ready(&cptestctx).await; @@ -504,30 +501,29 @@ async fn test_backplane_cache_ttl_expiry() { const GROUP_NAME: &str = "backplane-ttl-group"; const INSTANCE_NAME: &str = "backplane-ttl-instance"; - // Load default test config and customize TTLs - let mut config = nexus_test_utils::load_test_config(); - - // Set backplane cache TTL to 1 second (shorter than sled cache to test independently) - config.pkg.background_tasks.multicast_reconciler.backplane_cache_ttl_secs = - chrono::TimeDelta::seconds(1).to_std().unwrap(); - // Keep sled cache TTL longer to ensure we're testing backplane cache expiry - config.pkg.background_tasks.multicast_reconciler.sled_cache_ttl_secs = - chrono::TimeDelta::seconds(10).to_std().unwrap(); - - // Ensure multicast is enabled - config.pkg.multicast.enabled = true; - - // Start test server with custom config - let cptestctx = - nexus_test_utils::test_setup_with_config::( - "test_backplane_cache_ttl_expiry", - &mut config, - omicron_sled_agent::sim::SimMode::Explicit, - None, - 0, - gateway_test_utils::setup::DEFAULT_SP_SIM_CONFIG.into(), - ) - .await; + let cptestctx = nexus_test_utils::ControlPlaneBuilder::new( + "test_backplane_cache_ttl_expiry", + ) + .with_modified_default_config(&|config| { + // Set backplane cache TTL to 1 second (shorter than sled cache to test + // independently) + config + .pkg + .background_tasks + .multicast_reconciler + .backplane_cache_ttl_secs = + chrono::TimeDelta::seconds(1).to_std().unwrap(); + + // Keep sled cache TTL longer to ensure we're testing backplane cache + // expiry + config.pkg.background_tasks.multicast_reconciler.sled_cache_ttl_secs = + chrono::TimeDelta::seconds(10).to_std().unwrap(); + + // Ensure multicast is enabled + config.pkg.multicast.enabled = true; + }) + .start::() + .await; ensure_multicast_test_ready(&cptestctx).await; diff --git a/nexus/tests/integration_tests/multicast/enablement.rs b/nexus/tests/integration_tests/multicast/enablement.rs index d8cf90d2440..98aab4fc8ce 100644 --- a/nexus/tests/integration_tests/multicast/enablement.rs +++ b/nexus/tests/integration_tests/multicast/enablement.rs @@ -8,17 +8,14 @@ use std::net::IpAddr; -use gateway_test_utils::setup::DEFAULT_SP_SIM_CONFIG; use nexus_test_utils::resource_helpers::{ create_default_ip_pool, create_project, object_create, object_get, }; -use nexus_test_utils::{load_test_config, test_setup_with_config}; use nexus_types::external_api::params::MulticastGroupCreate; use nexus_types::external_api::views::MulticastGroup; use omicron_common::api::external::{ IdentityMetadataCreateParams, Instance, InstanceState, NameOrId, }; -use omicron_sled_agent::sim; use omicron_uuid_kinds::{GenericUuid, InstanceUuid}; use super::*; @@ -34,19 +31,15 @@ const GROUP_NAME: &str = "test-group"; /// and no multicast members are ever created. #[tokio::test] async fn test_multicast_enablement() { - // Create custom config with multicast disabled (simulating PROD, for now) - let mut config = load_test_config(); - config.pkg.multicast.enabled = false; - - let cptestctx = test_setup_with_config::( - "test_multicast_enablement", - &mut config, - sim::SimMode::Explicit, - None, - 0, - DEFAULT_SP_SIM_CONFIG.into(), - ) - .await; + let cptestctx = + nexus_test_utils::ControlPlaneBuilder::new("test_multicast_enablement") + .with_modified_default_config(&|config| { + // Create custom config with multicast disabled (simulating + // PROD, for now) + config.pkg.multicast.enabled = false; + }) + .start::() + .await; let client = &cptestctx.external_client; diff --git a/nexus/tests/integration_tests/oximeter.rs b/nexus/tests/integration_tests/oximeter.rs index 7e2faa465cf..594f149f6e1 100644 --- a/nexus/tests/integration_tests/oximeter.rs +++ b/nexus/tests/integration_tests/oximeter.rs @@ -73,10 +73,10 @@ async fn test_oximeter_database_records(context: &ControlPlaneTestContext) { #[tokio::test] async fn test_oximeter_reregistration() { - let mut context = nexus_test_utils::test_setup::( + let mut context = nexus_test_utils::ControlPlaneBuilder::new( "test_oximeter_reregistration", - 0, ) + .start::() .await; let db = &context.database; let producer_id: Uuid = nexus_test_utils::PRODUCER_UUID.parse().unwrap(); diff --git a/nexus/tests/integration_tests/target_release.rs b/nexus/tests/integration_tests/target_release.rs index 897b197a859..0a533cbefad 100644 --- a/nexus/tests/integration_tests/target_release.rs +++ b/nexus/tests/integration_tests/target_release.rs @@ -12,7 +12,6 @@ use http::method::Method; use nexus_test_utils::http_testing::AuthnMode; use nexus_test_utils::http_testing::{NexusRequest, RequestBuilder}; use nexus_test_utils::resource_helpers::object_get; -use nexus_test_utils::test_setup; use nexus_types::external_api::params::SetTargetReleaseParams; use nexus_types::external_api::views; use semver::Version; @@ -24,7 +23,9 @@ use crate::integration_tests::updates::TestTrustRoot; #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn get_set_target_release() -> Result<()> { let ctx = - test_setup::("get_set_target_release", 0).await; + nexus_test_utils::ControlPlaneBuilder::new("get_set_target_release") + .start::() + .await; let client = &ctx.external_client; let logctx = &ctx.logctx; diff --git a/nexus/tests/integration_tests/unauthorized.rs b/nexus/tests/integration_tests/unauthorized.rs index a3f57b409ac..6b232ab8ecb 100644 --- a/nexus/tests/integration_tests/unauthorized.rs +++ b/nexus/tests/integration_tests/unauthorized.rs @@ -22,7 +22,6 @@ use nexus_test_utils::http_testing::NexusRequest; use nexus_test_utils::http_testing::RequestBuilder; use nexus_test_utils::http_testing::TestResponse; use nexus_test_utils::resource_helpers::TestDataset; -use nexus_test_utils::test_setup; use omicron_common::disk::DatasetKind; use omicron_uuid_kinds::DatasetUuid; use omicron_uuid_kinds::ZpoolUuid; @@ -64,7 +63,9 @@ type DiskTest<'a> = #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_unauthorized() { let cptestctx = - test_setup::("test_unauthorized", 0).await; + nexus_test_utils::ControlPlaneBuilder::new("test_unauthorized") + .start::() + .await; let mut disk_test = DiskTest::new(&cptestctx).await; let sled_id = cptestctx.first_sled_id(); diff --git a/nexus/tests/integration_tests/updates.rs b/nexus/tests/integration_tests/updates.rs index 1792433153e..a72f78670ff 100644 --- a/nexus/tests/integration_tests/updates.rs +++ b/nexus/tests/integration_tests/updates.rs @@ -18,7 +18,6 @@ use nexus_test_utils::http_testing::{AuthnMode, NexusRequest, RequestBuilder}; use nexus_test_utils::resource_helpers::object_get; use nexus_test_utils::resource_helpers::object_get_error; use nexus_test_utils::resource_helpers::objects_list_page_authz; -use nexus_test_utils::test_setup; use nexus_test_utils_macros::nexus_test; use nexus_types::external_api::views; use nexus_types::external_api::views::{TufRepoUpload, TufRepoUploadStatus}; @@ -173,9 +172,11 @@ impl TestRepo { #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_repo_upload_unconfigured() -> Result<()> { - let cptestctx = - test_setup::("test_update_uninitialized", 0) - .await; + let cptestctx = nexus_test_utils::ControlPlaneBuilder::new( + "test_repo_upload_unconfigured", + ) + .start::() + .await; let client = &cptestctx.external_client; let logctx = &cptestctx.logctx; @@ -214,11 +215,11 @@ async fn test_repo_upload_unconfigured() -> Result<()> { #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_repo_upload() -> Result<()> { - let cptestctx = test_setup::( - "test_update_end_to_end", - 3, // 4 total sled agents - ) - .await; + let cptestctx = + nexus_test_utils::ControlPlaneBuilder::new("test_update_end_to_end") + .extra_sled_agents(3) + .start::() + .await; let client = &cptestctx.external_client; let logctx = &cptestctx.logctx; @@ -711,7 +712,8 @@ async fn test_trust_root_operations(cptestctx: &ControlPlaneTestContext) { #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_update_status() -> Result<()> { let cptestctx = - test_setup::("test_update_uninitialized", 0) + nexus_test_utils::ControlPlaneBuilder::new("test_update_status") + .start::() .await; let client = &cptestctx.external_client; let logctx = &cptestctx.logctx; @@ -863,11 +865,11 @@ async fn test_repo_prune(cptestctx: &ControlPlaneTestContext) { #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_repo_list() -> Result<()> { - let cptestctx = test_setup::( - "test_update_repo_list", - 3, // 4 total sled agents - ) - .await; + let cptestctx = + nexus_test_utils::ControlPlaneBuilder::new("test_repo_list") + .extra_sled_agents(3) + .start::() + .await; let client = &cptestctx.external_client; let logctx = &cptestctx.logctx; From ce73694ed74a7087a3eafd522bc1cae21f7524cb Mon Sep 17 00:00:00 2001 From: David Pacheco Date: Tue, 25 Nov 2025 15:41:13 -0800 Subject: [PATCH 2/2] fix docs --- nexus/test-utils/src/nexus_test.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/nexus/test-utils/src/nexus_test.rs b/nexus/test-utils/src/nexus_test.rs index f604926deb4..403e020225c 100644 --- a/nexus/test-utils/src/nexus_test.rs +++ b/nexus/test-utils/src/nexus_test.rs @@ -129,6 +129,9 @@ impl<'a> ControlPlaneBuilder<'a> { } } +/// Helper for setting up the control plane for testing and accessing its parts +/// +/// See [`ControlPlaneBuilder`] for setting one up. pub struct ControlPlaneTestContext { pub start_time: chrono::DateTime, pub external_client: ClientTestContext, @@ -303,7 +306,7 @@ pub fn load_test_config() -> NexusConfig { .expect("failed to load config.test.toml") } -/// Setup routine to use for `omicron-dev`. Use [`test_setup_with_config`] for +/// Setup routine to use for `omicron-dev`. Use [`ControlPlaneBuilder`] for /// tests. /// /// The main difference from tests is that this routine ensures the seed tarball