diff --git a/Cargo.lock b/Cargo.lock index 8d2124152fe..741af48baf9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1765,6 +1765,14 @@ dependencies = [ "uuid", ] +[[package]] +name = "nexus-test-utils-macros" +version = "0.1.0" +dependencies = [ + "quote", + "syn", +] + [[package]] name = "normalize-line-endings" version = "0.3.0" @@ -1894,6 +1902,7 @@ dependencies = [ "mime_guess", "newtype_derive", "nexus-test-utils", + "nexus-test-utils-macros", "omicron-common", "omicron-rpaths", "omicron-sled-agent", diff --git a/Cargo.toml b/Cargo.toml index 39d8ee8369f..5853d11a0b3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,7 @@ members = [ "nexus", "nexus/src/db/db-macros", "nexus/test-utils", + "nexus/test-utils-macros", "nexus-client", "package", "rpaths", diff --git a/nexus/Cargo.toml b/nexus/Cargo.toml index 14122c0f52b..ee0d04f51cf 100644 --- a/nexus/Cargo.toml +++ b/nexus/Cargo.toml @@ -109,6 +109,7 @@ features = [ "serde", "v4" ] [dev-dependencies] criterion = { version = "0.3", features = [ "async_tokio" ] } expectorate = "1.0.4" +nexus-test-utils-macros = { path = "test-utils-macros" } nexus-test-utils = { path = "test-utils" } omicron-test-utils = { path = "../test-utils" } openapiv3 = "0.5.0" diff --git a/nexus/test-utils-macros/Cargo.toml b/nexus/test-utils-macros/Cargo.toml new file mode 100644 index 00000000000..3fceb1b8339 --- /dev/null +++ b/nexus/test-utils-macros/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "nexus-test-utils-macros" +version = "0.1.0" +edition = "2021" + +[lib] +proc-macro = true + +[dependencies] +quote = "1.0" +syn = { version="1.0", features=["full", "fold", "parsing"] } diff --git a/nexus/test-utils-macros/src/lib.rs b/nexus/test-utils-macros/src/lib.rs new file mode 100644 index 00000000000..865c2c84926 --- /dev/null +++ b/nexus/test-utils-macros/src/lib.rs @@ -0,0 +1,70 @@ +use proc_macro::TokenStream; +use quote::quote; +use syn::{parse_macro_input, ItemFn}; + +/// Attribute for wrapping a test function to handle automatically +/// creating and destroying a ControlPlaneTestContext. If the wrapped test +/// fails, the context will intentionally not be cleaned up to support +/// debugging. The wrapped test a +/// +/// Example usage: +/// +/// // #[nexus_test] +/// // async fn test_my_test_case(cptestctx: &ControlPlaneTestContext) { +/// // assert!(true); +/// // } +/// +/// We use this instead of implementing Drop on ControlPlaneTestContext because +/// we want the teardown to only happen when the test doesn't fail (which causes +/// a panic and unwind). +#[proc_macro_attribute] +pub fn nexus_test(_metadata: TokenStream, input: TokenStream) -> TokenStream { + let input_func = parse_macro_input!(input as ItemFn); + + let mut correct_signature = true; + if input_func.sig.variadic.is_some() + || input_func.sig.inputs.len() != 1 + || input_func.sig.asyncness.is_none() + { + correct_signature = false; + } + + // Verify we're returning an empty tuple + correct_signature &= match input_func.sig.output { + syn::ReturnType::Default => true, + syn::ReturnType::Type(_, ref t) => { + if let syn::Type::Tuple(syn::TypeTuple { elems, .. }) = &**t { + elems.len() == 0 + } else { + false + } + } + }; + if !correct_signature { + panic!("func signature must be async fn(&ControlPlaneTestContext)"); + } + + let func_ident_string = input_func.sig.ident.to_string(); + let func_ident = input_func.sig.ident.clone(); + let new_block = quote! { + { + #input_func + + let ctx = ::nexus_test_utils::test_setup(#func_ident_string).await; + #func_ident(&ctx).await; + ctx.teardown().await; + } + }; + let mut sig = input_func.sig.clone(); + sig.inputs.clear(); + let func = ItemFn { + attrs: input_func.attrs, + vis: input_func.vis, + sig, + block: Box::new(syn::parse2(new_block).unwrap()), + }; + TokenStream::from(quote!( + #[::tokio::test] + #func + )) +} diff --git a/nexus/tests/integration_tests/authz.rs b/nexus/tests/integration_tests/authz.rs index 99c1ac8cba4..8a3eceef1eb 100644 --- a/nexus/tests/integration_tests/authz.rs +++ b/nexus/tests/integration_tests/authz.rs @@ -8,7 +8,8 @@ use nexus_test_utils::http_testing::RequestBuilder; use http::method::Method; use http::StatusCode; -use nexus_test_utils::test_setup; +use nexus_test_utils::ControlPlaneTestContext; +use nexus_test_utils_macros::nexus_test; use omicron_common::api::external::IdentityMetadataCreateParams; use omicron_nexus::authn::external::spoof::HTTP_HEADER_OXIDE_AUTHN_SPOOF; use omicron_nexus::external_api::params; @@ -23,9 +24,8 @@ use omicron_nexus::external_api::params; // authz so that we're at least testing the mechanism itself. Testing this for // all endpoints would ensure that we've applied the mechanism consistently and // correctly for all endpoints. -#[tokio::test] -async fn test_authz_basic() { - let cptestctx = test_setup("test_authz_basic").await; +#[nexus_test] +async fn test_authz_basic(cptestctx: &ControlPlaneTestContext) { let client = &cptestctx.external_client; // With no credentials, we should get back a 401 "Unauthorized" response. @@ -70,8 +70,6 @@ async fn test_authz_basic() { .await; assert_eq!(error.error_code, Some(String::from("Unauthorized"))); assert_eq!(error.message.as_str(), "credentials missing or invalid"); - - cptestctx.teardown().await; } async fn try_create_organization( diff --git a/nexus/tests/integration_tests/basic.rs b/nexus/tests/integration_tests/basic.rs index 44dd8754de4..2bdf0de33eb 100644 --- a/nexus/tests/integration_tests/basic.rs +++ b/nexus/tests/integration_tests/basic.rs @@ -33,12 +33,12 @@ use nexus_test_utils::http_testing::RequestBuilder; use nexus_test_utils::resource_helpers::create_organization; use nexus_test_utils::resource_helpers::create_project; use nexus_test_utils::start_sled_agent; -use nexus_test_utils::test_setup; +use nexus_test_utils::ControlPlaneTestContext; +use nexus_test_utils_macros::nexus_test; -#[tokio::test] -async fn test_basic_failures() { - let testctx = test_setup("basic_failures").await; - let client = &testctx.external_client; +#[nexus_test] +async fn test_basic_failures(cptestctx: &ControlPlaneTestContext) { + let client = &cptestctx.external_client; let org_name = "test-org"; create_organization(&client, &org_name).await; @@ -169,14 +169,11 @@ async fn test_basic_failures() { (allowed characters are lowercase ASCII, digits, and \"-\")", error.message ); - - testctx.teardown().await; } -#[tokio::test] -async fn test_projects_basic() { - let testctx = test_setup("test_projects").await; - let client = &testctx.external_client; +#[nexus_test] +async fn test_projects_basic(cptestctx: &ControlPlaneTestContext) { + let client = &cptestctx.external_client; let org_name = "test-org"; create_organization(&client, &org_name).await; @@ -510,14 +507,11 @@ async fn test_projects_basic() { assert_eq!(projects[1].identity.description, "little lightning"); assert_eq!(projects[2].identity.name, "simproject1"); assert!(projects[2].identity.description.len() > 0); - - testctx.teardown().await; } -#[tokio::test] -async fn test_projects_list() { - let testctx = test_setup("test_projects_list").await; - let client = &testctx.external_client; +#[nexus_test] +async fn test_projects_list(cptestctx: &ControlPlaneTestContext) { + let client = &cptestctx.external_client; let org_name = "test-org"; create_organization(&client, &org_name).await; @@ -636,14 +630,11 @@ async fn test_projects_list() { .map(|v| v.identity.id) .collect::>() ); - - testctx.teardown().await; } -#[tokio::test] -async fn test_sleds_list() { - let testctx = test_setup("test_sleds_list").await; - let client = &testctx.external_client; +#[nexus_test] +async fn test_sleds_list(cptestctx: &ControlPlaneTestContext) { + let client = &cptestctx.external_client; /* Verify that there is one sled to begin with. */ let sleds_url = "/hardware/sleds"; @@ -654,8 +645,9 @@ async fn test_sleds_list() { let mut sas = Vec::with_capacity(nsleds); for _ in 0..nsleds { let sa_id = Uuid::new_v4(); - let log = testctx.logctx.log.new(o!( "sled_id" => sa_id.to_string() )); - let addr = testctx.server.http_server_internal.local_addr(); + let log = + cptestctx.logctx.log.new(o!( "sled_id" => sa_id.to_string() )); + let addr = cptestctx.server.http_server_internal.local_addr(); sas.push(start_sled_agent(log, addr, sa_id).await.unwrap()); } @@ -673,8 +665,6 @@ async fn test_sleds_list() { for sa in sas { sa.http_server.close().await.unwrap(); } - - testctx.teardown().await; } async fn projects_list( diff --git a/nexus/tests/integration_tests/console_api.rs b/nexus/tests/integration_tests/console_api.rs index 574675c7986..253a2fcb1fa 100644 --- a/nexus/tests/integration_tests/console_api.rs +++ b/nexus/tests/integration_tests/console_api.rs @@ -8,14 +8,16 @@ use http::{header, method::Method, StatusCode}; use std::env::current_dir; use nexus_test_utils::http_testing::{RequestBuilder, TestResponse}; -use nexus_test_utils::{load_test_config, test_setup, test_setup_with_config}; +use nexus_test_utils::{ + load_test_config, test_setup_with_config, ControlPlaneTestContext, +}; +use nexus_test_utils_macros::nexus_test; use omicron_common::api::external::IdentityMetadataCreateParams; use omicron_nexus::external_api::console_api::LoginParams; use omicron_nexus::external_api::params::OrganizationCreate; -#[tokio::test] -async fn test_sessions() { - let cptestctx = test_setup("test_sessions").await; +#[nexus_test] +async fn test_sessions(cptestctx: &ControlPlaneTestContext) { let testctx = &cptestctx.external_client; // logout always gives the same response whether you have a session or not @@ -100,13 +102,10 @@ async fn test_sessions() { .execute() .await .expect("failed to get 302 for unauthed console request"); - - cptestctx.teardown().await; } -#[tokio::test] -async fn test_console_pages() { - let cptestctx = test_setup("test_console_pages").await; +#[nexus_test] +async fn test_console_pages(cptestctx: &ControlPlaneTestContext) { let testctx = &cptestctx.external_client; // request to console page route without auth should redirect to IdP @@ -133,13 +132,10 @@ async fn test_console_pages() { .expect("failed to get console index"); assert_eq!(console_page.body, "".as_bytes()); - - cptestctx.teardown().await; } -#[tokio::test] -async fn text_login_form() { - let cptestctx = test_setup("test_login_form").await; +#[nexus_test] +async fn text_login_form(cptestctx: &ControlPlaneTestContext) { let testctx = &cptestctx.external_client; // login route returns bundle too, but is not auth gated @@ -154,13 +150,10 @@ async fn text_login_form() { .expect("failed to get login form"); assert_eq!(console_page.body, "".as_bytes()); - - cptestctx.teardown().await; } -#[tokio::test] -async fn test_assets() { - let cptestctx = test_setup("test_assets").await; +#[nexus_test] +async fn test_assets(cptestctx: &ControlPlaneTestContext) { let testctx = &cptestctx.external_client; // nonexistent file 404s @@ -192,8 +185,6 @@ async fn test_assets() { .expect("failed to get existing file"); assert_eq!(resp.body, "hello there".as_bytes()); - - cptestctx.teardown().await; } #[tokio::test] @@ -211,6 +202,7 @@ async fn test_absolute_static_dir() { .expect("failed to get existing file"); assert_eq!(resp.body, "hello there".as_bytes()); + cptestctx.teardown().await; } diff --git a/nexus/tests/integration_tests/datasets.rs b/nexus/tests/integration_tests/datasets.rs index 3234925605e..ebc89f71378 100644 --- a/nexus/tests/integration_tests/datasets.rs +++ b/nexus/tests/integration_tests/datasets.rs @@ -11,15 +11,15 @@ use omicron_nexus::internal_api::params::{ use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use uuid::Uuid; -use nexus_test_utils::{test_setup, SLED_AGENT_UUID}; +use nexus_test_utils::{ControlPlaneTestContext, SLED_AGENT_UUID}; +use nexus_test_utils_macros::nexus_test; // Tests the "normal" case of dataset_put: inserting a dataset within a known // zpool. // // This will typically be invoked by the Sled Agent, after performing inventory. -#[tokio::test] -async fn test_dataset_put_success() { - let cptestctx = test_setup("test_dataset_put_success").await; +#[nexus_test] +async fn test_dataset_put_success(cptestctx: &ControlPlaneTestContext) { let client = &cptestctx.internal_client; let zpool_id = Uuid::new_v4(); @@ -53,16 +53,14 @@ async fn test_dataset_put_success() { ) .await .unwrap(); - - cptestctx.teardown().await; } // Tests a failure case of dataset_put: Inserting a dataset into a zpool that // does not exist. -#[tokio::test] -async fn test_dataset_put_bad_zpool_returns_not_found() { - let cptestctx = - test_setup("test_dataset_put_bad_zpool_returns_not_found").await; +#[nexus_test] +async fn test_dataset_put_bad_zpool_returns_not_found( + cptestctx: &ControlPlaneTestContext, +) { let client = &cptestctx.internal_client; // A zpool with the "nil" UUID should not exist. @@ -84,5 +82,4 @@ async fn test_dataset_put_bad_zpool_returns_not_found() { StatusCode::NOT_FOUND, ) .await; - cptestctx.teardown().await; } diff --git a/nexus/tests/integration_tests/disks.rs b/nexus/tests/integration_tests/disks.rs index 88142097742..2f12667650b 100644 --- a/nexus/tests/integration_tests/disks.rs +++ b/nexus/tests/integration_tests/disks.rs @@ -33,15 +33,15 @@ use nexus_test_utils::http_testing::RequestBuilder; use nexus_test_utils::identity_eq; use nexus_test_utils::resource_helpers::create_organization; use nexus_test_utils::resource_helpers::create_project; -use nexus_test_utils::test_setup; +use nexus_test_utils::ControlPlaneTestContext; +use nexus_test_utils_macros::nexus_test; /* * TODO-cleanup the mess of URLs used here and in test_instances.rs ought to * come from common code. */ -#[tokio::test] -async fn test_disks() { - let cptestctx = test_setup("test_disks").await; +#[nexus_test] +async fn test_disks(cptestctx: &ControlPlaneTestContext) { let client = &cptestctx.external_client; let apictx = &cptestctx.server.apictx; let nexus = &apictx.nexus; @@ -534,8 +534,6 @@ async fn test_disks() { .make_request_error(Method::GET, &disk_url, StatusCode::NOT_FOUND) .await; assert_eq!(error.message, "not found: disk with name \"just-rainsticks\""); - - cptestctx.teardown().await; } async fn disk_get(client: &ClientTestContext, disk_url: &str) -> Disk { diff --git a/nexus/tests/integration_tests/instances.rs b/nexus/tests/integration_tests/instances.rs index 51913289e9b..b7564223f02 100644 --- a/nexus/tests/integration_tests/instances.rs +++ b/nexus/tests/integration_tests/instances.rs @@ -30,16 +30,16 @@ use dropshot::test_util::ClientTestContext; use nexus_test_utils::identity_eq; use nexus_test_utils::resource_helpers::{create_organization, create_project}; -use nexus_test_utils::test_setup; +use nexus_test_utils::ControlPlaneTestContext; +use nexus_test_utils_macros::nexus_test; static ORGANIZATION_NAME: &str = "test-org"; static PROJECT_NAME: &str = "springfield-squidport"; -#[tokio::test] -async fn test_instances_access_before_create_returns_not_found() { - let cptestctx = - test_setup("test_instances_access_before_create_returns_not_found") - .await; +#[nexus_test] +async fn test_instances_access_before_create_returns_not_found( + cptestctx: &ControlPlaneTestContext, +) { let client = &cptestctx.external_client; /* Create a project that we'll use for testing. */ @@ -76,12 +76,12 @@ async fn test_instances_access_before_create_returns_not_found() { error.message, "not found: instance with name \"just-rainsticks\"" ); - cptestctx.teardown().await; } -#[tokio::test] -async fn test_instances_create_reboot_halt() { - let cptestctx = test_setup("test_instances_create_reboot_halt").await; +#[nexus_test] +async fn test_instances_create_reboot_halt( + cptestctx: &ControlPlaneTestContext, +) { let client = &cptestctx.external_client; let apictx = &cptestctx.server.apictx; let nexus = &apictx.nexus; @@ -369,16 +369,12 @@ async fn test_instances_create_reboot_halt() { StatusCode::NOT_FOUND, ) .await; - - cptestctx.teardown().await; } -#[tokio::test] -async fn test_instances_delete_fails_when_running_succeeds_when_stopped() { - let cptestctx = test_setup( - "test_instances_delete_fails_when_running_succeeds_when_stopped", - ) - .await; +#[nexus_test] +async fn test_instances_delete_fails_when_running_succeeds_when_stopped( + cptestctx: &ControlPlaneTestContext, +) { let client = &cptestctx.external_client; let apictx = &cptestctx.server.apictx; let nexus = &apictx.nexus; @@ -433,20 +429,19 @@ async fn test_instances_delete_fails_when_running_succeeds_when_stopped() { // Now deletion should succeed. object_delete(&client, &instance_url).await; - - cptestctx.teardown().await; } -#[tokio::test] -async fn test_instances_invalid_creation_returns_bad_request() { +#[nexus_test] +async fn test_instances_invalid_creation_returns_bad_request( + cptestctx: &ControlPlaneTestContext, +) { /* * The rest of these examples attempt to create invalid instances. We don't * do exhaustive tests of the model here -- those are part of unit tests -- * but we exercise a few different types of errors to make sure those get * passed through properly. */ - let cptestctx = - test_setup("test_instances_invalid_creation_returns_bad_request").await; + let client = &cptestctx.external_client; let url_instances = format!( "/organizations/{}/projects/{}/instances", @@ -487,8 +482,6 @@ async fn test_instances_invalid_creation_returns_bad_request() { assert!(error .message .starts_with("unable to parse body: invalid value: integer `-3`")); - - cptestctx.teardown().await; } async fn instance_get( diff --git a/nexus/tests/integration_tests/organizations.rs b/nexus/tests/integration_tests/organizations.rs index 68389c248ce..fdcb3c95c6e 100644 --- a/nexus/tests/integration_tests/organizations.rs +++ b/nexus/tests/integration_tests/organizations.rs @@ -11,11 +11,11 @@ use http::StatusCode; use nexus_test_utils::resource_helpers::{ create_organization, create_project, objects_list_page_authz, }; -use nexus_test_utils::test_setup; +use nexus_test_utils::ControlPlaneTestContext; +use nexus_test_utils_macros::nexus_test; -#[tokio::test] -async fn test_organizations() { - let cptestctx = test_setup("test_organizations").await; +#[nexus_test] +async fn test_organizations(cptestctx: &ControlPlaneTestContext) { let client = &cptestctx.external_client; /* Create organizations that we'll use for testing. */ @@ -87,6 +87,4 @@ async fn test_organizations() { // Delete the project, then delete the organization object_delete(&client, &project_url).await; object_delete(&client, &o2_url).await; - - cptestctx.teardown().await; } diff --git a/nexus/tests/integration_tests/oximeter.rs b/nexus/tests/integration_tests/oximeter.rs index fb6cfc8f147..a3575173adc 100644 --- a/nexus/tests/integration_tests/oximeter.rs +++ b/nexus/tests/integration_tests/oximeter.rs @@ -4,16 +4,16 @@ //! Integration tests for oximeter collectors and producers. +use nexus_test_utils::ControlPlaneTestContext; +use nexus_test_utils_macros::nexus_test; use omicron_test_utils::dev::poll::{wait_for_condition, CondCheckError}; use oximeter_db::DbWrite; use std::net; use std::time::Duration; use uuid::Uuid; -#[tokio::test] -async fn test_oximeter_database_records() { - let context = - nexus_test_utils::test_setup("test_oximeter_database_records").await; +#[nexus_test] +async fn test_oximeter_database_records(context: &ControlPlaneTestContext) { let db = &context.database; // Get a handle to the DB, for various tests @@ -58,8 +58,6 @@ async fn test_oximeter_database_records() { nexus_test_utils::OXIMETER_UUID.parse().unwrap(), "Producer's oximeter ID returned from the database does not match the expected ID" ); - - context.teardown().await; } #[tokio::test] diff --git a/nexus/tests/integration_tests/projects.rs b/nexus/tests/integration_tests/projects.rs index 9c92f66bd66..74f8a882221 100644 --- a/nexus/tests/integration_tests/projects.rs +++ b/nexus/tests/integration_tests/projects.rs @@ -8,11 +8,11 @@ use dropshot::test_util::object_get; use dropshot::test_util::objects_list_page; use nexus_test_utils::resource_helpers::{create_organization, create_project}; -use nexus_test_utils::test_setup; +use nexus_test_utils::ControlPlaneTestContext; +use nexus_test_utils_macros::nexus_test; -#[tokio::test] -async fn test_projects() { - let cptestctx = test_setup("test_projects").await; +#[nexus_test] +async fn test_projects(cptestctx: &ControlPlaneTestContext) { let client = &cptestctx.external_client; let org_name = "test-org"; @@ -62,6 +62,4 @@ async fn test_projects() { .items; assert_eq!(projects.len(), 1); assert_eq!(projects[0].identity.name, p1_name); - - cptestctx.teardown().await; } diff --git a/nexus/tests/integration_tests/router_routes.rs b/nexus/tests/integration_tests/router_routes.rs index 241518c2cfd..25d1676d34e 100644 --- a/nexus/tests/integration_tests/router_routes.rs +++ b/nexus/tests/integration_tests/router_routes.rs @@ -9,7 +9,8 @@ use dropshot::test_util::{ }; use dropshot::Method; use http::StatusCode; -use nexus_test_utils::test_setup; +use nexus_test_utils::ControlPlaneTestContext; +use nexus_test_utils_macros::nexus_test; use omicron_common::api::external::{ IdentityMetadataCreateParams, IdentityMetadataUpdateParams, Name, RouteDestination, RouteTarget, RouterRoute, RouterRouteCreateParams, @@ -20,9 +21,8 @@ use nexus_test_utils::resource_helpers::{ create_organization, create_project, create_router, create_vpc, }; -#[tokio::test] -async fn test_router_routes() { - let cptestctx = test_setup("test_vpc_routers").await; +#[nexus_test] +async fn test_router_routes(cptestctx: &ControlPlaneTestContext) { let client = &cptestctx.external_client; let organization_name = "test-org"; @@ -165,6 +165,4 @@ async fn test_router_routes() { StatusCode::NOT_FOUND, ) .await; - - cptestctx.teardown().await; } diff --git a/nexus/tests/integration_tests/subnet_allocation.rs b/nexus/tests/integration_tests/subnet_allocation.rs index 68e95db7722..1cc5133019d 100644 --- a/nexus/tests/integration_tests/subnet_allocation.rs +++ b/nexus/tests/integration_tests/subnet_allocation.rs @@ -22,7 +22,8 @@ use dropshot::test_util::ClientTestContext; use dropshot::HttpErrorResponseBody; use nexus_test_utils::resource_helpers::{create_organization, create_project}; -use nexus_test_utils::test_setup; +use nexus_test_utils::ControlPlaneTestContext; +use nexus_test_utils_macros::nexus_test; async fn create_instance( client: &ClientTestContext, @@ -66,9 +67,8 @@ async fn create_instance_expect_failure( .await } -#[tokio::test] -async fn test_subnet_allocation() { - let cptestctx = test_setup("test_subnet_allocation").await; +#[nexus_test] +async fn test_subnet_allocation(cptestctx: &ControlPlaneTestContext) { let client = &cptestctx.external_client; let organization_name = "test-org"; @@ -133,6 +133,4 @@ async fn test_subnet_allocation() { network_interfaces[1].ip, "192.168.42.6".parse::().unwrap() ); - - cptestctx.teardown().await; } diff --git a/nexus/tests/integration_tests/users_builtin.rs b/nexus/tests/integration_tests/users_builtin.rs index 1ff12c10587..210c29b8d3f 100644 --- a/nexus/tests/integration_tests/users_builtin.rs +++ b/nexus/tests/integration_tests/users_builtin.rs @@ -8,13 +8,13 @@ use std::collections::BTreeMap; use nexus_test_utils::http_testing::AuthnMode; use nexus_test_utils::http_testing::NexusRequest; use nexus_test_utils::http_testing::RequestBuilder; -use nexus_test_utils::test_setup; +use nexus_test_utils::ControlPlaneTestContext; +use nexus_test_utils_macros::nexus_test; use omicron_nexus::authn; use omicron_nexus::external_api::views::User; -#[tokio::test] -async fn test_users_builtin() { - let cptestctx = test_setup("test_users_builtin").await; +#[nexus_test] +async fn test_users_builtin(cptestctx: &ControlPlaneTestContext) { let testctx = &cptestctx.external_client; RequestBuilder::new(testctx, Method::GET, "/users") @@ -55,5 +55,4 @@ async fn test_users_builtin() { users.remove(&authn::USER_TEST_UNPRIVILEGED.name.to_string()).unwrap(); assert_eq!(u.identity.id, authn::USER_TEST_UNPRIVILEGED.id); assert!(users.is_empty(), "found unexpected built-in users"); - cptestctx.teardown().await; } diff --git a/nexus/tests/integration_tests/vpc_firewall.rs b/nexus/tests/integration_tests/vpc_firewall.rs index 73bab3ae95a..964aaf1941f 100644 --- a/nexus/tests/integration_tests/vpc_firewall.rs +++ b/nexus/tests/integration_tests/vpc_firewall.rs @@ -19,11 +19,11 @@ use dropshot::test_util::{object_delete, objects_list_page}; use nexus_test_utils::resource_helpers::{ create_organization, create_project, create_vpc, }; -use nexus_test_utils::test_setup; +use nexus_test_utils::ControlPlaneTestContext; +use nexus_test_utils_macros::nexus_test; -#[tokio::test] -async fn test_vpc_firewall() { - let cptestctx = test_setup("test_vpc_firewall").await; +#[nexus_test] +async fn test_vpc_firewall(cptestctx: &ControlPlaneTestContext) { let client = &cptestctx.external_client; /* Create a project that we'll use for testing. */ @@ -138,7 +138,6 @@ async fn test_vpc_firewall() { StatusCode::NOT_FOUND, ) .await; - cptestctx.teardown().await; } fn is_default_firewall_rules(rules: &Vec) -> bool { diff --git a/nexus/tests/integration_tests/vpc_routers.rs b/nexus/tests/integration_tests/vpc_routers.rs index 6520fd5c1ff..721c94a6f28 100644 --- a/nexus/tests/integration_tests/vpc_routers.rs +++ b/nexus/tests/integration_tests/vpc_routers.rs @@ -18,11 +18,11 @@ use nexus_test_utils::identity_eq; use nexus_test_utils::resource_helpers::{ create_organization, create_project, create_vpc, }; -use nexus_test_utils::test_setup; +use nexus_test_utils::ControlPlaneTestContext; +use nexus_test_utils_macros::nexus_test; -#[tokio::test] -async fn test_vpc_routers() { - let cptestctx = test_setup("test_vpc_routers").await; +#[nexus_test] +async fn test_vpc_routers(cptestctx: &ControlPlaneTestContext) { let client = &cptestctx.external_client; /* Create a project that we'll use for testing. */ @@ -203,8 +203,6 @@ async fn test_vpc_routers() { "it's also not really a router" ); assert_eq!(router_same_name.vpc_id, vpc2.identity.id); - - cptestctx.teardown().await; } fn routers_eq(sn1: &VpcRouter, sn2: &VpcRouter) { diff --git a/nexus/tests/integration_tests/vpc_subnets.rs b/nexus/tests/integration_tests/vpc_subnets.rs index 2d9cfe71061..c82ed72abc8 100644 --- a/nexus/tests/integration_tests/vpc_subnets.rs +++ b/nexus/tests/integration_tests/vpc_subnets.rs @@ -20,11 +20,11 @@ use nexus_test_utils::identity_eq; use nexus_test_utils::resource_helpers::{ create_organization, create_project, create_vpc, }; -use nexus_test_utils::test_setup; +use nexus_test_utils::ControlPlaneTestContext; +use nexus_test_utils_macros::nexus_test; -#[tokio::test] -async fn test_vpc_subnets() { - let cptestctx = test_setup("test_vpc_subnets").await; +#[nexus_test] +async fn test_vpc_subnets(cptestctx: &ControlPlaneTestContext) { let client = &cptestctx.external_client; /* Create a project that we'll use for testing. */ @@ -247,8 +247,6 @@ async fn test_vpc_subnets() { assert_eq!(subnet_same_name.vpc_id, vpc2.identity.id); assert_eq!(subnet_same_name.ipv4_block, None); assert_eq!(subnet_same_name.ipv6_block, None); - - cptestctx.teardown().await; } fn subnets_eq(sn1: &VpcSubnet, sn2: &VpcSubnet) { diff --git a/nexus/tests/integration_tests/vpcs.rs b/nexus/tests/integration_tests/vpcs.rs index 3978e78417e..9daf01b1680 100644 --- a/nexus/tests/integration_tests/vpcs.rs +++ b/nexus/tests/integration_tests/vpcs.rs @@ -15,11 +15,11 @@ use nexus_test_utils::identity_eq; use nexus_test_utils::resource_helpers::{ create_organization, create_project, create_vpc, create_vpc_with_error, }; -use nexus_test_utils::test_setup; +use nexus_test_utils::ControlPlaneTestContext; +use nexus_test_utils_macros::nexus_test; -#[tokio::test] -async fn test_vpcs() { - let cptestctx = test_setup("test_vpcs").await; +#[nexus_test] +async fn test_vpcs(cptestctx: &ControlPlaneTestContext) { let client = &cptestctx.external_client; /* Create a project that we'll use for testing. */ @@ -128,8 +128,6 @@ async fn test_vpcs() { let vpcs = vpcs_list(&client, &vpcs_url).await; assert_eq!(vpcs.len(), 1); vpcs_eq(&vpcs[0], &default_vpc); - - cptestctx.teardown().await; } async fn vpcs_list(client: &ClientTestContext, vpcs_url: &str) -> Vec { diff --git a/nexus/tests/integration_tests/zpools.rs b/nexus/tests/integration_tests/zpools.rs index c6f6d0a3e6c..0896e2e1593 100644 --- a/nexus/tests/integration_tests/zpools.rs +++ b/nexus/tests/integration_tests/zpools.rs @@ -8,14 +8,14 @@ use omicron_common::api::external::ByteCount; use omicron_nexus::internal_api::params::ZpoolPutRequest; use uuid::Uuid; -use nexus_test_utils::{test_setup, SLED_AGENT_UUID}; +use nexus_test_utils::{ControlPlaneTestContext, SLED_AGENT_UUID}; +use nexus_test_utils_macros::nexus_test; // Tests the "normal" case of zpool_put: inserting a known Zpool. // // This will typically be invoked by the Sled Agent, after performing inventory. -#[tokio::test] -async fn test_zpool_put_success() { - let cptestctx = test_setup("test_zpool_put_success").await; +#[nexus_test] +async fn test_zpool_put_success(cptestctx: &ControlPlaneTestContext) { let client = &cptestctx.internal_client; let zpool_id = Uuid::new_v4(); @@ -32,16 +32,14 @@ async fn test_zpool_put_success() { ) .await .unwrap(); - - cptestctx.teardown().await; } // Tests a failure case of zpool_put: Inserting a zpool into a sled agent that // does not exist. -#[tokio::test] -async fn test_zpool_put_bad_sled_returns_not_found() { - let cptestctx = - test_setup("test_zpool_put_bad_sled_returns_not_found").await; +#[nexus_test] +async fn test_zpool_put_bad_sled_returns_not_found( + cptestctx: &ControlPlaneTestContext, +) { let client = &cptestctx.internal_client; // A sled with the "nil" UUID should not exist. @@ -58,5 +56,4 @@ async fn test_zpool_put_bad_sled_returns_not_found() { StatusCode::NOT_FOUND, ) .await; - cptestctx.teardown().await; }