diff --git a/src/CoreTests/Bugs/Bug_4185_codegen_conflict_projection_with_secondary_store_dependency.cs b/src/CoreTests/Bugs/Bug_4185_codegen_conflict_projection_with_secondary_store_dependency.cs index e6c5e162a8..c435813a11 100644 --- a/src/CoreTests/Bugs/Bug_4185_codegen_conflict_projection_with_secondary_store_dependency.cs +++ b/src/CoreTests/Bugs/Bug_4185_codegen_conflict_projection_with_secondary_store_dependency.cs @@ -66,31 +66,22 @@ public void Apply(OrderShipped4185 e, OrderSummary4185 summary) /// secondary IDocumentStore via constructor injection; that's what /// this remaining test pins. /// -public class Bug_4185_codegen_conflict_projection_with_secondary_store_dependency +public class Bug_4185_codegen_conflict_projection_with_secondary_store_dependency: HostedStoreContext { [Fact] public async Task projection_with_secondary_store_dependency_should_work_at_runtime() { - using var host = await Host.CreateDefaultBuilder() - .ConfigureServices(services => + var host = await StartHostAsync(_ => { }, + configureServices: services => services.AddMartenStore(opts => { - services.AddMartenStore(opts => - { - opts.Connection(ConnectionSource.ConnectionString); - opts.DatabaseSchemaName = "bug4185_sec"; - }); - - services.AddMarten(opts => - { - opts.Connection(ConnectionSource.ConnectionString); - opts.DatabaseSchemaName = "bug4185_pri"; - }) - .AddProjectionWithServices( - ProjectionLifecycle.Inline, - ServiceLifetime.Singleton) - .ApplyAllDatabaseChangesOnStartup(); - }) - .StartAsync(); + opts.Connection(ConnectionSource.ConnectionString); + opts.DatabaseSchemaName = $"{SchemaName}_sec"; + }), + configureMarten: marten => marten + .AddProjectionWithServices( + ProjectionLifecycle.Inline, + ServiceLifetime.Singleton) + .ApplyAllDatabaseChangesOnStartup()); var store = host.Services.GetRequiredService(); var streamId = Guid.NewGuid(); diff --git a/src/CoreTests/Bugs/Bug_4187_ancillary_store_isolation.cs b/src/CoreTests/Bugs/Bug_4187_ancillary_store_isolation.cs index 524edc6a18..2837eb7206 100644 --- a/src/CoreTests/Bugs/Bug_4187_ancillary_store_isolation.cs +++ b/src/CoreTests/Bugs/Bug_4187_ancillary_store_isolation.cs @@ -14,7 +14,7 @@ namespace CoreTests.Bugs; /// Regression test for #4187: document tables from ancillary stores should never /// be created in the main store's database. /// -public class Bug_4187_ancillary_store_isolation +public class Bug_4187_ancillary_store_isolation: HostedStoreContext { // Types only used in the primary store public class PrimaryDoc @@ -36,27 +36,19 @@ public interface IAncillaryStore : IDocumentStore; [Fact] public async Task ancillary_store_types_should_not_appear_in_primary_store_schema() { - using var host = await Host.CreateDefaultBuilder() - .ConfigureServices(services => + var host = await StartHostAsync(opts => { - services.AddMarten(opts => - { - opts.Connection(ConnectionSource.ConnectionString); - opts.DatabaseSchemaName = "primary_4187"; - opts.RegisterDocumentType(); - // Explicitly do NOT register AncillaryDoc - }) - .ApplyAllDatabaseChangesOnStartup(); - - services.AddMartenStore(opts => - { - opts.Connection(ConnectionSource.ConnectionString); - opts.DatabaseSchemaName = "ancillary_4187"; - opts.RegisterDocumentType(); - // Explicitly do NOT register PrimaryDoc - }); - }) - .StartAsync(); + opts.RegisterDocumentType(); + // Explicitly do NOT register AncillaryDoc + }, + configureServices: services => services.AddMartenStore(opts => + { + opts.Connection(ConnectionSource.ConnectionString); + opts.DatabaseSchemaName = $"{SchemaName}_ancillary"; + opts.RegisterDocumentType(); + // Explicitly do NOT register PrimaryDoc + }), + configureMarten: marten => marten.ApplyAllDatabaseChangesOnStartup()); var primaryStore = (DocumentStore)host.Services.GetRequiredService(); var ancillaryStore = (DocumentStore)host.Services.GetRequiredService(); @@ -86,25 +78,15 @@ public async Task ancillary_store_types_should_not_appear_in_primary_store_schem [Fact] public async Task ancillary_store_ddl_should_not_contain_primary_store_types() { - using var host = await Host.CreateDefaultBuilder() - .ConfigureServices(services => + var host = await StartHostAsync( + opts => opts.RegisterDocumentType(), + configureServices: services => services.AddMartenStore(opts => { - services.AddMarten(opts => - { - opts.Connection(ConnectionSource.ConnectionString); - opts.DatabaseSchemaName = "primary_4187b"; - opts.RegisterDocumentType(); - }) - .ApplyAllDatabaseChangesOnStartup(); - - services.AddMartenStore(opts => - { - opts.Connection(ConnectionSource.ConnectionString); - opts.DatabaseSchemaName = "ancillary_4187b"; - opts.RegisterDocumentType(); - }); - }) - .StartAsync(); + opts.Connection(ConnectionSource.ConnectionString); + opts.DatabaseSchemaName = $"{SchemaName}_ancillary_b"; + opts.RegisterDocumentType(); + }), + configureMarten: marten => marten.ApplyAllDatabaseChangesOnStartup()); var primaryStore = (DocumentStore)host.Services.GetRequiredService(); var ancillaryStore = (DocumentStore)host.Services.GetRequiredService(); diff --git a/src/CoreTests/Bugs/Bug_5039_generic_secondary_store_marker.cs b/src/CoreTests/Bugs/Bug_5039_generic_secondary_store_marker.cs index e5d44d59b9..5915cc5b14 100644 --- a/src/CoreTests/Bugs/Bug_5039_generic_secondary_store_marker.cs +++ b/src/CoreTests/Bugs/Bug_5039_generic_secondary_store_marker.cs @@ -16,7 +16,7 @@ namespace CoreTests.Bugs; /// contains a backtick + arity (e.g. IMartenStoreMarker`1), which is not a valid URI /// hostname when composing the marten:// subject in SecondaryStoreConfig.Build. /// -public class Bug_5039_generic_secondary_store_marker +public class Bug_5039_generic_secondary_store_marker: HostedStoreContext { public sealed class MyContext; public sealed class OtherContext; @@ -44,23 +44,16 @@ public void sanitized_uri_strips_backtick_and_includes_generic_argument() [Fact] public async Task can_register_and_resolve_generic_marker_store() { - using var host = await Host.CreateDefaultBuilder() - .ConfigureServices(services => + var host = await StartHostAsync(_ => { }, + configureServices: services => { - services.AddMarten(opts => - { - opts.Connection(ConnectionSource.ConnectionString); - opts.DatabaseSchemaName = "bug5039_primary"; - }); - // This threw UriFormatException before the fix services.AddMartenStore>(opts => { opts.Connection(ConnectionSource.ConnectionString); - opts.DatabaseSchemaName = "bug5039_ancillary"; + opts.DatabaseSchemaName = $"{SchemaName}_ancillary"; }); - }) - .StartAsync(); + }); var store = host.Services.GetRequiredService>(); store.ShouldNotBeNull(); diff --git a/src/CoreTests/CoreTests.csproj b/src/CoreTests/CoreTests.csproj index a29cbcd5c5..1920615c9f 100644 --- a/src/CoreTests/CoreTests.csproj +++ b/src/CoreTests/CoreTests.csproj @@ -91,6 +91,9 @@ Harness\DestructiveIntegrationContext.cs + + Harness\HostedStoreContext.cs + Harness\IntegrationContext.cs diff --git a/src/CoreTests/Internal/Sessions/EventTracingConnectionLifetimeTests.cs b/src/CoreTests/Internal/Sessions/EventTracingConnectionLifetimeTests.cs index fb194f866a..cc1f04117d 100644 --- a/src/CoreTests/Internal/Sessions/EventTracingConnectionLifetimeTests.cs +++ b/src/CoreTests/Internal/Sessions/EventTracingConnectionLifetimeTests.cs @@ -679,7 +679,7 @@ public async Task query_session_with_EventTracingConnectionLifetime_uses_storeOp { var logger = new BatchSuccessRecordingLogger(); - var store = DocumentStore.For(options => + await using var store = DocumentStore.For(options => { options.Connection(ConnectionSource.ConnectionString); options.OpenTelemetry.TrackConnections = TrackLevel.Normal; diff --git a/src/CoreTests/SessionOptionsTests.cs b/src/CoreTests/SessionOptionsTests.cs index da195b5923..7d5c29ed9a 100644 --- a/src/CoreTests/SessionOptionsTests.cs +++ b/src/CoreTests/SessionOptionsTests.cs @@ -185,14 +185,11 @@ public async Task can_define_custom_timeout_via_pgcstring() connectionStringBuilder.CommandTimeout = 1; - var documentStore = DocumentStore.For(c => + var documentStore = SeparateStore(c => { + // Caller-supplied connection string; the base supplies this class's own + // schema so the write/read-back doesn't race schema-wiping tests. c.Connection(connectionStringBuilder.ToString()); - - // Own schema: this test writes then reads back through a caller-supplied - // connection, and on the shared public schema it races any test that wipes - // the schema in between. - c.DatabaseSchemaName = "session_options_custom_connection"; }); using var query = documentStore.LightweightSession(); @@ -208,14 +205,11 @@ public async Task can_override_pgcstring_timeout_in_sessionoptions() connectionStringBuilder.CommandTimeout = 1; - var documentStore = DocumentStore.For(c => + var documentStore = SeparateStore(c => { + // Caller-supplied connection string; the base supplies this class's own + // schema so the write/read-back doesn't race schema-wiping tests. c.Connection(connectionStringBuilder.ToString()); - - // Own schema: this test writes then reads back through a caller-supplied - // connection, and on the shared public schema it races any test that wipes - // the schema in between. - c.DatabaseSchemaName = "session_options_custom_connection"; }); var options = new SessionOptions { Timeout = 60 }; @@ -231,14 +225,11 @@ public async Task session_with_custom_connection_reusable_after_saveChanges() { var connectionStringBuilder = new NpgsqlConnectionStringBuilder(ConnectionSource.ConnectionString); - var documentStore = DocumentStore.For(c => + var documentStore = SeparateStore(c => { + // Caller-supplied connection string; the base supplies this class's own + // schema so the write/read-back doesn't race schema-wiping tests. c.Connection(connectionStringBuilder.ToString()); - - // Own schema: this test writes then reads back through a caller-supplied - // connection, and on the shared public schema it races any test that wipes - // the schema in between. - c.DatabaseSchemaName = "session_options_custom_connection"; }); var connection = new NpgsqlConnection(connectionStringBuilder.ToString()); @@ -259,14 +250,11 @@ public async Task session_with_custom_connection_reusable_after_saveChangesAsync { var connectionStringBuilder = new NpgsqlConnectionStringBuilder(ConnectionSource.ConnectionString); - var documentStore = DocumentStore.For(c => + var documentStore = SeparateStore(c => { + // Caller-supplied connection string; the base supplies this class's own + // schema so the write/read-back doesn't race schema-wiping tests. c.Connection(connectionStringBuilder.ToString()); - - // Own schema: this test writes then reads back through a caller-supplied - // connection, and on the shared public schema it races any test that wipes - // the schema in between. - c.DatabaseSchemaName = "session_options_custom_connection"; }); var connection = new NpgsqlConnection(connectionStringBuilder.ToString()); diff --git a/src/CoreTests/configuring_marten_with_async_extensions.cs b/src/CoreTests/configuring_marten_with_async_extensions.cs index c0d1da5454..ec97b8c0f1 100644 --- a/src/CoreTests/configuring_marten_with_async_extensions.cs +++ b/src/CoreTests/configuring_marten_with_async_extensions.cs @@ -14,7 +14,7 @@ namespace CoreTests; -public class configuring_marten_with_async_extensions +public class configuring_marten_with_async_extensions: HostedStoreContext { [Fact] public async Task feature_flag_positive() @@ -22,30 +22,26 @@ public async Task feature_flag_positive() var featureManager = Substitute.For(); featureManager.IsEnabledAsync("Module1").Returns(true); - using var host = await Host.CreateDefaultBuilder() - .ConfigureServices(services => + var host = await StartHostAsync(opts => + { + // #4552: ApplyAllDatabaseChangesOnStartup takes the global advisory lock + // (default id 4004) to apply schema changes. That id is shared by every + // store in the suite, and advisory locks are connection-scoped, so a pooled + // connection from another test's startup-apply can still hold 4004 and make + // this acquisition time out under CI load ("Unable to attain a global lock in + // time"). Use a distinct lock id so this test can't contend with the default. + opts.ApplyChangesLockId = opts.ApplyChangesLockId + 4552; + }, + configureServices: services => { - services.AddMarten(opts => - { - opts.Connection(ConnectionSource.ConnectionString); - opts.DatabaseSchemaName = "async_config"; - - // #4552: ApplyAllDatabaseChangesOnStartup takes the global advisory lock - // (default id 4004) to apply schema changes. That id is shared by every - // store in the suite, and advisory locks are connection-scoped, so a pooled - // connection from another test's startup-apply can still hold 4004 and make - // this acquisition time out under CI load ("Unable to attain a global lock in - // time"). Use a distinct lock id so this test can't contend with the default. - opts.ApplyChangesLockId = opts.ApplyChangesLockId + 4552; - }).ApplyAllDatabaseChangesOnStartup(); - #region sample_registering_async_config_marten services.ConfigureMartenWithServices(); #endregion services.AddSingleton(featureManager); - }).StartAsync(); + }, + configureMarten: marten => marten.ApplyAllDatabaseChangesOnStartup()); var store = (DocumentStore)host.Services.GetRequiredService(); @@ -61,18 +57,12 @@ public async Task feature_flag_negative() featureManager.IsEnabledAsync("Module1").Returns(false); - using var host = await Host.CreateDefaultBuilder() - .ConfigureServices(services => + var host = await StartHostAsync(_ => { }, + configureServices: services => { - services.AddMarten(opts => - { - opts.Connection(ConnectionSource.ConnectionString); - opts.DatabaseSchemaName = "async_config"; - }); - services.ConfigureMartenWithServices(); services.AddSingleton(featureManager); - }).StartAsync(); + }); var store = (DocumentStore)host.Services.GetRequiredService(); @@ -88,17 +78,10 @@ public async Task bare_AddSingleton_IAsyncConfigureMarten_is_invoked() // registered the impl but never wired AsyncConfigureMartenApplication, so // Configure() silently never ran. AddMarten now registers the hosted service // unconditionally, matching how bare AddSingleton() works. - using var host = await Host.CreateDefaultBuilder() - .ConfigureServices(services => - { - services.AddMarten(opts => - { - opts.Connection(ConnectionSource.ConnectionString); - opts.DatabaseSchemaName = "async_config_bare"; - }); - - services.AddSingleton(); - }).StartAsync(); + var host = await StartHostAsync( + opts => opts.DatabaseSchemaName = $"{SchemaName}_bare", + configureServices: services => + services.AddSingleton()); var recorded = host.Services.GetServices() .OfType() diff --git a/src/CoreTests/document_store_diagnostics_tests.cs b/src/CoreTests/document_store_diagnostics_tests.cs index a209bc4d80..987aab43ad 100644 --- a/src/CoreTests/document_store_diagnostics_tests.cs +++ b/src/CoreTests/document_store_diagnostics_tests.cs @@ -39,12 +39,12 @@ public class DiagCat: DiagAnimal { } /// enrichment (SubClasses + structured Partitioning) that /// feeds the CritterWatch Document Database Explorer. /// -public class document_store_diagnostics_tests +public class document_store_diagnostics_tests: HostedStoreContext { [Fact] public async Task diagnostics_is_registered_in_the_container() { - using var host = await BuildHost("doc_diag_di", opts => opts.Schema.For()); + var host = await BuildHost("di", opts => opts.Schema.For()); host.Services.GetService().ShouldNotBeNull(); } @@ -52,7 +52,7 @@ public async Task diagnostics_is_registered_in_the_container() [Fact] public async Task document_types_lists_registered_mappings() { - using var host = await BuildHost("doc_diag_types", opts => + var host = await BuildHost("types", opts => { opts.Schema.For(); opts.Schema.For(); @@ -63,7 +63,7 @@ public async Task document_types_lists_registered_mappings() var widget = types.Single(t => t.Alias == "diagwidget"); widget.TypeName.ShouldContain(nameof(DiagWidget)); - widget.SchemaName.ShouldBe("doc_diag_types"); + widget.SchemaName.ShouldBe($"{SchemaName}_types"); types.Select(t => t.Alias).ShouldContain("user"); } @@ -71,7 +71,7 @@ public async Task document_types_lists_registered_mappings() [Fact] public async Task query_documents_pages_and_reports_the_total() { - using var host = await BuildHost("doc_diag_paging", opts => opts.Schema.For()); + var host = await BuildHost("paging", opts => opts.Schema.For()); var store = host.Services.GetRequiredService(); await using (var session = store.LightweightSession()) @@ -111,7 +111,7 @@ public async Task query_documents_pages_and_reports_the_total() [Fact] public async Task query_documents_can_filter_by_id() { - using var host = await BuildHost("doc_diag_byid", opts => opts.Schema.For()); + var host = await BuildHost("byid", opts => opts.Schema.For()); var target = new DiagWidget { Id = Guid.NewGuid(), Name = "the-one" }; var store = host.Services.GetRequiredService(); @@ -134,7 +134,7 @@ public async Task query_documents_can_filter_by_id() [Fact] public async Task query_documents_for_an_unknown_type_returns_an_empty_page() { - using var host = await BuildHost("doc_diag_unknown", opts => opts.Schema.For()); + var host = await BuildHost("unknown", opts => opts.Schema.For()); var diagnostics = host.Services.GetRequiredService(); @@ -148,7 +148,7 @@ public async Task query_documents_for_an_unknown_type_returns_an_empty_page() [Fact] public async Task load_document_json_returns_the_document_or_null() { - using var host = await BuildHost("doc_diag_load", opts => opts.Schema.For()); + var host = await BuildHost("load", opts => opts.Schema.For()); var target = new DiagWidget { Id = Guid.NewGuid(), Name = "loadable" }; var store = host.Services.GetRequiredService(); @@ -172,7 +172,7 @@ public async Task load_document_json_returns_the_document_or_null() [Fact] public async Task mapping_descriptor_carries_subclasses_for_a_hierarchy() { - using var host = await BuildHost("doc_diag_subclasses", opts => + var host = await BuildHost("subclasses", opts => opts.Schema.For() .AddSubClass() .AddSubClass()); @@ -189,7 +189,7 @@ public async Task mapping_descriptor_carries_subclasses_for_a_hierarchy() [Fact] public async Task mapping_descriptor_carries_structured_partitioning() { - using var host = await BuildHost("doc_diag_partitioning", opts => + var host = await BuildHost("partitioning", opts => opts.Schema.For().PartitionOn(x => x.Number, x => { x.ByRange() @@ -210,7 +210,7 @@ public async Task mapping_descriptor_carries_structured_partitioning() [Fact] public async Task mapping_descriptor_has_no_partitioning_when_not_partitioned() { - using var host = await BuildHost("doc_diag_no_partitioning", opts => opts.Schema.For()); + var host = await BuildHost("no_partitioning", opts => opts.Schema.For()); var usage = await GetUsageAsync(host); var descriptor = usage.Documents.Single(d => d.Alias == "diagwidget"); @@ -219,27 +219,22 @@ public async Task mapping_descriptor_has_no_partitioning_when_not_partitioned() descriptor.Partitioning.ShouldBeNull(); } - private static async Task BuildHost(string schema, Action configure) + private async Task BuildHost(string suffix, Action configure) { // Start from a clean schema so the data-bearing tests get a deterministic row count // regardless of prior runs against the same database (e.g. the net9 + net10 matrix). + var schema = $"{SchemaName}_{suffix}"; await using (var conn = new NpgsqlConnection(ConnectionSource.ConnectionString)) { await conn.OpenAsync(); await conn.DropSchemaAsync(schema); } - return await Host.CreateDefaultBuilder() - .ConfigureServices(services => - { - services.AddMarten(opts => - { - opts.Connection(ConnectionSource.ConnectionString); - opts.DatabaseSchemaName = schema; - configure(opts); - }); - }) - .StartAsync(); + return await StartHostAsync(opts => + { + opts.DatabaseSchemaName = schema; + configure(opts); + }); } private static async Task GetUsageAsync(IHost host) diff --git a/src/CoreTests/document_store_usage_tests.cs b/src/CoreTests/document_store_usage_tests.cs index 716e9c25ba..96616adbad 100644 --- a/src/CoreTests/document_store_usage_tests.cs +++ b/src/CoreTests/document_store_usage_tests.cs @@ -23,15 +23,14 @@ namespace CoreTests; /// CritterWatch Documents tab end-to-end so the operationally-interesting /// settings reach the monitoring console accurately. /// -public class document_store_usage_tests +public class document_store_usage_tests: HostedStoreContext { [Fact] public async Task usage_carries_first_class_identity_properties() { - using var host = await BuildHost(opts => + var host = await BuildHost(opts => { - opts.Connection(ConnectionSource.ConnectionString); - opts.DatabaseSchemaName = "doc_usage_identity"; + opts.DatabaseSchemaName = $"{SchemaName}_identity"; opts.AutoCreateSchemaObjects = AutoCreate.None; opts.Schema.For(); }); @@ -41,7 +40,7 @@ public async Task usage_carries_first_class_identity_properties() usage.ShouldNotBeNull(); usage.SubjectUri.ShouldBe(new Uri("marten://main")); usage.StoreName.ShouldBe("Main"); - usage.DatabaseSchemaName.ShouldBe("doc_usage_identity"); + usage.DatabaseSchemaName.ShouldBe($"{SchemaName}_identity"); usage.AutoCreateSchemaObjects.ShouldBe(AutoCreate.None.ToString()); usage.EnumStorage.ShouldNotBeNullOrEmpty(); usage.Version.ShouldNotBeNullOrEmpty(); @@ -51,10 +50,9 @@ public async Task usage_carries_first_class_identity_properties() [Fact] public async Task usage_includes_a_descriptor_per_registered_document_mapping() { - using var host = await BuildHost(opts => + var host = await BuildHost(opts => { - opts.Connection(ConnectionSource.ConnectionString); - opts.DatabaseSchemaName = "doc_usage_mappings"; + opts.DatabaseSchemaName = $"{SchemaName}_mappings"; opts.Schema.For(); opts.Schema.For(); opts.Schema.For(); @@ -70,7 +68,7 @@ public async Task usage_includes_a_descriptor_per_registered_document_mapping() var userMapping = usage.Documents.Single(d => d.Alias == "user"); userMapping.DocumentType.FullName.ShouldBe(typeof(User).FullName); userMapping.DocumentType.Name.ShouldBe(nameof(User)); - userMapping.DatabaseSchemaName.ShouldBe("doc_usage_mappings"); + userMapping.DatabaseSchemaName.ShouldBe($"{SchemaName}_mappings"); userMapping.IdStrategy.ShouldNotBeNullOrEmpty(); userMapping.TenancyStyle.ShouldBe("Single"); userMapping.DeleteStyle.ShouldBe("Remove"); @@ -79,10 +77,9 @@ public async Task usage_includes_a_descriptor_per_registered_document_mapping() [Fact] public async Task mapping_descriptor_carries_concurrency_and_tenancy_overrides() { - using var host = await BuildHost(opts => + var host = await BuildHost(opts => { - opts.Connection(ConnectionSource.ConnectionString); - opts.DatabaseSchemaName = "doc_usage_overrides"; + opts.DatabaseSchemaName = $"{SchemaName}_overrides"; opts.Schema.For().UseOptimisticConcurrency(true); opts.Schema.For().MultiTenanted(); opts.Schema.For().SoftDeleted(); @@ -98,10 +95,9 @@ public async Task mapping_descriptor_carries_concurrency_and_tenancy_overrides() [Fact] public async Task mapping_descriptor_carries_full_create_table_ddl() { - using var host = await BuildHost(opts => + var host = await BuildHost(opts => { - opts.Connection(ConnectionSource.ConnectionString); - opts.DatabaseSchemaName = "doc_usage_ddl"; + opts.DatabaseSchemaName = $"{SchemaName}_ddl"; opts.Schema.For(); }); @@ -114,16 +110,15 @@ public async Task mapping_descriptor_carries_full_create_table_ddl() // statement for this mapping at minimum. mapping.Ddl.ShouldNotBeNullOrEmpty(); mapping.Ddl.ShouldContain("CREATE", Case.Insensitive); - mapping.Ddl.ShouldContain("doc_usage_ddl.mt_doc_user", Case.Insensitive); + mapping.Ddl.ShouldContain($"{SchemaName}_ddl.mt_doc_user", Case.Insensitive); } [Fact] public async Task usage_carries_flat_option_values_for_secondary_settings() { - using var host = await BuildHost(opts => + var host = await BuildHost(opts => { - opts.Connection(ConnectionSource.ConnectionString); - opts.DatabaseSchemaName = "doc_usage_flat"; + opts.DatabaseSchemaName = $"{SchemaName}_flat"; opts.CommandTimeout = 42; opts.UpdateBatchSize = 250; opts.Schema.For(); @@ -149,10 +144,9 @@ public async Task usage_carries_flat_option_values_for_secondary_settings() [Fact] public async Task event_store_usage_includes_global_aggregates_when_present() { - using var host = await BuildHost(opts => + var host = await BuildHost(opts => { - opts.Connection(ConnectionSource.ConnectionString); - opts.DatabaseSchemaName = "doc_usage_global_aggs"; + opts.DatabaseSchemaName = $"{SchemaName}_global_aggs"; // GlobalAggregates lives on the internal EventGraph implementation // (not on the public IEventStoreOptions surface). CoreTests has // InternalsVisibleTo, so the cast is fine here. @@ -166,14 +160,9 @@ public async Task event_store_usage_includes_global_aggregates_when_present() usage.GlobalAggregates.ShouldContain(g => g.FullName == typeof(User).FullName); } - private static async Task BuildHost(Action configure) + private Task BuildHost(Action configure) { - return await Host.CreateDefaultBuilder() - .ConfigureServices(services => - { - services.AddMarten(configure); - }) - .StartAsync(); + return StartHostAsync(configure); } private static async Task GetUsageAsync(IHost host) diff --git a/src/CoreTests/lazy_ancillary_store_registration.cs b/src/CoreTests/lazy_ancillary_store_registration.cs index 8e5ddc5b0a..a1c11fa109 100644 --- a/src/CoreTests/lazy_ancillary_store_registration.cs +++ b/src/CoreTests/lazy_ancillary_store_registration.cs @@ -11,27 +11,17 @@ namespace CoreTests; public interface ILazyTestStore : IDocumentStore; -public class lazy_ancillary_store_registration +public class lazy_ancillary_store_registration: HostedStoreContext { [Fact] public async Task lazy_of_ancillary_store_is_registered_as_singleton() { - using var host = await Host.CreateDefaultBuilder() - .ConfigureServices(services => + var host = await StartHostAsync(_ => { }, + configureServices: services => services.AddMartenStore(opts => { - services.AddMarten(opts => - { - opts.Connection(ConnectionSource.ConnectionString); - opts.DatabaseSchemaName = "lazy_test_primary"; - }); - - services.AddMartenStore(opts => - { - opts.Connection(ConnectionSource.ConnectionString); - opts.DatabaseSchemaName = "lazy_test_ancillary"; - }); - }) - .StartAsync(); + opts.Connection(ConnectionSource.ConnectionString); + opts.DatabaseSchemaName = $"{SchemaName}_ancillary"; + })); // Lazy should be resolvable var lazy = host.Services.GetService>(); @@ -50,24 +40,17 @@ public async Task lazy_of_ancillary_store_is_registered_as_singleton() [Fact] public async Task lazy_of_ancillary_store_can_be_injected_into_a_service() { - using var host = await Host.CreateDefaultBuilder() - .ConfigureServices(services => + var host = await StartHostAsync(_ => { }, + configureServices: services => { - services.AddMarten(opts => - { - opts.Connection(ConnectionSource.ConnectionString); - opts.DatabaseSchemaName = "lazy_test2_primary"; - }); - services.AddMartenStore(opts => { opts.Connection(ConnectionSource.ConnectionString); - opts.DatabaseSchemaName = "lazy_test2_ancillary"; + opts.DatabaseSchemaName = $"{SchemaName}_ancillary2"; }); services.AddSingleton(); - }) - .StartAsync(); + }); var service = host.Services.GetRequiredService(); service.ShouldNotBeNull(); diff --git a/src/CoreTests/migrate_from_guid_to_int_based_revisions.cs b/src/CoreTests/migrate_from_guid_to_int_based_revisions.cs index 3050b249c2..3f9c6698ba 100644 --- a/src/CoreTests/migrate_from_guid_to_int_based_revisions.cs +++ b/src/CoreTests/migrate_from_guid_to_int_based_revisions.cs @@ -6,30 +6,21 @@ namespace CoreTests; -public class migrate_from_guid_to_int_based_revisions +public class migrate_from_guid_to_int_based_revisions: OneOffConfigurationsContext { [Fact] public async Task automatic_conversion_of_guid_version_to_integer() { - using var store1 = DocumentStore.For(opts => + var store1 = StoreOptions(opts => { - opts.Connection(ConnectionSource.ConnectionString); - opts.DatabaseSchemaName = "migrations"; - opts.Schema.For().UseOptimisticConcurrency(true); }); - await store1.Advanced.Clean.CompletelyRemoveAllAsync(); - await store1.Storage.ApplyAllConfiguredChangesToDatabaseAsync(); - using var store2 = DocumentStore.For(opts => + var store2 = SeparateStore(opts => { - opts.Connection(ConnectionSource.ConnectionString); - opts.DatabaseSchemaName = "migrations"; - opts.Schema.For().UseNumericRevisions(true); - }); await store2.Storage.ApplyAllConfiguredChangesToDatabaseAsync(); diff --git a/src/CoreTests/request_count_tracking.cs b/src/CoreTests/request_count_tracking.cs index e6eac23a8b..1877564584 100644 --- a/src/CoreTests/request_count_tracking.cs +++ b/src/CoreTests/request_count_tracking.cs @@ -10,30 +10,15 @@ namespace CoreTests; -public class request_count_tracking : IDisposable +public class request_count_tracking : OneOffConfigurationsContext { private readonly RecordingLogger logger = new(); - private readonly DocumentStore _store; - private readonly IDocumentSession theSession; public request_count_tracking() { - _store = DocumentStore.For(opts => - { - opts.Connection(ConnectionSource.ConnectionString); - opts.DatabaseSchemaName = "request_counts"; - }); - - theSession = _store.LightweightSession(); theSession.Logger = logger; } - public void Dispose() - { - _store?.Dispose(); - theSession?.Dispose(); - } - [Fact] public async Task log_execute_failure_1_async() { diff --git a/src/CoreTests/setting_solo_mode_in_test_support.cs b/src/CoreTests/setting_solo_mode_in_test_support.cs index 5fa63a42df..77175426a3 100644 --- a/src/CoreTests/setting_solo_mode_in_test_support.cs +++ b/src/CoreTests/setting_solo_mode_in_test_support.cs @@ -11,35 +11,33 @@ namespace CoreTests; -public class setting_solo_mode_in_test_support +public class setting_solo_mode_in_test_support: HostedStoreContext { [Fact] public async Task override_every_store_to_use_a_solo_async_daemon() { - using var host = await Host.CreateDefaultBuilder() - .ConfigureServices(services => + // Mostly just to prove we can mix and match daemon registrations + var host = await StartHostAsync(_ => { }, DaemonMode.HotCold, + configureServices: services => { - // Mostly just to prove we can mix and match - services.AddMarten(ConnectionSource.ConnectionString).AddAsyncDaemon(DaemonMode.HotCold); - services.AddMartenStore(opts => { opts.Connection(ConnectionSource.ConnectionString); - opts.DatabaseSchemaName = "first_store"; + opts.DatabaseSchemaName = $"{SchemaName}_first"; }).AddAsyncDaemon(DaemonMode.HotCold); - services.AddMartenStore(services => + services.AddMartenStore(s => { var opts = new StoreOptions(); opts.Connection(ConnectionSource.ConnectionString); - opts.DatabaseSchemaName = "second_store"; + opts.DatabaseSchemaName = $"{SchemaName}_second"; return opts; }).AddAsyncDaemon(DaemonMode.HotCold); // Forget what the application says, let's make all the daemons run in solo mode! services.MartenDaemonModeIsSolo(); - }).StartAsync(); + }); // 9.0: JFx.Events 2.0 introduced its own IProjectionCoordinator(); qualify // with the full Marten namespace path to disambiguate the resolution this test diff --git a/src/CoreTests/working_with_initial_data.cs b/src/CoreTests/working_with_initial_data.cs index f885433a6c..a8ec1befc4 100644 --- a/src/CoreTests/working_with_initial_data.cs +++ b/src/CoreTests/working_with_initial_data.cs @@ -16,19 +16,6 @@ namespace CoreTests; -public class MartenHost -{ - public static Task For(Action configure) - { - return Host.CreateDefaultBuilder() - .ConfigureServices((c, services) => - { - configure(services); - }) - .StartAsync(); - } -} - public class StubInitialData: IInitialData { public Task Populate(IDocumentStore store, CancellationToken cancellation) @@ -40,7 +27,7 @@ public Task Populate(IDocumentStore store, CancellationToken cancellation) public IDocumentStore ReceivedStore { get; set; } } -public class working_with_initial_data : OneOffConfigurationsContext +public class working_with_initial_data : HostedStoreContext { [Fact] public async Task runs_all_the_initial_data_sets_on_startup() @@ -49,15 +36,8 @@ public async Task runs_all_the_initial_data_sets_on_startup() var data2 = Substitute.For(); var data3 = Substitute.For(); - using var host = await MartenHost.For(services => - { - services.AddMarten(opts => - { - opts.Connection(ConnectionSource.ConnectionString); - - }) - .InitializeWith(data1, data2, data3); - }); + var host = await StartHostAsync(_ => { }, + configureMarten: marten => marten.InitializeWith(data1, data2, data3)); var store = host.Services.GetRequiredService().As(); store.Options.InitialData.ShouldBe([data1, data2, data3]); @@ -74,17 +54,8 @@ public async Task runs_all_the_initial_data_sets_on_startup_2() var data2 = Substitute.For(); var data3 = Substitute.For(); - using var host = await MartenHost.For(services => - { - services.AddMarten(opts => - { - opts.Connection(ConnectionSource.ConnectionString); - - }); - - services.InitializeMartenWith(data1, data2, data3); - - }); + var host = await StartHostAsync(_ => { }, + configureServices: services => services.InitializeMartenWith(data1, data2, data3)); var store = host.Services.GetRequiredService().As(); store.Options.InitialData.ShouldBe([data1, data2, data3]); @@ -97,15 +68,8 @@ public async Task runs_all_the_initial_data_sets_on_startup_2() [Fact] public async Task use_service_registration_for_initial_data() { - using var host = await MartenHost.For(services => - { - services.AddMarten(opts => - { - opts.Connection(ConnectionSource.ConnectionString); - - }) - .InitializeWith(); - }); + var host = await StartHostAsync(_ => { }, + configureMarten: marten => marten.InitializeWith()); var stub = host.Services.GetServices().OfType().Single(); var store = host.Services.GetRequiredService().As(); @@ -117,17 +81,8 @@ public async Task use_service_registration_for_initial_data() [Fact] public async Task use_service_registration_for_initial_data_separate_registration() { - using var host = await MartenHost.For(services => - { - services.AddMarten(opts => - { - opts.Connection(ConnectionSource.ConnectionString); - - }); - - services.InitializeMartenWith(); - - }); + var host = await StartHostAsync(_ => { }, + configureServices: services => services.InitializeMartenWith()); var stub = host.Services.GetServices().OfType().Single(); var store = host.Services.GetRequiredService().As(); @@ -144,15 +99,13 @@ public async Task runs_all_the_initial_data_sets_on_startup_on_other_store() var data2 = Substitute.For(); var data3 = Substitute.For(); - using var host = await MartenHost.For(services => - { - services.AddMartenStore(opts => + var host = await StartHostAsync(_ => { }, + configureServices: services => services.AddMartenStore(opts => { opts.Connection(ConnectionSource.ConnectionString); - + opts.DatabaseSchemaName = $"{SchemaName}_other"; }) - .InitializeWith(data1, data2, data3); - }); + .InitializeWith(data1, data2, data3)); var store = host.Services.GetRequiredService().As(); store.Options.InitialData.ShouldBe([data1, data2, data3]); @@ -169,17 +122,18 @@ public async Task runs_all_the_initial_data_sets_on_startup_on_other_store_separ var data2 = Substitute.For(); var data3 = Substitute.For(); - using var host = await MartenHost.For(services => - { - services.AddMartenStore(opts => + var host = await StartHostAsync(_ => { }, + configureServices: services => { - opts.Connection(ConnectionSource.ConnectionString); + services.AddMartenStore(opts => + { + opts.Connection(ConnectionSource.ConnectionString); + opts.DatabaseSchemaName = $"{SchemaName}_other"; + }); + services.InitializeMartenWith(data1, data2, data3); }); - services.InitializeMartenWith(data1, data2, data3); - }); - var store = host.Services.GetRequiredService().As(); store.Options.InitialData.ShouldBe([data1, data2, data3]); @@ -191,15 +145,13 @@ public async Task runs_all_the_initial_data_sets_on_startup_on_other_store_separ [Fact] public async Task use_service_registration_for_initial_data_for_other_store() { - using var host = await MartenHost.For(services => - { - services.AddMartenStore(opts => + var host = await StartHostAsync(_ => { }, + configureServices: services => services.AddMartenStore(opts => { opts.Connection(ConnectionSource.ConnectionString); - + opts.DatabaseSchemaName = $"{SchemaName}_other"; }) - .InitializeWith(); - }); + .InitializeWith()); var store = host.Services.GetRequiredService().As(); var stub = store.Options.InitialData.OfType().Single(); @@ -210,18 +162,18 @@ public async Task use_service_registration_for_initial_data_for_other_store() [Fact] public async Task use_service_registration_for_initial_data_for_other_store_separate_call() { - using var host = await MartenHost.For(services => - { - services.AddMartenStore(opts => + var host = await StartHostAsync(_ => { }, + configureServices: services => { - opts.Connection(ConnectionSource.ConnectionString); + services.AddMartenStore(opts => + { + opts.Connection(ConnectionSource.ConnectionString); + opts.DatabaseSchemaName = $"{SchemaName}_other"; + }); + services.InitializeMartenWith(); }); - services - .InitializeMartenWith(); - }); - var store = host.Services.GetRequiredService().As(); var stub = store.Options.InitialData.OfType().Single(); stub.ReceivedStore.ShouldBe(store); @@ -231,17 +183,18 @@ public async Task use_service_registration_for_initial_data_for_other_store_sepa [Fact] public async Task use_service_registration_for_initial_data_for_other_store_2() { - using var host = await MartenHost.For(services => - { - services.AddMartenStore(opts => + var host = await StartHostAsync(_ => { }, + configureServices: services => { - opts.Connection(ConnectionSource.ConnectionString); + services.AddMartenStore(opts => + { + opts.Connection(ConnectionSource.ConnectionString); + opts.DatabaseSchemaName = $"{SchemaName}_other"; + }); + services.InitializeMartenWith(); }); - services.InitializeMartenWith(); - }); - var store = host.Services.GetRequiredService().As(); var stub = store.Options.InitialData.OfType().Single(); stub.ReceivedStore.ShouldBe(store); @@ -252,9 +205,9 @@ public async Task use_service_registration_for_initial_data_for_other_store_2() [Fact] public async Task initial_data_should_populate_db_with_query_in_populate_method() { - var store = DocumentStore.For(_ => + await using var store = DocumentStore.For(_ => { - _.DatabaseSchemaName = "Bug1495"; + _.DatabaseSchemaName = $"{SchemaName}_bug1495"; _.Connection(ConnectionSource.ConnectionString); @@ -271,8 +224,6 @@ public async Task initial_data_should_populate_db_with_query_in_populate_method( aggregate.Name.ShouldBe(initialAggregate.Name); } } - - store.Dispose(); } } public class InitialDataWithQuery: IInitialData