From 8d8f07f74a374d9126d779a92e01ff59cbc206a8 Mon Sep 17 00:00:00 2001 From: William Chong Date: Mon, 6 Jan 2025 16:03:29 +0400 Subject: [PATCH] Tests --- .github/workflows/base.yml | 9 +- .github/workflows/dispatch-ce.yml | 8 +- .github/workflows/dispatch-ee.yml | 58 +- .github/workflows/publish.yml | 386 ++++---- .github/workflows/pull-request-check.yml | 46 +- Directory.Build.props | 4 +- EventStore.Client.sln | 54 +- src/Directory.Build.props | 4 +- .../Core/Certificates/X509Certificates.cs | 57 +- ...entStoreClientSettings.ConnectionString.cs | 42 +- test/Directory.Build.props | 3 +- .../AssemblyInfo.cs | 1 - .../EventStore.Client.Operations.Tests.csproj | 6 - .../ResignNodeTests.cs | 20 - .../RestartPersistentSubscriptionsTests.cs | 20 - .../ShutdownNodeAuthenticationTests.cs | 12 - .../ShutdownNodeTests.cs | 12 - .../AssemblyInfo.cs | 1 - .../Bugs/Issue_1125.cs | 84 -- ...ubscriptionsTracingInstrumentationTests.cs | 155 --- ...lient.PersistentSubscriptions.Tests.csproj | 9 - ...tentSubscriptions.Tests.csproj.DotSettings | 4 - .../EventStoreClientFixture.cs | 41 - .../PersistentSubscriptionSettingsTests.cs | 11 - ...o_existing_with_max_one_client_obsolete.cs | 43 - ...t_to_existing_with_permissions_obsolete.cs | 37 - ...ting_with_start_from_beginning_obsolete.cs | 66 -- ...isting_with_start_from_not_set_obsolete.cs | 64 -- ...rom_not_set_then_event_written_obsolete.cs | 72 -- ...start_from_set_to_end_position_obsolete.cs | 63 -- ...nd_position_then_event_written_obsolete.cs | 69 -- ...set_to_invalid_middle_position_obsolete.cs | 49 - ...m_set_to_valid_middle_position_obsolete.cs | 65 -- ...o_existing_without_permissions_obsolete.cs | 32 - ...g_without_read_all_permissions_obsolete.cs | 33 - ..._non_existing_with_permissions_obsolete.cs | 32 - .../Obsolete/connect_with_retries_obsolete.cs | 59 -- ...eting_existing_with_subscriber_obsolete.cs | 66 -- ...p_to_link_to_events_manual_ack_obsolete.cs | 78 -- ...up_to_normal_events_manual_ack_obsolete.cs | 65 -- .../Obsolete/happy_case_filtered_obsolete.cs | 72 -- ...e_filtered_with_start_from_set_obsolete.cs | 86 -- ...ng_to_normal_events_manual_ack_obsolete.cs | 65 -- ...ting_with_check_point_filtered_obsolete.cs | 120 --- ...date_existing_with_subscribers_obsolete.cs | 60 -- ...iting_and_filtering_out_events_obsolete.cs | 108 --- ...g_to_normal_events_manual_nack_obsolete.cs | 68 -- ...ate_duplicate_name_on_different_streams.cs | 22 - ...connect_to_existing_with_max_one_client.cs | 31 - .../connect_to_existing_with_permissions.cs | 23 - ...t_to_existing_with_start_from_beginning.cs | 52 - ...ect_to_existing_with_start_from_not_set.cs | 44 - ...h_start_from_not_set_then_event_written.cs | 54 -- ...ing_with_start_from_set_to_end_position.cs | 46 - ..._set_to_end_position_then_event_written.cs | 56 -- ...art_from_set_to_invalid_middle_position.cs | 48 - ...start_from_set_to_valid_middle_position.cs | 51 - ...connect_to_existing_without_permissions.cs | 23 - ...o_existing_without_read_all_permissions.cs | 25 - ...onnect_to_non_existing_with_permissions.cs | 24 - .../SubscriptionToAll/connect_with_retries.cs | 49 - .../create_after_deleting_the_same.cs | 32 - .../SubscriptionToAll/create_duplicate.cs | 33 - .../SubscriptionToAll/create_filtered.cs | 29 - .../SubscriptionToAll/create_on_all_stream.cs | 21 - ...rsistent_subscription_with_dont_timeout.cs | 21 - ...position_equal_to_last_indexed_position.cs | 32 - ...ition_larger_than_last_indexed_position.cs | 41 - ...re_position_larger_than_commit_position.cs | 24 - .../create_without_permissions.cs | 25 - .../deleting_existing_with_permissions.cs | 26 - .../deleting_existing_with_subscriber.cs | 23 - .../SubscriptionToAll/deleting_filtered.cs | 24 - .../SubscriptionToAll/deleting_nonexistent.cs | 19 - .../deleting_without_permissions.cs | 19 - .../SubscriptionToAll/get_info.cs | 181 ---- ...atching_up_to_link_to_events_manual_ack.cs | 57 -- ...catching_up_to_normal_events_manual_ack.cs | 51 - .../SubscriptionToAll/happy_case_filtered.cs | 54 -- ...happy_case_filtered_with_start_from_set.cs | 62 -- ...subscribing_to_normal_events_manual_ack.cs | 57 -- .../list_with_persistent_subscriptions.cs | 82 -- .../list_without_persistent_subscriptions.cs | 26 - .../SubscriptionToAll/replay_parked.cs | 90 -- .../SubscriptionToAll/update_existing.cs | 28 - .../update_existing_filtered.cs | 30 - .../update_existing_with_check_point.cs | 108 --- ...date_existing_with_check_point_filtered.cs | 111 --- ...position_equal_to_last_indexed_position.cs | 41 - ...ition_larger_than_last_indexed_position.cs | 49 - .../update_existing_with_subscribers.cs | 49 - .../update_existing_without_permissions.cs | 32 - .../SubscriptionToAll/update_non_existent.cs | 25 - ...re_position_larger_than_commit_position.cs | 26 - .../when_writing_and_filtering_out_events.cs | 87 -- ...ubscribing_to_normal_events_manual_nack.cs | 57 -- ...o_existing_with_max_one_client_obsolete.cs | 47 - ...t_to_existing_with_permissions_obsolete.cs | 39 - ...rom_beginning_and_events_in_it_obsolete.cs | 65 -- ...t_from_beginning_and_no_stream_obsolete.cs | 65 -- ..._from_not_set_and_events_in_it_obsolete.cs | 61 -- ...vents_in_it_then_event_written_obsolete.cs | 67 -- ..._end_position_and_events_in_it_obsolete.cs | 60 -- ...vents_in_it_then_event_written_obsolete.cs | 72 -- ...h_start_from_two_and_no_stream_obsolete.cs | 65 -- ...rt_from_x_set_and_events_in_it_obsolete.cs | 65 -- ...vents_in_it_then_event_written_obsolete.cs | 68 -- ...vents_in_it_then_event_written_obsolete.cs | 72 -- ...o_existing_without_permissions_obsolete.cs | 35 - ..._non_existing_with_permissions_obsolete.cs | 34 - .../Obsolete/connect_with_retries_obsolete.cs | 70 -- ...g_to_a_persistent_subscription_obsolete.cs | 72 -- ...eting_existing_with_subscriber_obsolete.cs | 67 -- .../Obsolete/get_info_obsolete.cs | 199 ---- ...p_to_link_to_events_manual_ack_obsolete.cs | 80 -- ...up_to_normal_events_manual_ack_obsolete.cs | 67 -- ...ng_to_normal_events_manual_ack_obsolete.cs | 67 -- ...date_existing_with_check_point_obsolete.cs | 124 --- ...date_existing_with_subscribers_obsolete.cs | 61 -- ...g_to_normal_events_manual_nack_obsolete.cs | 70 -- ...ate_duplicate_name_on_different_streams.cs | 32 - ...connect_to_existing_with_max_one_client.cs | 33 - .../connect_to_existing_with_permissions.cs | 26 - ...h_start_from_beginning_and_events_in_it.cs | 51 - ...with_start_from_beginning_and_no_stream.cs | 51 - ...ith_start_from_not_set_and_events_in_it.cs | 52 - ...set_and_events_in_it_then_event_written.cs | 58 -- ...om_set_to_end_position_and_events_in_it.cs | 53 - ...ion_and_events_in_it_then_event_written.cs | 57 -- ...sting_with_start_from_two_and_no_stream.cs | 55 -- ..._with_start_from_x_set_and_events_in_it.cs | 55 -- ...set_and_events_in_it_then_event_written.cs | 54 -- ...n_x_and_events_in_it_then_event_written.cs | 58 -- ...connect_to_existing_without_permissions.cs | 29 - ...onnect_to_non_existing_with_permissions.cs | 24 - .../connect_with_retries.cs | 60 -- ...connecting_to_a_persistent_subscription.cs | 47 - .../create_after_deleting_the_same.cs | 38 - .../SubscriptionToStream/create_duplicate.cs | 37 - .../create_on_existing_stream.cs | 24 - .../create_on_non_existing_stream.cs | 23 - ...rsistent_subscription_with_dont_timeout.cs | 23 - .../create_without_permissions.cs | 27 - .../deleting_existing_with_permissions.cs | 29 - .../deleting_existing_with_subscriber.cs | 26 - .../deleting_nonexistent.cs | 24 - .../deleting_without_permissions.cs | 25 - .../SubscriptionToStream/get_info.cs | 198 ---- ...atching_up_to_link_to_events_manual_ack.cs | 59 -- ...catching_up_to_normal_events_manual_ack.cs | 53 - ...subscribing_to_normal_events_manual_ack.cs | 52 - .../list_with_persistent_subscriptions.cs | 82 -- .../list_without_persistent_subscriptions.cs | 36 - .../SubscriptionToStream/replay_parked.cs | 80 -- .../SubscriptionToStream/update_existing.cs | 33 - .../update_existing_with_check_point.cs | 95 -- .../update_existing_with_subscribers.cs | 50 - .../update_existing_without_permissions.cs | 42 - .../update_non_existent.cs | 26 - ...ubscribing_to_normal_events_manual_nack.cs | 54 -- .../restart_subsystem.cs | 74 -- .../EventStore.Client.Plugins.Tests.csproj | 6 - .../AssemblyInfo.cs | 1 - ...e.Client.ProjectionManagement.Tests.csproj | 6 - .../EventStoreClientFixture.cs | 50 - .../StandardProjections.cs | 30 - .../abort.cs | 21 - .../create.cs | 35 - .../disable.cs | 21 - .../enable.cs | 22 - .../get_result.cs | 51 - .../get_state.cs | 51 - .../get_status.cs | 21 - .../list_all_projections.cs | 20 - .../list_continuous_projections.cs | 31 - .../list_one_time_projections.cs | 23 - .../reset.cs | 22 - .../restart_subsystem.cs | 20 - .../update.cs | 30 - .../Append/append_to_stream_limits.cs | 54 -- .../Append/append_to_stream_retry.cs | 37 - .../append_to_stream_with_tls_ca_file.cs | 35 - .../appending_to_implicitly_created_stream.cs | 266 ------ .../sending_and_receiving_large_messages.cs | 29 - .../AssemblyInfo.cs | 1 - .../DependencyInjectionTests.cs | 75 -- .../StreamsTracingInstrumentationTests.cs | 221 ----- .../EventDataTests.cs | 23 - .../EventStore.Client.Streams.Tests.csproj | 9 - ...re.Client.Streams.Tests.csproj.DotSettings | 12 - .../Obsolete/SecurityFixture_obsolete.cs | 321 ------- ...ll_stream_with_no_acl_security_obsolete.cs | 37 - ...system_stream_security_for_all_obsolete.cs | 70 -- ...erriden_system_stream_security_obsolete.cs | 87 -- ...overriden_user_stream_security_obsolete.cs | 78 -- .../subscribe_to_all_security_obsolete.cs | 22 - .../subscribe_to_stream_security_obsolete.cs | 75 -- .../system_stream_security_obsolete.cs | 146 --- .../Serialization/is_json.cs | 59 -- .../Obsolete/subscribe_to_all_obsolete.cs | 592 ------------ .../Obsolete/subscribe_to_stream_obsolete.cs | 303 ------ .../SubscriptionDroppedResult.cs | 16 - .../Subscriptions/SubscriptionsFixture.cs | 18 - .../Subscriptions/reconnection.cs | 178 ---- .../Subscriptions/subscribe_to_all.cs | 480 ---------- .../AssertEx.cs | 4 +- .../EventStore.Client.Tests.Common.csproj | 118 +-- .../Extensions/ConfigurationExtensions.cs | 2 +- .../Extensions/EventStoreClientExtensions.cs | 2 +- .../EventStoreClientWarmupExtensions.cs | 2 +- .../Extensions/OperatingSystemExtensions.cs | 2 +- .../Extensions/ReadOnlyMemoryExtensions.cs | 2 +- .../Extensions}/ShouldThrowAsyncExtensions.cs | 4 +- .../Extensions}/TypeExtensions.cs | 4 +- .../Extensions/WithExtension.cs | 2 +- .../Facts/AnonymousAccess.cs | 2 +- .../Facts/Deprecation.cs | 6 +- .../Facts/Regression.cs | 6 +- .../Facts/SupportsPSToAllFact.cs | 18 - .../Fakers/TestUserFaker.cs | 2 +- .../Base/EventStoreClientFixtureBase.cs | 147 --- .../Fixtures/Base/EventStoreTestServer.cs | 143 --- .../Base/EventStoreTestServerCluster.cs | 93 -- .../Base/EventStoreTestServerExternal.cs | 8 - .../Fixtures/Base/IEventStoreTestServer.cs | 6 - .../Fixtures/BaseTestNode.cs | 162 ++++ .../Fixtures/DiagnosticsFixture.cs | 107 --- .../Fixtures/EventStoreTestCluster.cs | 52 - .../Fixtures/InsecureClientTestFixture.cs | 7 - .../Fixtures/KurrentFixtureOptions.cs | 20 + ....cs => KurrentPermanentFixture.Helpers.cs} | 24 +- ...eFixture.cs => KurrentPermanentFixture.cs} | 90 +- ...estNode.cs => KurrentPermanentTestNode.cs} | 150 +-- .../KurrentTemporaryFixture.Helpers.cs | 107 +++ .../Fixtures/KurrentTemporaryFixture.cs | 189 ++++ .../Fixtures/KurrentTemporaryTestNode.cs | 193 ++++ .../Fixtures/RunInMemoryTestFixture.cs | 4 - .../Fixtures/RunProjectionsTestFixture.cs | 4 - .../FluentDockerBuilderExtensions.cs | 2 +- .../FluentDockerServiceExtensions.cs | 2 +- .../FluentDocker/TestCompositeService.cs | 2 +- .../FluentDocker/TestContainerService.cs | 2 +- .../GlobalEnvironment.cs | 34 +- .../EventStore.Client.Tests.Common/Logging.cs | 2 +- .../PasswordGenerator.cs | 2 +- .../Shouldly/ShouldThrowAsyncExtensions.cs | 2 +- .../TestCredentials.cs | 2 +- .../Assertions/ComparableAssertion.cs | 2 +- .../Assertions/EqualityAssertion.cs | 2 +- .../Assertions/NullArgumentAssertion.cs | 2 +- .../Assertions/StringConversionAssertion.cs | 2 +- .../Assertions/ValueObjectAssertion.cs | 2 +- .../AutoScenarioDataAttribute.cs | 2 +- .../ClientCertificatesTests.cs} | 27 +- .../ConnectionStringTests.cs | 24 +- ....cs => EventStoreClientOperationsTests.cs} | 6 +- test/EventStore.Client.Tests/FromAllTests.cs | 8 +- .../FromStreamTests.cs | 14 +- .../GossipChannelSelectorTests.cs | 6 +- .../GrpcServerCapabilitiesClientTests.cs | 2 +- .../ReportLeaderInterceptorTests.cs | 224 ----- .../ListProjectionTests.cs | 43 + .../NodePreferenceComparerTests.cs | 2 +- .../NodeSelectorTests.cs | 4 +- .../Operations}/AuthenticationTests.cs | 33 +- .../Operations/MergeIndexTests.cs} | 18 +- .../Operations/ResignNodeTests.cs | 21 + .../RestartPersistentSubscriptionsTests.cs | 20 + .../Operations}/ScavengeTests.cs | 29 +- .../ShutdownNodeAuthenticationTests.cs | 13 + .../Operations/ShutdownNodeTests.cs | 13 + .../FilterTestCases.cs} | 4 +- ...ToAllConnectWithoutReadPermissionsTests.cs | 30 + .../SubscribeToAllFilterTests.cs | 129 +++ .../SubscribeToAllGetInfoTests.cs | 101 ++ ...eToAllListWithIncorrectCredentialsTests.cs | 63 ++ ...SubscribeToAllNoDefaultCredentialsTests.cs | 93 ++ .../SubscribeToAllReplayParkedTests.cs | 84 ++ ...AllResultWithNormalUserCredentialsTests.cs | 34 + .../SubscribeToAllReturnsAllSubscriptions.cs | 41 + ...AllReturnsSubscriptionsToAllStreamTests.cs | 35 + .../SubscribeToAllTests.cs | 903 ++++++++++++++++++ ...beToAllUpdateExistingWithCheckpointTest.cs | 86 ++ .../SubscribeToAllWithoutPSTests.cs | 15 + .../SubscribeToStreamGetInfoTests.cs} | 201 ++-- .../SubscribeToStreamListTests.cs | 44 + ...scribeToStreamNoDefaultCredentialsTests.cs | 77 ++ .../SubscribeToStreamReplayParkedTests.cs | 68 ++ .../SubscribeToStreamTests.cs | 743 ++++++++++++++ test/EventStore.Client.Tests/PositionTests.cs | 6 +- .../PrefixFilterExpressionTests.cs | 11 - .../ProjectionManagementTests.cs | 205 ++++ .../RegularFilterExpressionTests.cs | 2 +- .../AllStreamWithNoAclSecurityTests.cs} | 10 +- .../Security/DeleteStreamSecurityTests.cs} | 35 +- .../Security/MultipleRoleSecurityTests.cs} | 12 +- ...erridenSystemStreamSecurityForAllTests.cs} | 8 +- .../OverridenSystemStreamSecurityTests.cs} | 8 +- .../OverridenUserStreamSecurityTests.cs} | 8 +- .../Security/ReadAllSecurityTests.cs} | 9 +- .../Security/ReadStreamMetaSecurityTests.cs} | 25 +- .../Security/ReadStreamSecurityTests.cs} | 11 +- .../Security/SecurityFixture.cs | 17 +- .../StreamSecurityInheritanceTests.cs} | 14 +- .../Security/SubscribeToAllSecurityTests.cs} | 9 +- .../SubscribeToStreamSecurityTests.cs} | 25 +- .../Security/SystemStreamSecurityTests.cs} | 11 +- .../Security/WriteStreamMetaSecurityTests.cs} | 16 +- .../Security/WriteStreamSecurityTests.cs} | 8 +- .../SharingProviderTests.cs | 22 +- .../StreamPositionTests.cs | 26 +- .../StreamRevisionTests.cs | 26 +- .../StreamStateTests.cs | 18 +- .../Streams/AppendTests.cs} | 390 +++++++- .../Streams/Bugs/Obsolete/Issue104.cs} | 4 +- .../Streams/Bugs/Obsolete/Issue2544.cs} | 42 +- .../Streams/DeleteTests.cs} | 45 +- .../Streams}/Read/EventBinaryData.cs | 28 +- .../Streams}/Read/EventDataComparer.cs | 4 +- .../Read/ReadAllEventsBackwardTests.cs} | 28 +- .../Streams}/Read/ReadAllEventsFixture.cs | 12 +- .../Read/ReadAllEventsForwardTests.cs} | 31 +- .../Streams/Read/ReadStreamBackwardTests.cs} | 18 +- ...StreamEventsLinkedToDeletedStreamTests.cs} | 32 +- .../Streams/Read/ReadStreamForwardTests.cs} | 12 +- ...eamWhenHavingMaxCountSetForStreamTests.cs} | 10 +- .../Streams/SoftDeleteTests.cs} | 34 +- .../Streams/StreamMetadataTests.cs} | 17 +- .../Streams/SubscribeToStreamTests.cs} | 63 +- .../Streams}/SubscriptionFilter.cs | 9 +- test/EventStore.Client.Tests/UuidTests.cs | 14 +- .../ValueObjectTests.cs | 6 +- .../X509CertificatesTests.cs | 14 +- .../AssemblyInfo.cs | 1 - ...ntStore.Client.UserManagement.Tests.csproj | 12 - ...nt.UserManagement.Tests.csproj.DotSettings | 2 - .../InvalidCredentialsTestCases.cs | 30 - .../UserCredentialsTests.cs | 42 - .../changing_user_password.cs | 76 -- .../creating_a_user.cs | 84 -- .../deleting_a_user.cs | 68 -- .../disabling_a_user.cs | 64 -- .../enabling_a_user.cs | 62 -- .../getting_current_user.cs | 14 - .../listing_users.cs | 42 - .../resetting_user_password.cs | 80 -- 346 files changed, 5039 insertions(+), 14036 deletions(-) delete mode 100644 test/EventStore.Client.Operations.Tests/AssemblyInfo.cs delete mode 100644 test/EventStore.Client.Operations.Tests/EventStore.Client.Operations.Tests.csproj delete mode 100644 test/EventStore.Client.Operations.Tests/ResignNodeTests.cs delete mode 100644 test/EventStore.Client.Operations.Tests/RestartPersistentSubscriptionsTests.cs delete mode 100644 test/EventStore.Client.Operations.Tests/ShutdownNodeAuthenticationTests.cs delete mode 100644 test/EventStore.Client.Operations.Tests/ShutdownNodeTests.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/AssemblyInfo.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/Bugs/Issue_1125.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/Diagnostics/PersistentSubscriptionsTracingInstrumentationTests.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/EventStore.Client.PersistentSubscriptions.Tests.csproj delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/EventStore.Client.PersistentSubscriptions.Tests.csproj.DotSettings delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/EventStoreClientFixture.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/PersistentSubscriptionSettingsTests.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_max_one_client_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_permissions_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_beginning_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_not_set_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_not_set_then_event_written_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_set_to_end_position_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_set_to_end_position_then_event_written_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_set_to_invalid_middle_position_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_set_to_valid_middle_position_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_without_permissions_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_without_read_all_permissions_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_non_existing_with_permissions_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_with_retries_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/deleting_existing_with_subscriber_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/happy_case_catching_up_to_link_to_events_manual_ack_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/happy_case_catching_up_to_normal_events_manual_ack_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/happy_case_filtered_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/happy_case_filtered_with_start_from_set_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/happy_case_writing_and_subscribing_to_normal_events_manual_ack_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/update_existing_with_check_point_filtered_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/update_existing_with_subscribers_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/when_writing_and_filtering_out_events_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/when_writing_and_subscribing_to_normal_events_manual_nack_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/can_create_duplicate_name_on_different_streams.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_max_one_client.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_permissions.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_beginning.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_not_set.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_not_set_then_event_written.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_set_to_end_position.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_set_to_end_position_then_event_written.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_set_to_invalid_middle_position.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_set_to_valid_middle_position.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_without_permissions.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_without_read_all_permissions.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_non_existing_with_permissions.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_with_retries.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_after_deleting_the_same.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_duplicate.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_filtered.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_on_all_stream.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_persistent_subscription_with_dont_timeout.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_with_commit_position_equal_to_last_indexed_position.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_with_commit_position_larger_than_last_indexed_position.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_with_prepare_position_larger_than_commit_position.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_without_permissions.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/deleting_existing_with_permissions.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/deleting_existing_with_subscriber.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/deleting_filtered.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/deleting_nonexistent.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/deleting_without_permissions.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/get_info.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/happy_case_catching_up_to_link_to_events_manual_ack.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/happy_case_catching_up_to_normal_events_manual_ack.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/happy_case_filtered.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/happy_case_filtered_with_start_from_set.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/happy_case_writing_and_subscribing_to_normal_events_manual_ack.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/list_with_persistent_subscriptions.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/list_without_persistent_subscriptions.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/replay_parked.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_filtered.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_with_check_point.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_with_check_point_filtered.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_with_commit_position_equal_to_last_indexed_position.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_with_commit_position_larger_than_last_indexed_position.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_with_subscribers.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_without_permissions.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_non_existent.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_with_prepare_position_larger_than_commit_position.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/when_writing_and_filtering_out_events.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/when_writing_and_subscribing_to_normal_events_manual_nack.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_max_one_client_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_permissions_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_beginning_and_events_in_it_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_beginning_and_no_stream_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_not_set_and_events_in_it_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_not_set_and_events_in_it_then_event_written_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_then_event_written_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_two_and_no_stream_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_x_set_and_events_in_it_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_x_set_and_events_in_it_then_event_written_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_x_set_higher_than_x_and_events_in_it_then_event_written_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_without_permissions_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_non_existing_with_permissions_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_with_retries_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connecting_to_a_persistent_subscription_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/deleting_existing_with_subscriber_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/get_info_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/happy_case_catching_up_to_link_to_events_manual_ack_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/happy_case_catching_up_to_normal_events_manual_ack_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/happy_case_writing_and_subscribing_to_normal_events_manual_ack_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/update_existing_with_check_point_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/update_existing_with_subscribers_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/when_writing_and_subscribing_to_normal_events_manual_nack_obsolete.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/can_create_duplicate_name_on_different_streams.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_max_one_client.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_permissions.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_beginning_and_events_in_it.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_beginning_and_no_stream.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_not_set_and_events_in_it.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_not_set_and_events_in_it_then_event_written.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_set_to_end_position_and_events_in_it.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_then_event_written.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_two_and_no_stream.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_x_set_and_events_in_it.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_x_set_and_events_in_it_then_event_written.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_x_set_higher_than_x_and_events_in_it_then_event_written.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_without_permissions.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_non_existing_with_permissions.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_with_retries.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connecting_to_a_persistent_subscription.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_after_deleting_the_same.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_duplicate.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_on_existing_stream.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_on_non_existing_stream.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_persistent_subscription_with_dont_timeout.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_without_permissions.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/deleting_existing_with_permissions.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/deleting_existing_with_subscriber.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/deleting_nonexistent.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/deleting_without_permissions.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/get_info.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/happy_case_catching_up_to_link_to_events_manual_ack.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/happy_case_catching_up_to_normal_events_manual_ack.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/happy_case_writing_and_subscribing_to_normal_events_manual_ack.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/list_with_persistent_subscriptions.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/list_without_persistent_subscriptions.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/replay_parked.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/update_existing.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/update_existing_with_check_point.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/update_existing_with_subscribers.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/update_existing_without_permissions.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/update_non_existent.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/when_writing_and_subscribing_to_normal_events_manual_nack.cs delete mode 100644 test/EventStore.Client.PersistentSubscriptions.Tests/restart_subsystem.cs delete mode 100644 test/EventStore.Client.Plugins.Tests/EventStore.Client.Plugins.Tests.csproj delete mode 100644 test/EventStore.Client.ProjectionManagement.Tests/AssemblyInfo.cs delete mode 100644 test/EventStore.Client.ProjectionManagement.Tests/EventStore.Client.ProjectionManagement.Tests.csproj delete mode 100644 test/EventStore.Client.ProjectionManagement.Tests/EventStoreClientFixture.cs delete mode 100644 test/EventStore.Client.ProjectionManagement.Tests/StandardProjections.cs delete mode 100644 test/EventStore.Client.ProjectionManagement.Tests/abort.cs delete mode 100644 test/EventStore.Client.ProjectionManagement.Tests/create.cs delete mode 100644 test/EventStore.Client.ProjectionManagement.Tests/disable.cs delete mode 100644 test/EventStore.Client.ProjectionManagement.Tests/enable.cs delete mode 100644 test/EventStore.Client.ProjectionManagement.Tests/get_result.cs delete mode 100644 test/EventStore.Client.ProjectionManagement.Tests/get_state.cs delete mode 100644 test/EventStore.Client.ProjectionManagement.Tests/get_status.cs delete mode 100644 test/EventStore.Client.ProjectionManagement.Tests/list_all_projections.cs delete mode 100644 test/EventStore.Client.ProjectionManagement.Tests/list_continuous_projections.cs delete mode 100644 test/EventStore.Client.ProjectionManagement.Tests/list_one_time_projections.cs delete mode 100644 test/EventStore.Client.ProjectionManagement.Tests/reset.cs delete mode 100644 test/EventStore.Client.ProjectionManagement.Tests/restart_subsystem.cs delete mode 100644 test/EventStore.Client.ProjectionManagement.Tests/update.cs delete mode 100644 test/EventStore.Client.Streams.Tests/Append/append_to_stream_limits.cs delete mode 100644 test/EventStore.Client.Streams.Tests/Append/append_to_stream_retry.cs delete mode 100644 test/EventStore.Client.Streams.Tests/Append/append_to_stream_with_tls_ca_file.cs delete mode 100644 test/EventStore.Client.Streams.Tests/Append/appending_to_implicitly_created_stream.cs delete mode 100644 test/EventStore.Client.Streams.Tests/Append/sending_and_receiving_large_messages.cs delete mode 100644 test/EventStore.Client.Streams.Tests/AssemblyInfo.cs delete mode 100644 test/EventStore.Client.Streams.Tests/DependencyInjectionTests.cs delete mode 100644 test/EventStore.Client.Streams.Tests/Diagnostics/StreamsTracingInstrumentationTests.cs delete mode 100644 test/EventStore.Client.Streams.Tests/EventDataTests.cs delete mode 100644 test/EventStore.Client.Streams.Tests/EventStore.Client.Streams.Tests.csproj delete mode 100644 test/EventStore.Client.Streams.Tests/EventStore.Client.Streams.Tests.csproj.DotSettings delete mode 100644 test/EventStore.Client.Streams.Tests/Security/Obsolete/SecurityFixture_obsolete.cs delete mode 100644 test/EventStore.Client.Streams.Tests/Security/Obsolete/all_stream_with_no_acl_security_obsolete.cs delete mode 100644 test/EventStore.Client.Streams.Tests/Security/Obsolete/overriden_system_stream_security_for_all_obsolete.cs delete mode 100644 test/EventStore.Client.Streams.Tests/Security/Obsolete/overriden_system_stream_security_obsolete.cs delete mode 100644 test/EventStore.Client.Streams.Tests/Security/Obsolete/overriden_user_stream_security_obsolete.cs delete mode 100644 test/EventStore.Client.Streams.Tests/Security/Obsolete/subscribe_to_all_security_obsolete.cs delete mode 100644 test/EventStore.Client.Streams.Tests/Security/Obsolete/subscribe_to_stream_security_obsolete.cs delete mode 100644 test/EventStore.Client.Streams.Tests/Security/Obsolete/system_stream_security_obsolete.cs delete mode 100644 test/EventStore.Client.Streams.Tests/Serialization/is_json.cs delete mode 100644 test/EventStore.Client.Streams.Tests/Subscriptions/Obsolete/subscribe_to_all_obsolete.cs delete mode 100644 test/EventStore.Client.Streams.Tests/Subscriptions/Obsolete/subscribe_to_stream_obsolete.cs delete mode 100644 test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionDroppedResult.cs delete mode 100644 test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionsFixture.cs delete mode 100644 test/EventStore.Client.Streams.Tests/Subscriptions/reconnection.cs delete mode 100644 test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all.cs rename test/{EventStore.Client.ProjectionManagement.Tests => EventStore.Client.Tests.Common}/AssertEx.cs (97%) rename test/{EventStore.Client.Streams.Tests/Append => EventStore.Client.Tests.Common/Extensions}/ShouldThrowAsyncExtensions.cs (90%) rename test/{EventStore.Client.Tests => EventStore.Client.Tests.Common/Extensions}/TypeExtensions.cs (98%) delete mode 100644 test/EventStore.Client.Tests.Common/Facts/SupportsPSToAllFact.cs delete mode 100644 test/EventStore.Client.Tests.Common/Fixtures/Base/EventStoreClientFixtureBase.cs delete mode 100644 test/EventStore.Client.Tests.Common/Fixtures/Base/EventStoreTestServer.cs delete mode 100644 test/EventStore.Client.Tests.Common/Fixtures/Base/EventStoreTestServerCluster.cs delete mode 100644 test/EventStore.Client.Tests.Common/Fixtures/Base/EventStoreTestServerExternal.cs delete mode 100644 test/EventStore.Client.Tests.Common/Fixtures/Base/IEventStoreTestServer.cs create mode 100644 test/EventStore.Client.Tests.Common/Fixtures/BaseTestNode.cs delete mode 100644 test/EventStore.Client.Tests.Common/Fixtures/DiagnosticsFixture.cs delete mode 100644 test/EventStore.Client.Tests.Common/Fixtures/EventStoreTestCluster.cs delete mode 100644 test/EventStore.Client.Tests.Common/Fixtures/InsecureClientTestFixture.cs create mode 100644 test/EventStore.Client.Tests.Common/Fixtures/KurrentFixtureOptions.cs rename test/EventStore.Client.Tests.Common/Fixtures/{EventStoreFixture.Helpers.cs => KurrentPermanentFixture.Helpers.cs} (78%) rename test/EventStore.Client.Tests.Common/Fixtures/{EventStoreFixture.cs => KurrentPermanentFixture.cs} (64%) rename test/EventStore.Client.Tests.Common/Fixtures/{EventStoreTestNode.cs => KurrentPermanentTestNode.cs} (54%) create mode 100644 test/EventStore.Client.Tests.Common/Fixtures/KurrentTemporaryFixture.Helpers.cs create mode 100644 test/EventStore.Client.Tests.Common/Fixtures/KurrentTemporaryFixture.cs create mode 100644 test/EventStore.Client.Tests.Common/Fixtures/KurrentTemporaryTestNode.cs delete mode 100644 test/EventStore.Client.Tests.Common/Fixtures/RunInMemoryTestFixture.cs delete mode 100644 test/EventStore.Client.Tests.Common/Fixtures/RunProjectionsTestFixture.cs rename test/{EventStore.Client.Plugins.Tests/ClientCertificateTests.cs => EventStore.Client.Tests/ClientCertificatesTests.cs} (76%) rename test/EventStore.Client.Tests/{EventStoreClientOperationOptionsTests.cs => EventStoreClientOperationsTests.cs} (89%) delete mode 100644 test/EventStore.Client.Tests/Interceptors/ReportLeaderInterceptorTests.cs create mode 100644 test/EventStore.Client.Tests/ListProjectionTests.cs rename test/{EventStore.Client.Operations.Tests => EventStore.Client.Tests/Operations}/AuthenticationTests.cs (64%) rename test/{EventStore.Client.Operations.Tests/MergeIndexesTests.cs => EventStore.Client.Tests/Operations/MergeIndexTests.cs} (50%) create mode 100644 test/EventStore.Client.Tests/Operations/ResignNodeTests.cs create mode 100644 test/EventStore.Client.Tests/Operations/RestartPersistentSubscriptionsTests.cs rename test/{EventStore.Client.Operations.Tests => EventStore.Client.Tests/Operations}/ScavengeTests.cs (79%) create mode 100644 test/EventStore.Client.Tests/Operations/ShutdownNodeAuthenticationTests.cs create mode 100644 test/EventStore.Client.Tests/Operations/ShutdownNodeTests.cs rename test/{EventStore.Client.PersistentSubscriptions.Tests/FilterTestCase.cs => EventStore.Client.Tests/PersistentSubscriptions/FilterTestCases.cs} (95%) create mode 100644 test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllConnectWithoutReadPermissionsTests.cs create mode 100644 test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllFilterTests.cs create mode 100644 test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllGetInfoTests.cs create mode 100644 test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllListWithIncorrectCredentialsTests.cs create mode 100644 test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllNoDefaultCredentialsTests.cs create mode 100644 test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllReplayParkedTests.cs create mode 100644 test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllResultWithNormalUserCredentialsTests.cs create mode 100644 test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllReturnsAllSubscriptions.cs create mode 100644 test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllReturnsSubscriptionsToAllStreamTests.cs create mode 100644 test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllTests.cs create mode 100644 test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllUpdateExistingWithCheckpointTest.cs create mode 100644 test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllWithoutPSTests.cs rename test/{EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/get_info_obsolete.cs => EventStore.Client.Tests/PersistentSubscriptions/SubscribeToStreamGetInfoTests.cs} (52%) create mode 100644 test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToStreamListTests.cs create mode 100644 test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToStreamNoDefaultCredentialsTests.cs create mode 100644 test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToStreamReplayParkedTests.cs create mode 100644 test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToStreamTests.cs delete mode 100644 test/EventStore.Client.Tests/PrefixFilterExpressionTests.cs create mode 100644 test/EventStore.Client.Tests/ProjectionManagementTests.cs rename test/{EventStore.Client.Streams.Tests/Security/all_stream_with_no_acl_security.cs => EventStore.Client.Tests/Security/AllStreamWithNoAclSecurityTests.cs} (90%) rename test/{EventStore.Client.Streams.Tests/Security/delete_stream_security.cs => EventStore.Client.Tests/Security/DeleteStreamSecurityTests.cs} (87%) rename test/{EventStore.Client.Streams.Tests/Security/multiple_role_security.cs => EventStore.Client.Tests/Security/MultipleRoleSecurityTests.cs} (83%) rename test/{EventStore.Client.Streams.Tests/Security/overriden_system_stream_security_for_all.cs => EventStore.Client.Tests/Security/OverridenSystemStreamSecurityForAllTests.cs} (86%) rename test/{EventStore.Client.Streams.Tests/Security/overriden_system_stream_security.cs => EventStore.Client.Tests/Security/OverridenSystemStreamSecurityTests.cs} (91%) rename test/{EventStore.Client.Streams.Tests/Security/overriden_user_stream_security.cs => EventStore.Client.Tests/Security/OverridenUserStreamSecurityTests.cs} (91%) rename test/{EventStore.Client.Streams.Tests/Security/read_all_security.cs => EventStore.Client.Tests/Security/ReadAllSecurityTests.cs} (83%) rename test/{EventStore.Client.Streams.Tests/Security/read_stream_meta_security.cs => EventStore.Client.Tests/Security/ReadStreamMetaSecurityTests.cs} (74%) rename test/{EventStore.Client.Streams.Tests/Security/read_stream_security.cs => EventStore.Client.Tests/Security/ReadStreamSecurityTests.cs} (96%) rename test/{EventStore.Client.Streams.Tests => EventStore.Client.Tests}/Security/SecurityFixture.cs (97%) rename test/{EventStore.Client.Streams.Tests/Security/stream_security_inheritance.cs => EventStore.Client.Tests/Security/StreamSecurityInheritanceTests.cs} (95%) rename test/{EventStore.Client.Streams.Tests/Security/subscribe_to_all_security.cs => EventStore.Client.Tests/Security/SubscribeToAllSecurityTests.cs} (77%) rename test/{EventStore.Client.Streams.Tests/Security/subscribe_to_stream_security.cs => EventStore.Client.Tests/Security/SubscribeToStreamSecurityTests.cs} (78%) rename test/{EventStore.Client.Streams.Tests/Security/system_stream_security.cs => EventStore.Client.Tests/Security/SystemStreamSecurityTests.cs} (94%) rename test/{EventStore.Client.Streams.Tests/Security/write_stream_meta_security.cs => EventStore.Client.Tests/Security/WriteStreamMetaSecurityTests.cs} (86%) rename test/{EventStore.Client.Streams.Tests/Security/write_stream_security.cs => EventStore.Client.Tests/Security/WriteStreamSecurityTests.cs} (93%) rename test/{EventStore.Client.Streams.Tests/Append/append_to_stream.cs => EventStore.Client.Tests/Streams/AppendTests.cs} (55%) rename test/{EventStore.Client.Streams.Tests/Bugs/Obsolete/Issue_104.cs => EventStore.Client.Tests/Streams/Bugs/Obsolete/Issue104.cs} (89%) rename test/{EventStore.Client.Streams.Tests/Bugs/Obsolete/Issue_2544.cs => EventStore.Client.Tests/Streams/Bugs/Obsolete/Issue2544.cs} (82%) rename test/{EventStore.Client.Streams.Tests/Delete/deleting_stream.cs => EventStore.Client.Tests/Streams/DeleteTests.cs} (72%) rename test/{EventStore.Client.Streams.Tests => EventStore.Client.Tests/Streams}/Read/EventBinaryData.cs (81%) rename test/{EventStore.Client.Streams.Tests => EventStore.Client.Tests/Streams}/Read/EventDataComparer.cs (91%) rename test/{EventStore.Client.Streams.Tests/Read/read_all_events_backward.cs => EventStore.Client.Tests/Streams/Read/ReadAllEventsBackwardTests.cs} (87%) rename test/{EventStore.Client.Streams.Tests => EventStore.Client.Tests/Streams}/Read/ReadAllEventsFixture.cs (81%) rename test/{EventStore.Client.Streams.Tests/Read/read_all_events_forward.cs => EventStore.Client.Tests/Streams/Read/ReadAllEventsForwardTests.cs} (91%) rename test/{EventStore.Client.Streams.Tests/Read/read_stream_backward.cs => EventStore.Client.Tests/Streams/Read/ReadStreamBackwardTests.cs} (96%) rename test/{EventStore.Client.Streams.Tests/Read/read_stream_events_linked_to_deleted_stream.cs => EventStore.Client.Tests/Streams/Read/ReadStreamEventsLinkedToDeletedStreamTests.cs} (70%) rename test/{EventStore.Client.Streams.Tests/Read/read_stream_forward.cs => EventStore.Client.Tests/Streams/Read/ReadStreamForwardTests.cs} (96%) rename test/{EventStore.Client.Streams.Tests/Read/read_stream_when_having_max_count_set_for_stream.cs => EventStore.Client.Tests/Streams/Read/ReadStreamWhenHavingMaxCountSetForStreamTests.cs} (93%) rename test/{EventStore.Client.Streams.Tests/Delete/soft_deleted_stream.cs => EventStore.Client.Tests/Streams/SoftDeleteTests.cs} (94%) rename test/{EventStore.Client.Streams.Tests/Metadata/stream_metadata.cs => EventStore.Client.Tests/Streams/StreamMetadataTests.cs} (92%) rename test/{EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream.cs => EventStore.Client.Tests/Streams/SubscribeToStreamTests.cs} (80%) rename test/{EventStore.Client.Streams.Tests/Subscriptions => EventStore.Client.Tests/Streams}/SubscriptionFilter.cs (92%) delete mode 100644 test/EventStore.Client.UserManagement.Tests/AssemblyInfo.cs delete mode 100644 test/EventStore.Client.UserManagement.Tests/EventStore.Client.UserManagement.Tests.csproj delete mode 100644 test/EventStore.Client.UserManagement.Tests/EventStore.Client.UserManagement.Tests.csproj.DotSettings delete mode 100644 test/EventStore.Client.UserManagement.Tests/InvalidCredentialsTestCases.cs delete mode 100644 test/EventStore.Client.UserManagement.Tests/UserCredentialsTests.cs delete mode 100644 test/EventStore.Client.UserManagement.Tests/changing_user_password.cs delete mode 100644 test/EventStore.Client.UserManagement.Tests/creating_a_user.cs delete mode 100644 test/EventStore.Client.UserManagement.Tests/deleting_a_user.cs delete mode 100644 test/EventStore.Client.UserManagement.Tests/disabling_a_user.cs delete mode 100644 test/EventStore.Client.UserManagement.Tests/enabling_a_user.cs delete mode 100644 test/EventStore.Client.UserManagement.Tests/getting_current_user.cs delete mode 100644 test/EventStore.Client.UserManagement.Tests/listing_users.cs delete mode 100644 test/EventStore.Client.UserManagement.Tests/resetting_user_password.cs diff --git a/.github/workflows/base.yml b/.github/workflows/base.yml index 20cfe91d7..40a0c3c5e 100644 --- a/.github/workflows/base.yml +++ b/.github/workflows/base.yml @@ -63,4 +63,11 @@ jobs: dotnet test --configuration ${{ matrix.configuration }} --blame \ --logger:"GitHubActions;report-warnings=false" --logger:"console;verbosity=normal" \ --framework ${{ matrix.framework }} \ - test/EventStore.Client.${{ inputs.test }}.Tests + test/EventStore.Client.Tests + +# run: | +# sudo ./gencert.sh +# dotnet test --configuration ${{ matrix.configuration }} --blame \ +# --logger:"GitHubActions;report-warnings=false" --logger:"console;verbosity=normal" \ +# --framework ${{ matrix.framework }} \ +# test/EventStore.Client.${{ inputs.test }}.Tests diff --git a/.github/workflows/dispatch-ce.yml b/.github/workflows/dispatch-ce.yml index 722baaea7..31e2d8966 100644 --- a/.github/workflows/dispatch-ce.yml +++ b/.github/workflows/dispatch-ce.yml @@ -15,10 +15,10 @@ on: jobs: test: uses: ./.github/workflows/base.yml - strategy: - fail-fast: false - matrix: - test: [ Streams, PersistentSubscriptions, Operations, UserManagement, ProjectionManagement ] +# strategy: +# fail-fast: false +# matrix: +# test: [ Streams, PersistentSubscriptions, Operations, UserManagement, ProjectionManagement ] name: Test CE (${{ inputs.docker-tag }}) with: docker-tag: ${{ inputs.docker-tag }} diff --git a/.github/workflows/dispatch-ee.yml b/.github/workflows/dispatch-ee.yml index 13f0b3398..75bde07de 100644 --- a/.github/workflows/dispatch-ee.yml +++ b/.github/workflows/dispatch-ee.yml @@ -1,29 +1,29 @@ -name: Dispatch EE - -on: - workflow_dispatch: - inputs: - docker-tag: - description: "Docker tag" - required: true - type: string - docker-image: - description: "Docker image" - required: true - type: string - -jobs: - test: - uses: ./.github/workflows/base.yml - strategy: - fail-fast: false - matrix: - test: [ Plugins ] - name: Test EE (${{ inputs.docker-tag }}) - with: - docker-tag: ${{ inputs.docker-tag }} - docker-image: ${{ inputs.docker-image }} - test: ${{ matrix.test }} - secrets: - CLOUDSMITH_CICD_USER: ${{ secrets.CLOUDSMITH_CICD_USER }} - CLOUDSMITH_CICD_TOKEN: ${{ secrets.CLOUDSMITH_CICD_TOKEN }} +#name: Dispatch EE +# +#on: +# workflow_dispatch: +# inputs: +# docker-tag: +# description: "Docker tag" +# required: true +# type: string +# docker-image: +# description: "Docker image" +# required: true +# type: string +# +#jobs: +# test: +# uses: ./.github/workflows/base.yml +## strategy: +## fail-fast: false +## matrix: +## test: [ Plugins ] +# name: Test EE (${{ inputs.docker-tag }}) +# with: +# docker-tag: ${{ inputs.docker-tag }} +# docker-image: ${{ inputs.docker-image }} +# test: ${{ matrix.test }} +# secrets: +# CLOUDSMITH_CICD_USER: ${{ secrets.CLOUDSMITH_CICD_USER }} +# CLOUDSMITH_CICD_TOKEN: ${{ secrets.CLOUDSMITH_CICD_TOKEN }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 42535a11d..ebe348e3e 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,193 +1,193 @@ -name: Publish - -on: - pull_request: - push: - branches: - - master - tags: - - v* - -jobs: - vulnerability-scan: - timeout-minutes: 10 - strategy: - fail-fast: false - matrix: - framework: [ net8.0 ] - os: [ ubuntu-latest, windows-latest ] - runs-on: ${{ matrix.os }} - name: scan-vulnerabilities/${{ matrix.os }}/${{ matrix.framework }} - steps: - - name: Checkout - uses: actions/checkout@v3 - - name: Install dotnet SDKs - uses: actions/setup-dotnet@v3 - with: - dotnet-version: | - 8.0.x - - name: Scan for Vulnerabilities - shell: bash - run: | - dotnet nuget list source - dotnet restore - dotnet list package --vulnerable --include-transitive --framework ${{ matrix.framework }} | tee vulnerabilities.txt - ! cat vulnerabilities.txt | grep -q "has the following vulnerable packages" - - build-samples: - timeout-minutes: 5 - name: build-samples/${{ matrix.framework }} - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - framework: [ net8.0 ] - services: - esdb: - image: docker.eventstore.com/eventstore-ce/eventstoredb-ce:lts - env: - EVENTSTORE_INSECURE: true - EVENTSTORE_MEM_DB: false - EVENTSTORE_RUN_PROJECTIONS: all - EVENTSTORE_START_STANDARD_PROJECTIONS: true - ports: - - 2113:2113 - options: --health-cmd "exit 0" - steps: - - name: Checkout - uses: actions/checkout@v3 - - name: Install dotnet SDKs - uses: actions/setup-dotnet@v3 - with: - dotnet-version: | - 8.0.x - - name: Compile - shell: bash - run: | - dotnet build samples - - name: Run - shell: bash - run: | - find samples/ -type f -iname "*.csproj" -print0 | xargs -0L1 dotnet run --framework ${{ matrix.framework }} --project - - generate-certificates: - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - - name: Generate certificates - run: | - mkdir -p certs - docker run --rm --user root --volume "$PWD/certs:/tmp" docker.eventstore.com/eventstore-utils/es-gencert-cli:latest create-ca -out /tmp/ca - docker run --rm --user root --volume "$PWD/certs:/tmp" docker.eventstore.com/eventstore-utils/es-gencert-cli:latest create-node -ca-certificate /tmp/ca/ca.crt -ca-key /tmp/ca/ca.key -out /tmp/node -ip-addresses 127.0.0.1 -dns-names localhost - docker run --rm --user root --volume "$PWD/certs:/tmp" docker.eventstore.com/eventstore-utils/es-gencert-cli:latest create-user -username admin -ca-certificate /tmp/ca/ca.crt -ca-key /tmp/ca/ca.key -out /tmp/user-admin - docker run --rm --user root --volume "$PWD/certs:/tmp" docker.eventstore.com/eventstore-utils/es-gencert-cli:latest create-user -username invalid -ca-certificate /tmp/ca/ca.crt -ca-key /tmp/ca/ca.key -out /tmp/user-invalid - - name: Set permissions on certificates - run: | - sudo chown -R $USER:$USER certs - sudo chmod -R 755 certs - - name: Upload certificates - uses: actions/upload-artifact@v4 - with: - name: certs - path: certs - - test: - needs: generate-certificates - timeout-minutes: 20 - strategy: - fail-fast: false - matrix: - framework: [ net8.0 ] - os: [ ubuntu-latest, windows-latest ] - configuration: [ release ] - runs-on: ${{ matrix.os }} - name: test/EventStore.Client/${{ matrix.os }}/${{ matrix.framework }} - steps: - - name: Checkout - uses: actions/checkout@v3 - - shell: bash - run: | - git fetch --prune --unshallow - - name: Install dotnet SDKs - uses: actions/setup-dotnet@v3 - with: - dotnet-version: | - 8.0.x - - name: Compile - shell: bash - run: | - dotnet build --configuration ${{ matrix.configuration }} --framework ${{ matrix.framework }} src/EventStore.Client - - name: Download certificates - uses: actions/download-artifact@v4 - with: - name: certs - path: certs - - name: Run Tests (Linux) - if: runner.os == 'Linux' - shell: bash - run: | - dotnet test --configuration ${{ matrix.configuration }} --blame \ - --logger:"GitHubActions;report-warnings=false" --logger:"console;verbosity=normal" \ - --framework ${{ matrix.framework }} \ - test/EventStore.Client.Tests - - name: Run Tests (Windows) - if: runner.os == 'Windows' - shell: pwsh - run: | - dotnet test --configuration ${{ matrix.configuration }} --blame ` - --logger:"GitHubActions;report-warnings=false" --logger:"console;verbosity=normal" ` - --framework ${{ matrix.framework }} ` - test/EventStore.Client.Tests - - publish: - timeout-minutes: 5 - needs: [ vulnerability-scan, test, build-samples ] - runs-on: ubuntu-latest - name: publish - steps: - - name: Checkout - uses: actions/checkout@v3 - - name: Get Version - id: get_version - run: | - echo "branch=${GITHUB_REF:10}" >> $GITHUB_OUTPUT - dotnet nuget list source - dotnet tool restore - version=$(dotnet tool run minver -- --tag-prefix=v) - echo "version=${version}" >> $GITHUB_OUTPUT - - shell: bash - run: | - git fetch --prune --unshallow - - name: Install dotnet SDKs - uses: actions/setup-dotnet@v3 - with: - dotnet-version: | - 8.0.x - - name: Dotnet Pack - shell: bash - run: | - mkdir -p packages - dotnet pack /p:Version=${{ steps.get_version.outputs.version }} --configuration=Release \ - /p:PublishDir=./packages \ - /p:NoWarn=NU5105 \ - /p:RepositoryUrl=https://github.com/EventStore/EventStore-Client-Dotnet \ - /p:RepositoryType=git - - name: Publish Artifacts - uses: actions/upload-artifact@v4 - with: - path: packages - name: nuget-packages - - name: Dotnet Push to Github Packages - shell: bash - if: github.event_name == 'push' - run: | - dotnet tool restore - find . -name "*.nupkg" | xargs -n1 dotnet nuget push --api-key=${{ secrets.github_token }} --source https://nuget.pkg.github.com/EventStore/index.json --skip-duplicate - - name: Dotnet Push to Nuget.org - shell: bash - if: contains(steps.get_version.outputs.branch, 'v') - run: | - dotnet nuget list source - dotnet tool restore - find . -name "*.nupkg" | xargs -n1 dotnet nuget push --api-key=${{ secrets.nuget_key }} --source https://api.nuget.org/v3/index.json --skip-duplicate +#name: Publish +# +#on: +# pull_request: +# push: +# branches: +# - master +# tags: +# - v* +# +#jobs: +# vulnerability-scan: +# timeout-minutes: 10 +# strategy: +# fail-fast: false +# matrix: +# framework: [ net8.0 ] +# os: [ ubuntu-latest, windows-latest ] +# runs-on: ${{ matrix.os }} +# name: scan-vulnerabilities/${{ matrix.os }}/${{ matrix.framework }} +# steps: +# - name: Checkout +# uses: actions/checkout@v3 +# - name: Install dotnet SDKs +# uses: actions/setup-dotnet@v3 +# with: +# dotnet-version: | +# 8.0.x +# - name: Scan for Vulnerabilities +# shell: bash +# run: | +# dotnet nuget list source +# dotnet restore +# dotnet list package --vulnerable --include-transitive --framework ${{ matrix.framework }} | tee vulnerabilities.txt +# ! cat vulnerabilities.txt | grep -q "has the following vulnerable packages" +# +# build-samples: +# timeout-minutes: 5 +# name: build-samples/${{ matrix.framework }} +# runs-on: ubuntu-latest +# strategy: +# fail-fast: false +# matrix: +# framework: [ net8.0 ] +# services: +# esdb: +# image: docker.eventstore.com/eventstore-ce/eventstoredb-ce:lts +# env: +# EVENTSTORE_INSECURE: true +# EVENTSTORE_MEM_DB: false +# EVENTSTORE_RUN_PROJECTIONS: all +# EVENTSTORE_START_STANDARD_PROJECTIONS: true +# ports: +# - 2113:2113 +# options: --health-cmd "exit 0" +# steps: +# - name: Checkout +# uses: actions/checkout@v3 +# - name: Install dotnet SDKs +# uses: actions/setup-dotnet@v3 +# with: +# dotnet-version: | +# 8.0.x +# - name: Compile +# shell: bash +# run: | +# dotnet build samples +# - name: Run +# shell: bash +# run: | +# find samples/ -type f -iname "*.csproj" -print0 | xargs -0L1 dotnet run --framework ${{ matrix.framework }} --project +# +# generate-certificates: +# runs-on: ubuntu-latest +# steps: +# - name: Checkout code +# uses: actions/checkout@v4 +# - name: Generate certificates +# run: | +# mkdir -p certs +# docker run --rm --user root --volume "$PWD/certs:/tmp" docker.eventstore.com/eventstore-utils/es-gencert-cli:latest create-ca -out /tmp/ca +# docker run --rm --user root --volume "$PWD/certs:/tmp" docker.eventstore.com/eventstore-utils/es-gencert-cli:latest create-node -ca-certificate /tmp/ca/ca.crt -ca-key /tmp/ca/ca.key -out /tmp/node -ip-addresses 127.0.0.1 -dns-names localhost +# docker run --rm --user root --volume "$PWD/certs:/tmp" docker.eventstore.com/eventstore-utils/es-gencert-cli:latest create-user -username admin -ca-certificate /tmp/ca/ca.crt -ca-key /tmp/ca/ca.key -out /tmp/user-admin +# docker run --rm --user root --volume "$PWD/certs:/tmp" docker.eventstore.com/eventstore-utils/es-gencert-cli:latest create-user -username invalid -ca-certificate /tmp/ca/ca.crt -ca-key /tmp/ca/ca.key -out /tmp/user-invalid +# - name: Set permissions on certificates +# run: | +# sudo chown -R $USER:$USER certs +# sudo chmod -R 755 certs +# - name: Upload certificates +# uses: actions/upload-artifact@v4 +# with: +# name: certs +# path: certs +# +# test: +# needs: generate-certificates +# timeout-minutes: 20 +# strategy: +# fail-fast: false +# matrix: +# framework: [ net8.0 ] +# os: [ ubuntu-latest, windows-latest ] +# configuration: [ release ] +# runs-on: ${{ matrix.os }} +# name: test/EventStore.Client/${{ matrix.os }}/${{ matrix.framework }} +# steps: +# - name: Checkout +# uses: actions/checkout@v3 +# - shell: bash +# run: | +# git fetch --prune --unshallow +# - name: Install dotnet SDKs +# uses: actions/setup-dotnet@v3 +# with: +# dotnet-version: | +# 8.0.x +# - name: Compile +# shell: bash +# run: | +# dotnet build --configuration ${{ matrix.configuration }} --framework ${{ matrix.framework }} src/EventStore.Client +# - name: Download certificates +# uses: actions/download-artifact@v4 +# with: +# name: certs +# path: certs +# - name: Run Tests (Linux) +# if: runner.os == 'Linux' +# shell: bash +# run: | +# dotnet test --configuration ${{ matrix.configuration }} --blame \ +# --logger:"GitHubActions;report-warnings=false" --logger:"console;verbosity=normal" \ +# --framework ${{ matrix.framework }} \ +# test/EventStore.Client.Tests +# - name: Run Tests (Windows) +# if: runner.os == 'Windows' +# shell: pwsh +# run: | +# dotnet test --configuration ${{ matrix.configuration }} --blame ` +# --logger:"GitHubActions;report-warnings=false" --logger:"console;verbosity=normal" ` +# --framework ${{ matrix.framework }} ` +# test/EventStore.Client.Tests +# +# publish: +# timeout-minutes: 5 +# needs: [ vulnerability-scan, test, build-samples ] +# runs-on: ubuntu-latest +# name: publish +# steps: +# - name: Checkout +# uses: actions/checkout@v3 +# - name: Get Version +# id: get_version +# run: | +# echo "branch=${GITHUB_REF:10}" >> $GITHUB_OUTPUT +# dotnet nuget list source +# dotnet tool restore +# version=$(dotnet tool run minver -- --tag-prefix=v) +# echo "version=${version}" >> $GITHUB_OUTPUT +# - shell: bash +# run: | +# git fetch --prune --unshallow +# - name: Install dotnet SDKs +# uses: actions/setup-dotnet@v3 +# with: +# dotnet-version: | +# 8.0.x +# - name: Dotnet Pack +# shell: bash +# run: | +# mkdir -p packages +# dotnet pack /p:Version=${{ steps.get_version.outputs.version }} --configuration=Release \ +# /p:PublishDir=./packages \ +# /p:NoWarn=NU5105 \ +# /p:RepositoryUrl=https://github.com/EventStore/EventStore-Client-Dotnet \ +# /p:RepositoryType=git +# - name: Publish Artifacts +# uses: actions/upload-artifact@v4 +# with: +# path: packages +# name: nuget-packages +# - name: Dotnet Push to Github Packages +# shell: bash +# if: github.event_name == 'push' +# run: | +# dotnet tool restore +# find . -name "*.nupkg" | xargs -n1 dotnet nuget push --api-key=${{ secrets.github_token }} --source https://nuget.pkg.github.com/EventStore/index.json --skip-duplicate +# - name: Dotnet Push to Nuget.org +# shell: bash +# if: contains(steps.get_version.outputs.branch, 'v') +# run: | +# dotnet nuget list source +# dotnet tool restore +# find . -name "*.nupkg" | xargs -n1 dotnet nuget push --api-key=${{ secrets.nuget_key }} --source https://api.nuget.org/v3/index.json --skip-duplicate diff --git a/.github/workflows/pull-request-check.yml b/.github/workflows/pull-request-check.yml index 17d1a4561..9b327e375 100644 --- a/.github/workflows/pull-request-check.yml +++ b/.github/workflows/pull-request-check.yml @@ -1,23 +1,23 @@ -name: Pull Request check -on: - pull_request: - paths-ignore: - - "test/**" - - "generators/**" - - "samples/**" - - "**.md" - - "gencert.sh" - - ".github/**" - - ".gitignore" - - ".gitattributes" - - ".editorconfig" - types: [ opened, edited ] -jobs: - checkPullRequest: - name: Pull Request check - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v3 - - name: Check pull requests - uses: EventStore/Automations/pr-check@master +#name: Pull Request check +#on: +# pull_request: +# paths-ignore: +# - "test/**" +# - "generators/**" +# - "samples/**" +# - "**.md" +# - "gencert.sh" +# - ".github/**" +# - ".gitignore" +# - ".gitattributes" +# - ".editorconfig" +# types: [ opened, edited ] +#jobs: +# checkPullRequest: +# name: Pull Request check +# runs-on: ubuntu-latest +# steps: +# - name: Checkout +# uses: actions/checkout@v3 +# - name: Check pull requests +# uses: EventStore/Automations/pr-check@master diff --git a/Directory.Build.props b/Directory.Build.props index 52c0d73a5..a22d9632a 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,6 +1,6 @@ - net48;net8.0 + net48;net8.0;net9.0 true enable enable @@ -18,4 +18,4 @@ - \ No newline at end of file + diff --git a/EventStore.Client.sln b/EventStore.Client.sln index 373aa58a2..4b4791ec9 100644 --- a/EventStore.Client.sln +++ b/EventStore.Client.sln @@ -9,23 +9,11 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventStore.Client", "src\Ev EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{C51F2C69-45A9-4D0D-A708-4FC319D5D340}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventStore.Client.ProjectionManagement.Tests", "test\EventStore.Client.ProjectionManagement.Tests\EventStore.Client.ProjectionManagement.Tests.csproj", "{8F8548D6-694C-4BAE-9EF3-A020140E04C7}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventStore.Client.Operations.Tests", "test\EventStore.Client.Operations.Tests\EventStore.Client.Operations.Tests.csproj", "{4BA2E05E-6B45-47C3-9001-8B039244ECA9}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventStore.Client.Streams.Tests", "test\EventStore.Client.Streams.Tests\EventStore.Client.Streams.Tests.csproj", "{082C77F5-4FF5-41D4-A1F1-710F05956E1C}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventStore.Client.Tests", "test\EventStore.Client.Tests\EventStore.Client.Tests.csproj", "{FC829F1B-43AD-4C96-9002-23D04BBA3AF3}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventStore.Client.PersistentSubscriptions.Tests", "test\EventStore.Client.PersistentSubscriptions.Tests\EventStore.Client.PersistentSubscriptions.Tests.csproj", "{6CEB731F-72E1-461F-A6B3-54DBF3FD786C}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventStore.Client.UserManagement.Tests", "test\EventStore.Client.UserManagement.Tests\EventStore.Client.UserManagement.Tests.csproj", "{22634CEE-4F7B-4679-A48D-38A2A8580ECA}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventStore.Client.Tests.Common", "test\EventStore.Client.Tests.Common\EventStore.Client.Tests.Common.csproj", "{E326832D-DE52-4DE4-9E54-C800908B75F3}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventStore.Client.Extensions.OpenTelemetry", "src\EventStore.Client.Extensions.OpenTelemetry\EventStore.Client.Extensions.OpenTelemetry.csproj", "{3723933C-585A-49BE-98E8-52D3FAD904CE}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventStore.Client.Plugins.Tests", "test\EventStore.Client.Plugins.Tests\EventStore.Client.Plugins.Tests.csproj", "{7D929D45-F1D9-462B-BE49-84BEC11D5039}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventStore.Client.Extensions.OpenTelemetry", "src\EventStore.Client.Extensions.OpenTelemetry\EventStore.Client.Extensions.OpenTelemetry.csproj", "{F6A7B391-36F1-4838-AD08-E0EE0F2FE57E}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -40,53 +28,23 @@ Global {8853D875-4A8E-450B-A1BE-9CEF8BEDABC3}.Debug|x64.Build.0 = Debug|Any CPU {8853D875-4A8E-450B-A1BE-9CEF8BEDABC3}.Release|x64.ActiveCfg = Release|Any CPU {8853D875-4A8E-450B-A1BE-9CEF8BEDABC3}.Release|x64.Build.0 = Release|Any CPU - {8F8548D6-694C-4BAE-9EF3-A020140E04C7}.Debug|x64.ActiveCfg = Debug|Any CPU - {8F8548D6-694C-4BAE-9EF3-A020140E04C7}.Debug|x64.Build.0 = Debug|Any CPU - {8F8548D6-694C-4BAE-9EF3-A020140E04C7}.Release|x64.ActiveCfg = Release|Any CPU - {8F8548D6-694C-4BAE-9EF3-A020140E04C7}.Release|x64.Build.0 = Release|Any CPU - {4BA2E05E-6B45-47C3-9001-8B039244ECA9}.Debug|x64.ActiveCfg = Debug|Any CPU - {4BA2E05E-6B45-47C3-9001-8B039244ECA9}.Debug|x64.Build.0 = Debug|Any CPU - {4BA2E05E-6B45-47C3-9001-8B039244ECA9}.Release|x64.ActiveCfg = Release|Any CPU - {4BA2E05E-6B45-47C3-9001-8B039244ECA9}.Release|x64.Build.0 = Release|Any CPU - {082C77F5-4FF5-41D4-A1F1-710F05956E1C}.Debug|x64.ActiveCfg = Debug|Any CPU - {082C77F5-4FF5-41D4-A1F1-710F05956E1C}.Debug|x64.Build.0 = Debug|Any CPU - {082C77F5-4FF5-41D4-A1F1-710F05956E1C}.Release|x64.ActiveCfg = Release|Any CPU - {082C77F5-4FF5-41D4-A1F1-710F05956E1C}.Release|x64.Build.0 = Release|Any CPU {FC829F1B-43AD-4C96-9002-23D04BBA3AF3}.Debug|x64.ActiveCfg = Debug|Any CPU {FC829F1B-43AD-4C96-9002-23D04BBA3AF3}.Debug|x64.Build.0 = Debug|Any CPU {FC829F1B-43AD-4C96-9002-23D04BBA3AF3}.Release|x64.ActiveCfg = Release|Any CPU {FC829F1B-43AD-4C96-9002-23D04BBA3AF3}.Release|x64.Build.0 = Release|Any CPU - {6CEB731F-72E1-461F-A6B3-54DBF3FD786C}.Debug|x64.ActiveCfg = Debug|Any CPU - {6CEB731F-72E1-461F-A6B3-54DBF3FD786C}.Debug|x64.Build.0 = Debug|Any CPU - {6CEB731F-72E1-461F-A6B3-54DBF3FD786C}.Release|x64.ActiveCfg = Release|Any CPU - {6CEB731F-72E1-461F-A6B3-54DBF3FD786C}.Release|x64.Build.0 = Release|Any CPU - {22634CEE-4F7B-4679-A48D-38A2A8580ECA}.Debug|x64.ActiveCfg = Debug|Any CPU - {22634CEE-4F7B-4679-A48D-38A2A8580ECA}.Debug|x64.Build.0 = Debug|Any CPU - {22634CEE-4F7B-4679-A48D-38A2A8580ECA}.Release|x64.ActiveCfg = Release|Any CPU - {22634CEE-4F7B-4679-A48D-38A2A8580ECA}.Release|x64.Build.0 = Release|Any CPU {E326832D-DE52-4DE4-9E54-C800908B75F3}.Debug|x64.ActiveCfg = Debug|Any CPU {E326832D-DE52-4DE4-9E54-C800908B75F3}.Debug|x64.Build.0 = Debug|Any CPU {E326832D-DE52-4DE4-9E54-C800908B75F3}.Release|x64.ActiveCfg = Release|Any CPU {E326832D-DE52-4DE4-9E54-C800908B75F3}.Release|x64.Build.0 = Release|Any CPU - {3723933C-585A-49BE-98E8-52D3FAD904CE}.Debug|x64.ActiveCfg = Debug|Any CPU - {3723933C-585A-49BE-98E8-52D3FAD904CE}.Debug|x64.Build.0 = Debug|Any CPU - {3723933C-585A-49BE-98E8-52D3FAD904CE}.Release|x64.ActiveCfg = Release|Any CPU - {3723933C-585A-49BE-98E8-52D3FAD904CE}.Release|x64.Build.0 = Release|Any CPU - {7D929D45-F1D9-462B-BE49-84BEC11D5039}.Debug|x64.ActiveCfg = Debug|Any CPU - {7D929D45-F1D9-462B-BE49-84BEC11D5039}.Debug|x64.Build.0 = Debug|Any CPU - {7D929D45-F1D9-462B-BE49-84BEC11D5039}.Release|x64.ActiveCfg = Release|Any CPU - {7D929D45-F1D9-462B-BE49-84BEC11D5039}.Release|x64.Build.0 = Release|Any CPU + {F6A7B391-36F1-4838-AD08-E0EE0F2FE57E}.Debug|x64.ActiveCfg = Debug|Any CPU + {F6A7B391-36F1-4838-AD08-E0EE0F2FE57E}.Debug|x64.Build.0 = Debug|Any CPU + {F6A7B391-36F1-4838-AD08-E0EE0F2FE57E}.Release|x64.ActiveCfg = Release|Any CPU + {F6A7B391-36F1-4838-AD08-E0EE0F2FE57E}.Release|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {8853D875-4A8E-450B-A1BE-9CEF8BEDABC3} = {EA59C1CB-16DA-4F68-AF8A-642A969B4CF8} - {8F8548D6-694C-4BAE-9EF3-A020140E04C7} = {C51F2C69-45A9-4D0D-A708-4FC319D5D340} - {4BA2E05E-6B45-47C3-9001-8B039244ECA9} = {C51F2C69-45A9-4D0D-A708-4FC319D5D340} - {082C77F5-4FF5-41D4-A1F1-710F05956E1C} = {C51F2C69-45A9-4D0D-A708-4FC319D5D340} {FC829F1B-43AD-4C96-9002-23D04BBA3AF3} = {C51F2C69-45A9-4D0D-A708-4FC319D5D340} - {6CEB731F-72E1-461F-A6B3-54DBF3FD786C} = {C51F2C69-45A9-4D0D-A708-4FC319D5D340} - {22634CEE-4F7B-4679-A48D-38A2A8580ECA} = {C51F2C69-45A9-4D0D-A708-4FC319D5D340} {E326832D-DE52-4DE4-9E54-C800908B75F3} = {C51F2C69-45A9-4D0D-A708-4FC319D5D340} - {3723933C-585A-49BE-98E8-52D3FAD904CE} = {EA59C1CB-16DA-4F68-AF8A-642A969B4CF8} - {7D929D45-F1D9-462B-BE49-84BEC11D5039} = {C51F2C69-45A9-4D0D-A708-4FC319D5D340} + {F6A7B391-36F1-4838-AD08-E0EE0F2FE57E} = {EA59C1CB-16DA-4F68-AF8A-642A969B4CF8} EndGlobalSection EndGlobal diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 15441ca5d..9f5159807 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -4,7 +4,7 @@ true EventStore.Client - Kurrent.Client + EventStore.Client @@ -50,4 +50,4 @@ - \ No newline at end of file + diff --git a/src/EventStore.Client/Core/Certificates/X509Certificates.cs b/src/EventStore.Client/Core/Certificates/X509Certificates.cs index 78efda04e..3fe1006f5 100644 --- a/src/EventStore.Client/Core/Certificates/X509Certificates.cs +++ b/src/EventStore.Client/Core/Certificates/X509Certificates.cs @@ -13,29 +13,36 @@ namespace EventStore.Client; static class X509Certificates { - // TODO SS: Use .NET 8 X509Certificate2.CreateFromPemFile(certPemFilePath, keyPemFilePath) once the Windows32Exception issue is resolved - public static X509Certificate2 CreateFromPemFile(string certPemFilePath, string keyPemFilePath) { - try { - using var publicCert = new X509Certificate2(certPemFilePath); - using var privateKey = RSA.Create().ImportPrivateKeyFromFile(keyPemFilePath); - using var certificate = publicCert.CopyWithPrivateKey(privateKey); - - return new(certificate.Export(X509ContentType.Pfx)); - } - catch (Exception ex) { - throw new CryptographicException($"Failed to load private key: {ex.Message}"); - } - - // Notes: - // using X509Certificate2.CreateFromPemFile(certPemFilePath, keyPemFilePath) would be the ideal choice here, - // but it's currently causing a Win32Exception specifically on Windows. Alternative implementation is used until the issue is resolved. - // - // Error: The SSL connection could not be established, see inner exception. AuthenticationException: Authentication failed because the platform - // does not support ephemeral keys. Win32Exception: No credentials are available in the security package - // - // public static X509Certificate2 CreateFromPemFile(string certPemFilePath, string keyPemFilePath) => - // X509Certificate2.CreateFromPemFile(certPemFilePath, keyPemFilePath); - } + // TODO SS: Use .NET 8 X509Certificate2.CreateFromPemFile(certPemFilePath, keyPemFilePath) once the Windows32Exception issue is resolved + public static X509Certificate2 CreateFromPemFile(string certPemFilePath, string keyPemFilePath) { + try { +#if NET9_0_OR_GREATER + using var publicCert = X509CertificateLoader.LoadCertificateFromFile(certPemFilePath); +#else + using var publicCert = new X509Certificate2(certPemFilePath); +#endif + using var privateKey = RSA.Create().ImportPrivateKeyFromFile(keyPemFilePath); + using var certificate = publicCert.CopyWithPrivateKey(privateKey); + +#if NET48 + return new(certificate.Export(X509ContentType.Pfx)); +#else + return X509Certificate2.CreateFromPemFile(certPemFilePath, keyPemFilePath); +#endif + } catch (Exception ex) { + throw new CryptographicException($"Failed to load private key: {ex.Message}"); + } + + // Notes: + // using X509Certificate2.CreateFromPemFile(certPemFilePath, keyPemFilePath) would be the ideal choice here, + // but it's currently causing a Win32Exception specifically on Windows. Alternative implementation is used until the issue is resolved. + // + // Error: The SSL connection could not be established, see inner exception. AuthenticationException: Authentication failed because the platform + // does not support ephemeral keys. Win32Exception: No credentials are available in the security package + // + // public static X509Certificate2 CreateFromPemFile(string certPemFilePath, string keyPemFilePath) => + // X509Certificate2.CreateFromPemFile(certPemFilePath, keyPemFilePath); + } } public static class RsaExtensions { @@ -59,7 +66,7 @@ public static RSA ImportPrivateKeyFromFile(this RSA rsa, string privateKeyPath) public static RSA ImportPrivateKeyFromFile(this RSA rsa, string privateKeyPath) { var (content, label) = LoadPemKeyFile(privateKeyPath); - var privateKey = string.Join(string.Empty, content[1..^1]); + var privateKey = string.Join(string.Empty, content[1..^1]); var privateKeyBytes = Convert.FromBase64String(privateKey); if (label == RsaPemLabels.Pkcs8PrivateKey) @@ -104,4 +111,4 @@ public static string ParseKeyLabel(string pemFileHeader) { return label; } -} \ No newline at end of file +} diff --git a/src/EventStore.Client/Core/EventStoreClientSettings.ConnectionString.cs b/src/EventStore.Client/Core/EventStoreClientSettings.ConnectionString.cs index 48eb84956..2aadebf64 100644 --- a/src/EventStore.Client/Core/EventStoreClientSettings.ConnectionString.cs +++ b/src/EventStore.Client/Core/EventStoreClientSettings.ConnectionString.cs @@ -41,7 +41,7 @@ private static class ConnectionStringParser { private const string ThrowOnAppendFailure = nameof(ThrowOnAppendFailure); private const string KeepAliveInterval = nameof(KeepAliveInterval); private const string KeepAliveTimeout = nameof(KeepAliveTimeout); - private const string UserCertFile = nameof(UserCertFile); + private const string UserCertFile = nameof(UserCertFile); private const string UserKeyFile = nameof(UserKeyFile); private const string UriSchemeDiscover = "esdb+discover"; @@ -64,8 +64,8 @@ private static class ConnectionStringParser { { ThrowOnAppendFailure, typeof(bool) }, { KeepAliveInterval, typeof(int) }, { KeepAliveTimeout, typeof(int) }, - { UserCertFile, typeof(string)}, - { UserKeyFile, typeof(string)}, + { UserCertFile, typeof(string) }, + { UserKeyFile, typeof(string) }, }; public static EventStoreClientSettings Parse(string connectionString) { @@ -77,10 +77,10 @@ public static EventStoreClientSettings Parse(string connectionString) { var scheme = ParseScheme(connectionString.Substring(0, schemeIndex)); currentIndex = schemeIndex + SchemeSeparator.Length; - var userInfoIndex = connectionString.IndexOf(UserInfoSeparator, currentIndex, StringComparison.Ordinal); - (string user, string pass)? userInfo = null; + var userInfoIndex = connectionString.IndexOf(UserInfoSeparator, currentIndex, StringComparison.Ordinal); + (string user, string pass)? userInfo = null; if (userInfoIndex != -1) { - userInfo = ParseUserInfo(connectionString.Substring(currentIndex, userInfoIndex - currentIndex)); + userInfo = ParseUserInfo(connectionString.Substring(currentIndex, userInfoIndex - currentIndex)); currentIndex = userInfoIndex + UserInfoSeparator.Length; } @@ -93,7 +93,7 @@ public static EventStoreClientSettings Parse(string connectionString) { if (questionMarkIndex == -1) questionMarkIndex = int.MaxValue; var hostSeparatorIndex = Math.Min(Math.Min(slashIndex, questionMarkIndex), endIndex); - var hosts = ParseHosts(connectionString.Substring(currentIndex, hostSeparatorIndex - currentIndex)); + var hosts = ParseHosts(connectionString.Substring(currentIndex, hostSeparatorIndex - currentIndex)); currentIndex = hostSeparatorIndex; string path = ""; @@ -163,11 +163,11 @@ private static EventStoreClientSettings CreateSettings( if (typedOptions.TryGetValue(NodePreference, out object? nodePreference)) { settings.ConnectivitySettings.NodePreference = ((string)nodePreference).ToLowerInvariant() switch { - "leader" => EventStore.Client.NodePreference.Leader, - "follower" => EventStore.Client.NodePreference.Follower, - "random" => EventStore.Client.NodePreference.Random, + "leader" => EventStore.Client.NodePreference.Leader, + "follower" => EventStore.Client.NodePreference.Follower, + "random" => EventStore.Client.NodePreference.Random, "readonlyreplica" => EventStore.Client.NodePreference.ReadOnlyReplica, - _ => throw new InvalidSettingException($"Invalid NodePreference: {nodePreference}") + _ => throw new InvalidSettingException($"Invalid NodePreference: {nodePreference}") }; } @@ -184,17 +184,17 @@ private static EventStoreClientSettings CreateSettings( if (typedOptions.TryGetValue(KeepAliveInterval, out var keepAliveIntervalMs)) { settings.ConnectivitySettings.KeepAliveInterval = keepAliveIntervalMs switch { - -1 => Timeout_.InfiniteTimeSpan, + -1 => Timeout_.InfiniteTimeSpan, int value and >= 0 => TimeSpan.FromMilliseconds(value), - _ => throw new InvalidSettingException($"Invalid KeepAliveInterval: {keepAliveIntervalMs}") + _ => throw new InvalidSettingException($"Invalid KeepAliveInterval: {keepAliveIntervalMs}") }; } if (typedOptions.TryGetValue(KeepAliveTimeout, out var keepAliveTimeoutMs)) { settings.ConnectivitySettings.KeepAliveTimeout = keepAliveTimeoutMs switch { - -1 => Timeout_.InfiniteTimeSpan, + -1 => Timeout_.InfiniteTimeSpan, int value and >= 0 => TimeSpan.FromMilliseconds(value), - _ => throw new InvalidSettingException($"Invalid KeepAliveTimeout: {keepAliveTimeoutMs}") + _ => throw new InvalidSettingException($"Invalid KeepAliveTimeout: {keepAliveTimeoutMs}") }; } @@ -221,7 +221,11 @@ private static EventStoreClientSettings CreateSettings( } try { +#if NET9_0_OR_GREATER + settings.ConnectivitySettings.TlsCaFile = X509CertificateLoader.LoadCertificateFromFile(tlsCaFilePath); +#else settings.ConnectivitySettings.TlsCaFile = new X509Certificate2(tlsCaFilePath); +#endif } catch (CryptographicException) { throw new InvalidClientCertificateException("Failed to load certificate. Invalid file format."); } @@ -239,9 +243,9 @@ HttpMessageHandler CreateDefaultHandler() { return settings.CreateHttpMessageHandler.Invoke(); var handler = new WinHttpHandler { - TcpKeepAliveEnabled = true, - TcpKeepAliveTime = settings.ConnectivitySettings.KeepAliveTimeout, - TcpKeepAliveInterval = settings.ConnectivitySettings.KeepAliveInterval, + TcpKeepAliveEnabled = true, + TcpKeepAliveTime = settings.ConnectivitySettings.KeepAliveTimeout, + TcpKeepAliveInterval = settings.ConnectivitySettings.KeepAliveInterval, EnableMultipleHttp2Connections = true }; @@ -285,7 +289,7 @@ HttpMessageHandler CreateDefaultHandler() { true when settings.ConnectivitySettings.TlsCaFile is not null => (sender, certificate, chain, errors) => { if (certificate is not X509Certificate2 peerCertificate || chain is null) return false; - chain.ChainPolicy.TrustMode = X509ChainTrustMode.CustomRootTrust; + chain.ChainPolicy.TrustMode = X509ChainTrustMode.CustomRootTrust; chain.ChainPolicy.CustomTrustStore.Add(settings.ConnectivitySettings.TlsCaFile); return chain.Build(peerCertificate); }, diff --git a/test/Directory.Build.props b/test/Directory.Build.props index 0d2e0dec9..8c770cca2 100644 --- a/test/Directory.Build.props +++ b/test/Directory.Build.props @@ -27,6 +27,7 @@ + @@ -40,4 +41,4 @@ - \ No newline at end of file + diff --git a/test/EventStore.Client.Operations.Tests/AssemblyInfo.cs b/test/EventStore.Client.Operations.Tests/AssemblyInfo.cs deleted file mode 100644 index b0b47aa73..000000000 --- a/test/EventStore.Client.Operations.Tests/AssemblyInfo.cs +++ /dev/null @@ -1 +0,0 @@ -[assembly: CollectionBehavior(DisableTestParallelization = true)] \ No newline at end of file diff --git a/test/EventStore.Client.Operations.Tests/EventStore.Client.Operations.Tests.csproj b/test/EventStore.Client.Operations.Tests/EventStore.Client.Operations.Tests.csproj deleted file mode 100644 index f80438c6b..000000000 --- a/test/EventStore.Client.Operations.Tests/EventStore.Client.Operations.Tests.csproj +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/test/EventStore.Client.Operations.Tests/ResignNodeTests.cs b/test/EventStore.Client.Operations.Tests/ResignNodeTests.cs deleted file mode 100644 index 6012ae943..000000000 --- a/test/EventStore.Client.Operations.Tests/ResignNodeTests.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace EventStore.Client.Operations.Tests; - -public class ResignNodeTests : IClassFixture { - public ResignNodeTests(ITestOutputHelper output, InsecureClientTestFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - InsecureClientTestFixture Fixture { get; } - - [Fact] - public async Task resign_node_does_not_throw() => - await Fixture.Operations - .ResignNodeAsync(userCredentials: TestCredentials.Root) - .ShouldNotThrowAsync(); - - [Fact] - public async Task resign_node_without_credentials_throws() => - await Fixture.Operations - .ResignNodeAsync() - .ShouldThrowAsync(); -} \ No newline at end of file diff --git a/test/EventStore.Client.Operations.Tests/RestartPersistentSubscriptionsTests.cs b/test/EventStore.Client.Operations.Tests/RestartPersistentSubscriptionsTests.cs deleted file mode 100644 index 1d04d1ca4..000000000 --- a/test/EventStore.Client.Operations.Tests/RestartPersistentSubscriptionsTests.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace EventStore.Client.Operations.Tests; - -public class RestartPersistentSubscriptionsTests : IClassFixture { - public RestartPersistentSubscriptionsTests(ITestOutputHelper output, InsecureClientTestFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - InsecureClientTestFixture Fixture { get; } - - [Fact] - public async Task restart_persistent_subscriptions_does_not_throw() => - await Fixture.Operations - .RestartPersistentSubscriptions(userCredentials: TestCredentials.Root) - .ShouldNotThrowAsync(); - - [Fact] - public async Task restart_persistent_subscriptions_without_credentials_throws() => - await Fixture.Operations - .RestartPersistentSubscriptions() - .ShouldThrowAsync(); -} \ No newline at end of file diff --git a/test/EventStore.Client.Operations.Tests/ShutdownNodeAuthenticationTests.cs b/test/EventStore.Client.Operations.Tests/ShutdownNodeAuthenticationTests.cs deleted file mode 100644 index 4219f616d..000000000 --- a/test/EventStore.Client.Operations.Tests/ShutdownNodeAuthenticationTests.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace EventStore.Client.Operations.Tests; - -public class ShutdownNodeAuthenticationTests : IClassFixture { - public ShutdownNodeAuthenticationTests(ITestOutputHelper output, InsecureClientTestFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - InsecureClientTestFixture Fixture { get; } - - [Fact] - public async Task shutdown_without_credentials_throws() => - await Fixture.Operations.ShutdownAsync().ShouldThrowAsync(); -} \ No newline at end of file diff --git a/test/EventStore.Client.Operations.Tests/ShutdownNodeTests.cs b/test/EventStore.Client.Operations.Tests/ShutdownNodeTests.cs deleted file mode 100644 index 4c73f52fa..000000000 --- a/test/EventStore.Client.Operations.Tests/ShutdownNodeTests.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace EventStore.Client.Operations.Tests; - -public class ShutdownNodeTests : IClassFixture { - public ShutdownNodeTests(ITestOutputHelper output, InsecureClientTestFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - InsecureClientTestFixture Fixture { get; } - - [Fact] - public async Task shutdown_does_not_throw() => - await Fixture.Operations.ShutdownAsync(userCredentials: TestCredentials.Root).ShouldNotThrowAsync(); -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/AssemblyInfo.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/AssemblyInfo.cs deleted file mode 100644 index b0b47aa73..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/AssemblyInfo.cs +++ /dev/null @@ -1 +0,0 @@ -[assembly: CollectionBehavior(DisableTestParallelization = true)] \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/Bugs/Issue_1125.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/Bugs/Issue_1125.cs deleted file mode 100644 index c94429ca3..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/Bugs/Issue_1125.cs +++ /dev/null @@ -1,84 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.Bugs; - -public class Issue_1125 : IClassFixture { - readonly Fixture _fixture; - - public Issue_1125(Fixture fixture) => _fixture = fixture; - - public static IEnumerable TestCases() => Enumerable.Range(0, 50).Select(i => new object[] { i }); - - [Theory] - [MemberData(nameof(TestCases))] - public async Task persistent_subscription_delivers_all_events(int iteration) { - const int eventCount = 250; - const int totalEvents = eventCount * 2; - - var hitCount = 0; - - var userCredentials = new UserCredentials("admin", "changeit"); - - var streamName = $"stream_{iteration}"; - var subscriptionName = $"subscription_{iteration}"; - - for (var i = 0; i < eventCount; i++) - await _fixture.StreamsClient.AppendToStreamAsync( - streamName, - StreamState.Any, - _fixture.CreateTestEvents() - ); - - await _fixture.Client.CreateToStreamAsync( - streamName, - subscriptionName, - new( - true, - StreamPosition.Start, - readBatchSize: 10, - historyBufferSize: 20 - ), - userCredentials: userCredentials - ); - - await using var subscription = - _fixture.Client.SubscribeToStream(streamName, subscriptionName, userCredentials: userCredentials); - - await Task.WhenAll(Subscribe(), Append()).WithTimeout(); - - Assert.Equal(totalEvents, hitCount); - - return; - - async Task Subscribe() { - await foreach (var message in subscription.Messages) { - if (message is not PersistentSubscriptionMessage.Event(var resolvedEvent, var retryCount)) { - continue; - } - - if (retryCount is 0 or null) { - var result = Interlocked.Increment(ref hitCount); - - await subscription.Ack(resolvedEvent); - - if (totalEvents == result) - return; - } else { - // This is a retry - await subscription.Ack(resolvedEvent); - } - } - } - - async Task Append() { - for (var i = 0; i < eventCount; i++) - await _fixture.StreamsClient.AppendToStreamAsync( - streamName, - StreamState.Any, - _fixture.CreateTestEvents()); - } - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/Diagnostics/PersistentSubscriptionsTracingInstrumentationTests.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/Diagnostics/PersistentSubscriptionsTracingInstrumentationTests.cs deleted file mode 100644 index 904f74f70..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/Diagnostics/PersistentSubscriptionsTracingInstrumentationTests.cs +++ /dev/null @@ -1,155 +0,0 @@ -using EventStore.Diagnostics.Tracing; - -namespace EventStore.Client.PersistentSubscriptions.Tests.Diagnostics; - -[Trait("Category", "Diagnostics:Tracing")] -public class PersistentSubscriptionsTracingInstrumentationTests(ITestOutputHelper output, DiagnosticsFixture fixture) - : EventStoreTests(output, fixture) { - [Fact] - public async Task PersistentSubscriptionIsInstrumentedWithTracingAndRestoresRemoteAppendContextAsExpected() { - var stream = Fixture.GetStreamName(); - var events = Fixture.CreateTestEvents(2, metadata: Fixture.CreateTestJsonMetadata()).ToArray(); - - var groupName = $"{stream}-group"; - await Fixture.Subscriptions.CreateToStreamAsync( - stream, - groupName, - new() - ); - - await Fixture.Streams.AppendToStreamAsync( - stream, - StreamState.NoStream, - events - ); - - string? subscriptionId = null; - await Subscribe().WithTimeout(); - - var appendActivity = Fixture - .GetActivitiesForOperation(TracingConstants.Operations.Append, stream) - .SingleOrDefault() - .ShouldNotBeNull(); - - var subscribeActivities = Fixture - .GetActivitiesForOperation(TracingConstants.Operations.Subscribe, stream) - .ToArray(); - - subscriptionId.ShouldNotBeNull(); - subscribeActivities.Length.ShouldBe(events.Length); - - for (var i = 0; i < subscribeActivities.Length; i++) { - subscribeActivities[i].TraceId.ShouldBe(appendActivity.Context.TraceId); - subscribeActivities[i].ParentSpanId.ShouldBe(appendActivity.Context.SpanId); - subscribeActivities[i].HasRemoteParent.ShouldBeTrue(); - - Fixture.AssertSubscriptionActivityHasExpectedTags( - subscribeActivities[i], - stream, - events[i].EventId.ToString(), - subscriptionId - ); - } - - return; - - async Task Subscribe() { - await using var subscription = Fixture.Subscriptions.SubscribeToStream(stream, groupName); - await using var enumerator = subscription.Messages.GetAsyncEnumerator(); - - int eventsAppeared = 0; - while (await enumerator.MoveNextAsync()) { - if (enumerator.Current is PersistentSubscriptionMessage.SubscriptionConfirmation(var sid)) - subscriptionId = sid; - - if (enumerator.Current is not PersistentSubscriptionMessage.Event(_, _)) - continue; - - eventsAppeared++; - if (eventsAppeared >= events.Length) - return; - } - } - } - - [Fact] - public async Task PersistentSubscriptionDoesNotThrowWhenInstrumentedWithTracingAndReceivesNonJsonEvents() { - var stream = Fixture.GetStreamName(); - var events = Fixture.CreateTestEvents( - 2, - metadata: Fixture.CreateTestJsonMetadata(), - contentType: Constants.Metadata.ContentTypes.ApplicationOctetStream - ).ToArray(); - - var groupName = $"{stream}-group"; - await Fixture.Subscriptions.CreateToStreamAsync( - stream, - groupName, - new() - ); - - await Fixture.Streams.AppendToStreamAsync( - stream, - StreamState.NoStream, - events - ); - - await Subscribe().WithTimeout(); - - return; - - async Task Subscribe() { - await using var subscription = Fixture.Subscriptions.SubscribeToStream(stream, groupName); - await using var enumerator = subscription.Messages.GetAsyncEnumerator(); - - var eventsAppeared = 0; - while (await enumerator.MoveNextAsync()) { - if (enumerator.Current is PersistentSubscriptionMessage.Event(_, _)) - eventsAppeared++; - - if (eventsAppeared >= events.Length) - return; - } - } - } - - [Fact] - public async Task PersistentSubscriptionDoesNotThrowWhenInstrumentedWithTracingAndReceivesEventsWithInvalidJsonMetadata() { - var stream = Fixture.GetStreamName(); - var events = Fixture.CreateTestEvents( - 2, - metadata: "clearlynotavalidjsonobject"u8.ToArray() - ).ToArray(); - - var groupName = $"{stream}-group"; - await Fixture.Subscriptions.CreateToStreamAsync( - stream, - groupName, - new() - ); - - await Fixture.Streams.AppendToStreamAsync( - stream, - StreamState.NoStream, - events - ); - - await Subscribe().WithTimeout(); - - return; - - async Task Subscribe() { - await using var subscription = Fixture.Subscriptions.SubscribeToStream(stream, groupName); - await using var enumerator = subscription.Messages.GetAsyncEnumerator(); - - var eventsAppeared = 0; - while (await enumerator.MoveNextAsync()) { - if (enumerator.Current is PersistentSubscriptionMessage.Event(_, _)) - eventsAppeared++; - - if (eventsAppeared >= events.Length) - return; - } - } - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/EventStore.Client.PersistentSubscriptions.Tests.csproj b/test/EventStore.Client.PersistentSubscriptions.Tests/EventStore.Client.PersistentSubscriptions.Tests.csproj deleted file mode 100644 index 0287e82db..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/EventStore.Client.PersistentSubscriptions.Tests.csproj +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/EventStore.Client.PersistentSubscriptions.Tests.csproj.DotSettings b/test/EventStore.Client.PersistentSubscriptions.Tests/EventStore.Client.PersistentSubscriptions.Tests.csproj.DotSettings deleted file mode 100644 index a456beab9..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/EventStore.Client.PersistentSubscriptions.Tests.csproj.DotSettings +++ /dev/null @@ -1,4 +0,0 @@ - - False - False - False \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/EventStoreClientFixture.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/EventStoreClientFixture.cs deleted file mode 100644 index babe29328..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/EventStoreClientFixture.cs +++ /dev/null @@ -1,41 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests; - -public abstract class EventStoreClientFixture : EventStoreClientFixtureBase { - readonly bool _skipPsWarmUp; - - protected EventStoreClientFixture(EventStoreClientSettings? settings = null, bool skipPSWarmUp = false, bool noDefaultCredentials = false) - : base(settings, noDefaultCredentials: noDefaultCredentials) { - _skipPsWarmUp = skipPSWarmUp; - - Client = new(Settings); - StreamsClient = new(Settings); - UserManagementClient = new(Settings); - } - - public EventStorePersistentSubscriptionsClient Client { get; } - public EventStoreClient StreamsClient { get; } - public EventStoreUserManagementClient UserManagementClient { get; } - - protected override async Task OnServerUpAsync() { - await StreamsClient.WarmUp(); - await UserManagementClient.WarmUp(); - - if (!_skipPsWarmUp) - await Client.WarmUp(); - - await UserManagementClient.CreateUserWithRetry( - TestCredentials.TestUser1.Username!, - TestCredentials.TestUser1.Username!, - Array.Empty(), - TestCredentials.TestUser1.Password!, - TestCredentials.Root - ); - } - - public override async Task DisposeAsync() { - await UserManagementClient.DisposeAsync(); - await StreamsClient.DisposeAsync(); - await Client.DisposeAsync(); - await base.DisposeAsync(); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/PersistentSubscriptionSettingsTests.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/PersistentSubscriptionSettingsTests.cs deleted file mode 100644 index de32c4160..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/PersistentSubscriptionSettingsTests.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests; - -public class PersistentSubscriptionSettingsTests { - [Fact] - public void LargeCheckpointAfterThrows() => - Assert.Throws(() => new PersistentSubscriptionSettings(checkPointAfter: TimeSpan.FromDays(25 * 365))); - - [Fact] - public void LargeMessageTimeoutThrows() => - Assert.Throws(() => new PersistentSubscriptionSettings(messageTimeout: TimeSpan.FromDays(25 * 365))); -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_max_one_client_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_max_one_client_obsolete.cs deleted file mode 100644 index 3c39e3598..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_max_one_client_obsolete.cs +++ /dev/null @@ -1,43 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_with_max_one_client_obsolete : IClassFixture { - const string Group = "maxoneclient"; - - readonly Fixture _fixture; - - public connect_to_existing_with_max_one_client_obsolete(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_second_subscription_fails_to_connect() { - using var first = await _fixture.Client.SubscribeToAllAsync( - Group, - delegate { return Task.CompletedTask; }, - userCredentials: TestCredentials.Root - ).WithTimeout(); - - var ex = await Assert.ThrowsAsync( - async () => { - using var _ = await _fixture.Client.SubscribeToAllAsync( - Group, - delegate { return Task.CompletedTask; }, - userCredentials: TestCredentials.Root - ); - } - ).WithTimeout(); - - Assert.Equal(SystemStreams.AllStream, ex.StreamName); - Assert.Equal(Group, ex.GroupName); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => - Client.CreateToAllAsync( - Group, - new(maxSubscriberCount: 1), - userCredentials: TestCredentials.Root - ); - - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_permissions_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_permissions_obsolete.cs deleted file mode 100644 index 890dacf49..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_permissions_obsolete.cs +++ /dev/null @@ -1,37 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_with_permissions_obsolete - : IClassFixture { - const string Group = "connectwithpermissions"; - - readonly Fixture _fixture; - - public connect_to_existing_with_permissions_obsolete(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_subscription_succeeds() { - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - using var subscription = await _fixture.Client.SubscribeToAllAsync( - Group, - delegate { return Task.CompletedTask; }, - (s, reason, ex) => dropped.TrySetResult((reason, ex)), - TestCredentials.Root - ).WithTimeout(); - - Assert.NotNull(subscription); - - await Assert.ThrowsAsync(() => dropped.Task.WithTimeout()); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => - Client.CreateToAllAsync( - Group, - new(), - userCredentials: TestCredentials.Root - ); - - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_beginning_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_beginning_obsolete.cs deleted file mode 100644 index 10b06a965..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_beginning_obsolete.cs +++ /dev/null @@ -1,66 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_with_start_from_beginning_obsolete : IClassFixture { - const string Group = "startfrombeginning"; - - readonly Fixture _fixture; - - public connect_to_existing_with_start_from_beginning_obsolete(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_subscription_gets_event_zero_as_its_first_event() { - var resolvedEvent = await _fixture.FirstEvent.WithTimeout(TimeSpan.FromSeconds(10)); - Assert.Equal(_fixture.Events![0].Event.EventId, resolvedEvent.Event.EventId); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _firstEventSource; - - PersistentSubscription? _subscription; - - public Fixture() => _firstEventSource = new(); - - public ResolvedEvent[]? Events { get; set; } - - public Task FirstEvent => _firstEventSource.Task; - - protected override async Task Given() { - //append 10 events to random streams to make sure we have at least 10 events in the transaction file - foreach (var @event in CreateTestEvents(10)) - await StreamsClient.AppendToStreamAsync(Guid.NewGuid().ToString(), StreamState.NoStream, new[] { @event }); - - Events = await StreamsClient.ReadAllAsync( - Direction.Forwards, - Position.Start, - 10, - userCredentials: TestCredentials.Root - ).ToArrayAsync(); - - await Client.CreateToAllAsync( - Group, - new(startFrom: Position.Start), - userCredentials: TestCredentials.Root - ); - } - - protected override async Task When() => - _subscription = await Client.SubscribeToAllAsync( - Group, - async (subscription, e, r, ct) => { - _firstEventSource.TrySetResult(e); - await subscription.Ack(e); - }, - (subscription, reason, ex) => { - if (reason != SubscriptionDroppedReason.Disposed) - _firstEventSource.TrySetException(ex!); - }, - TestCredentials.Root - ); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_not_set_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_not_set_obsolete.cs deleted file mode 100644 index 5446e1eef..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_not_set_obsolete.cs +++ /dev/null @@ -1,64 +0,0 @@ - -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_with_start_from_not_set_obsolete : IClassFixture { - const string Group = "startfromend1"; - readonly Fixture _fixture; - - public connect_to_existing_with_start_from_not_set_obsolete(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_subscription_gets_no_non_system_events() => - await Assert.ThrowsAsync(() => _fixture.FirstNonSystemEvent.WithTimeout()); - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _firstNonSystemEventSource; - PersistentSubscription? _subscription; - - public Fixture() => _firstNonSystemEventSource = new(); - - public Task FirstNonSystemEvent => _firstNonSystemEventSource.Task; - - protected override async Task Given() { - foreach (var @event in CreateTestEvents(10)) - await StreamsClient.AppendToStreamAsync( - "non-system-stream-" + Guid.NewGuid(), - StreamState.Any, - new[] { - @event - } - ); - - await Client.CreateToAllAsync( - Group, - new(), - userCredentials: TestCredentials.Root - ); - } - - protected override async Task When() => - _subscription = await Client.SubscribeToAllAsync( - Group, - async (subscription, e, r, ct) => { - if (SystemStreams.IsSystemStream(e.OriginalStreamId)) { - await subscription.Ack(e); - return; - } - - _firstNonSystemEventSource.TrySetResult(e); - await subscription.Ack(e); - }, - (subscription, reason, ex) => { - if (reason != SubscriptionDroppedReason.Disposed) - _firstNonSystemEventSource.TrySetException(ex!); - }, - TestCredentials.Root - ); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_not_set_then_event_written_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_not_set_then_event_written_obsolete.cs deleted file mode 100644 index 1ee2b6fae..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_not_set_then_event_written_obsolete.cs +++ /dev/null @@ -1,72 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_with_start_from_not_set_then_event_written_obsolete - : IClassFixture { - const string Group = "startfromnotset2"; - - readonly Fixture _fixture; - - public - connect_to_existing_with_start_from_not_set_then_event_written_obsolete(Fixture fixture) => - _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_subscription_gets_the_written_event_as_its_first_non_system_event2() { - var resolvedEvent = await _fixture.FirstNonSystemEvent.WithTimeout(); - Assert.Equal(_fixture.ExpectedEvent!.EventId, resolvedEvent.Event.EventId); - Assert.Equal(_fixture.ExpectedStreamId, resolvedEvent.Event.EventStreamId); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _firstNonSystemEventSource; - - public readonly EventData? ExpectedEvent; - public readonly string ExpectedStreamId; - - PersistentSubscription? _subscription; - - public Fixture() { - _firstNonSystemEventSource = new(); - ExpectedEvent = CreateTestEvents(1).First(); - ExpectedStreamId = Guid.NewGuid().ToString(); - } - - public Task FirstNonSystemEvent => _firstNonSystemEventSource.Task; - - protected override async Task Given() { - foreach (var @event in CreateTestEvents(10)) - await StreamsClient.AppendToStreamAsync( - "non-system-stream-" + Guid.NewGuid(), - StreamState.Any, - new[] { @event } - ); - - await Client.CreateToAllAsync(Group, new(), userCredentials: TestCredentials.Root); - _subscription = await Client.SubscribeToAllAsync( - Group, - async (subscription, e, r, ct) => { - if (SystemStreams.IsSystemStream(e.OriginalStreamId)) { - await subscription.Ack(e); - return; - } - - _firstNonSystemEventSource.TrySetResult(e); - await subscription.Ack(e); - }, - (subscription, reason, ex) => { - if (reason != SubscriptionDroppedReason.Disposed) - _firstNonSystemEventSource.TrySetException(ex!); - }, - TestCredentials.Root - ); - } - - protected override async Task When() => await StreamsClient.AppendToStreamAsync(ExpectedStreamId, StreamState.NoStream, new[] { ExpectedEvent! }); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_set_to_end_position_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_set_to_end_position_obsolete.cs deleted file mode 100644 index 7057b1489..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_set_to_end_position_obsolete.cs +++ /dev/null @@ -1,63 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_with_start_from_set_to_end_position_obsolete: IClassFixture { - const string Group = "startfromend1"; - - readonly Fixture _fixture; - - public connect_to_existing_with_start_from_set_to_end_position_obsolete(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_subscription_gets_no_non_system_events() => - await Assert.ThrowsAsync(() => _fixture.FirstNonSystemEvent.WithTimeout()); - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _firstNonSystemEventSource; - - PersistentSubscription? _subscription; - - public Fixture() => _firstNonSystemEventSource = new(); - - public Task FirstNonSystemEvent => _firstNonSystemEventSource.Task; - - protected override async Task Given() { - foreach (var @event in CreateTestEvents(10)) - await StreamsClient.AppendToStreamAsync( - "non-system-stream-" + Guid.NewGuid(), - StreamState.Any, - new[] { @event } - ); - - await Client.CreateToAllAsync( - Group, - new(startFrom: Position.End), - userCredentials: TestCredentials.Root - ); - } - - protected override async Task When() => - _subscription = await Client.SubscribeToAllAsync( - Group, - async (subscription, e, r, ct) => { - if (SystemStreams.IsSystemStream(e.OriginalStreamId)) { - await subscription.Ack(e); - return; - } - - _firstNonSystemEventSource.TrySetResult(e); - await subscription.Ack(e); - }, - (subscription, reason, ex) => { - if (reason != SubscriptionDroppedReason.Disposed) - _firstNonSystemEventSource.TrySetException(ex!); - }, - TestCredentials.Root - ); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_set_to_end_position_then_event_written_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_set_to_end_position_then_event_written_obsolete.cs deleted file mode 100644 index 7083cb78f..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_set_to_end_position_then_event_written_obsolete.cs +++ /dev/null @@ -1,69 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class - connect_to_existing_with_start_from_set_to_end_position_then_event_written_obsolete - : IClassFixture { - const string Group = "startfromnotset2"; - - readonly Fixture _fixture; - - public connect_to_existing_with_start_from_set_to_end_position_then_event_written_obsolete(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_subscription_gets_the_written_event_as_its_first_non_system_event() { - var resolvedEvent = await _fixture.FirstNonSystemEvent.WithTimeout(); - Assert.Equal(_fixture.ExpectedEvent.EventId, resolvedEvent.Event.EventId); - Assert.Equal(_fixture.ExpectedStreamId, resolvedEvent.Event.EventStreamId); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _firstNonSystemEventSource; - public readonly EventData ExpectedEvent; - public readonly string ExpectedStreamId; - PersistentSubscription? _subscription; - - public Fixture() { - _firstNonSystemEventSource = new(); - ExpectedEvent = CreateTestEvents(1).First(); - ExpectedStreamId = Guid.NewGuid().ToString(); - } - - public Task FirstNonSystemEvent => _firstNonSystemEventSource.Task; - - protected override async Task Given() { - foreach (var @event in CreateTestEvents(10)) - await StreamsClient.AppendToStreamAsync( - "non-system-stream-" + Guid.NewGuid(), - StreamState.Any, - new[] { @event } - ); - - await Client.CreateToAllAsync(Group, new(startFrom: Position.End), userCredentials: TestCredentials.Root); - _subscription = await Client.SubscribeToAllAsync( - Group, - async (subscription, e, r, ct) => { - if (SystemStreams.IsSystemStream(e.OriginalStreamId)) { - await subscription.Ack(e); - return; - } - - _firstNonSystemEventSource.TrySetResult(e); - await subscription.Ack(e); - }, - (subscription, reason, ex) => { - if (reason != SubscriptionDroppedReason.Disposed) - _firstNonSystemEventSource.TrySetException(ex!); - }, - TestCredentials.Root - ); - } - - protected override async Task When() => await StreamsClient.AppendToStreamAsync(ExpectedStreamId, StreamState.NoStream, new[] { ExpectedEvent }); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_set_to_invalid_middle_position_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_set_to_invalid_middle_position_obsolete.cs deleted file mode 100644 index f1d317b76..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_set_to_invalid_middle_position_obsolete.cs +++ /dev/null @@ -1,49 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_with_start_from_set_to_invalid_middle_position_obsolete - : IClassFixture { - const string Group = "startfrominvalid1"; - readonly Fixture _fixture; - - public connect_to_existing_with_start_from_set_to_invalid_middle_position_obsolete(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_subscription_is_dropped() { - var (reason, exception) = await _fixture.Dropped.WithTimeout(); - Assert.Equal(SubscriptionDroppedReason.ServerError, reason); - Assert.IsType(exception); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource<(SubscriptionDroppedReason, Exception?)> _dropped; - - PersistentSubscription? _subscription; - - public Fixture() => _dropped = new(); - - public Task<(SubscriptionDroppedReason, Exception?)> Dropped => _dropped.Task; - - protected override async Task Given() { - var invalidPosition = new Position(1L, 1L); - await Client.CreateToAllAsync( - Group, - new(startFrom: invalidPosition), - userCredentials: TestCredentials.Root - ); - } - - protected override async Task When() => - _subscription = await Client.SubscribeToAllAsync( - Group, - async (subscription, e, r, ct) => await subscription.Ack(e), - (subscription, reason, ex) => { _dropped.TrySetResult((reason, ex)); }, - TestCredentials.Root - ); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_set_to_valid_middle_position_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_set_to_valid_middle_position_obsolete.cs deleted file mode 100644 index 69230d695..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_set_to_valid_middle_position_obsolete.cs +++ /dev/null @@ -1,65 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_with_start_from_set_to_valid_middle_position_obsolete - : IClassFixture { - const string Group = "startfromvalid"; - - readonly Fixture _fixture; - - public connect_to_existing_with_start_from_set_to_valid_middle_position_obsolete(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_subscription_gets_the_event_at_the_specified_start_position_as_its_first_event() { - var resolvedEvent = await _fixture.FirstEvent.WithTimeout(); - Assert.Equal(_fixture.ExpectedEvent.OriginalPosition, resolvedEvent.Event.Position); - Assert.Equal(_fixture.ExpectedEvent.Event.EventId, resolvedEvent.Event.EventId); - Assert.Equal(_fixture.ExpectedEvent.Event.EventStreamId, resolvedEvent.Event.EventStreamId); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _firstEventSource; - PersistentSubscription? _subscription; - - public Fixture() => _firstEventSource = new(); - - public Task FirstEvent => _firstEventSource.Task; - public ResolvedEvent ExpectedEvent { get; private set; } - - protected override async Task Given() { - var events = await StreamsClient.ReadAllAsync( - Direction.Forwards, - Position.Start, - 10, - userCredentials: TestCredentials.Root - ).ToArrayAsync(); - - ExpectedEvent = events[events.Length / 2]; //just a random event in the middle of the results - - await Client.CreateToAllAsync( - Group, - new(startFrom: ExpectedEvent.OriginalPosition), - userCredentials: TestCredentials.Root - ); - } - - protected override async Task When() => - _subscription = await Client.SubscribeToAllAsync( - Group, - async (subscription, e, r, ct) => { - _firstEventSource.TrySetResult(e); - await subscription.Ack(e); - }, - (subscription, reason, ex) => { - if (reason != SubscriptionDroppedReason.Disposed) - _firstEventSource.TrySetException(ex!); - }, - TestCredentials.Root - ); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_without_permissions_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_without_permissions_obsolete.cs deleted file mode 100644 index b09dbc46a..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_without_permissions_obsolete.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_without_permissions_obsolete - : IClassFixture { - readonly Fixture _fixture; - public connect_to_existing_without_permissions_obsolete(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public Task throws_access_denied() => - Assert.ThrowsAsync( - async () => { - using var _ = await _fixture.Client.SubscribeToAllAsync( - "agroupname55", - delegate { return Task.CompletedTask; } - ); - } - ).WithTimeout(); - - public class Fixture : EventStoreClientFixture { - public Fixture() : base(noDefaultCredentials: true) { } - - protected override Task Given() => - Client.CreateToAllAsync( - "agroupname55", - new(), - userCredentials: TestCredentials.Root - ); - - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_without_read_all_permissions_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_without_read_all_permissions_obsolete.cs deleted file mode 100644 index da6f19f72..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_without_read_all_permissions_obsolete.cs +++ /dev/null @@ -1,33 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_without_read_all_permissions_obsolete - : IClassFixture { - readonly Fixture _fixture; - public connect_to_existing_without_read_all_permissions_obsolete(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public Task throws_access_denied() => - Assert.ThrowsAsync( - async () => { - using var _ = await _fixture.Client.SubscribeToAllAsync( - "agroupname55", - delegate { return Task.CompletedTask; }, - userCredentials: TestCredentials.TestUser1 - ); - } - ).WithTimeout(); - - public class Fixture : EventStoreClientFixture { - public Fixture() : base(noDefaultCredentials: true) { } - - protected override Task Given() => - Client.CreateToAllAsync( - "agroupname55", - new(), - userCredentials: TestCredentials.Root - ); - - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_non_existing_with_permissions_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_non_existing_with_permissions_obsolete.cs deleted file mode 100644 index 5f8c885c1..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_non_existing_with_permissions_obsolete.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_non_existing_with_permissions_obsolete - : IClassFixture { - const string Group = "foo"; - - readonly Fixture _fixture; - - public connect_to_non_existing_with_permissions_obsolete(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task throws_persistent_subscription_not_found() { - var ex = await Assert.ThrowsAsync( - async () => { - using var _ = await _fixture.Client.SubscribeToAllAsync( - Group, - delegate { return Task.CompletedTask; }, - userCredentials: TestCredentials.Root - ); - } - ).WithTimeout(); - - Assert.Equal(SystemStreams.AllStream, ex.StreamName); - Assert.Equal(Group, ex.GroupName); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_with_retries_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_with_retries_obsolete.cs deleted file mode 100644 index 085eecc3e..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_with_retries_obsolete.cs +++ /dev/null @@ -1,59 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_with_retries_obsolete - : IClassFixture { - const string Group = "retries"; - readonly Fixture _fixture; - - public connect_with_retries_obsolete(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task events_are_retried_until_success() => Assert.Equal(5, await _fixture.RetryCount.WithTimeout()); - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _retryCountSource; - PersistentSubscription? _subscription; - - public Fixture() => _retryCountSource = new(); - - public Task RetryCount => _retryCountSource.Task; - - protected override async Task Given() { - await Client.CreateToAllAsync( - Group, - new(startFrom: Position.Start), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToAllAsync( - Group, - async (subscription, e, r, ct) => { - if (r > 4) { - _retryCountSource.TrySetResult(r.Value); - await subscription.Ack(e.Event.EventId); - } - else { - await subscription.Nack( - PersistentSubscriptionNakEventAction.Retry, - "Not yet tried enough times", - e - ); - } - }, - (subscription, reason, ex) => { - if (reason != SubscriptionDroppedReason.Disposed) - _retryCountSource.TrySetException(ex!); - }, - TestCredentials.Root - ); - } - - protected override Task When() => Task.CompletedTask; - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/deleting_existing_with_subscriber_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/deleting_existing_with_subscriber_obsolete.cs deleted file mode 100644 index fdca510d5..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/deleting_existing_with_subscriber_obsolete.cs +++ /dev/null @@ -1,66 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class deleting_existing_with_subscriber_obsolete - : IClassFixture { - readonly Fixture _fixture; - - public deleting_existing_with_subscriber_obsolete(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_subscription_is_dropped() { - var (reason, exception) = await _fixture.Dropped.WithTimeout(); - Assert.Equal(SubscriptionDroppedReason.ServerError, reason); - var ex = Assert.IsType(exception); - - Assert.Equal(SystemStreams.AllStream, ex.StreamName); - Assert.Equal("groupname123", ex.GroupName); - } - - [Fact(Skip = "Isn't this how it should work?")] - public async Task the_subscription_is_dropped_with_not_found() { - var (reason, exception) = await _fixture.Dropped.WithTimeout(); - Assert.Equal(SubscriptionDroppedReason.ServerError, reason); - var ex = Assert.IsType(exception); - Assert.Equal(SystemStreams.AllStream, ex.StreamName); - Assert.Equal("groupname123", ex.GroupName); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource<(SubscriptionDroppedReason, Exception?)> _dropped; - PersistentSubscription? _subscription; - - public Fixture() => _dropped = new(); - - public Task<(SubscriptionDroppedReason, Exception?)> Dropped => _dropped.Task; - - protected override async Task Given() { - await Client.CreateToAllAsync( - "groupname123", - new(), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToAllAsync( - "groupname123", - async (s, e, i, ct) => await s.Ack(e), - (s, r, e) => _dropped.TrySetResult((r, e)), - TestCredentials.Root - ); - - // todo: investigate why this test is flaky without this delay - await Task.Delay(500); - } - - protected override Task When() => - Client.DeleteToAllAsync( - "groupname123", - userCredentials: TestCredentials.Root - ); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/happy_case_catching_up_to_link_to_events_manual_ack_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/happy_case_catching_up_to_link_to_events_manual_ack_obsolete.cs deleted file mode 100644 index cfccd2de2..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/happy_case_catching_up_to_link_to_events_manual_ack_obsolete.cs +++ /dev/null @@ -1,78 +0,0 @@ -using System.Text; - -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class happy_case_catching_up_to_link_to_events_manual_ack_obsolete - : IClassFixture { - const string Group = nameof(Group); - const int BufferCount = 10; - const int EventWriteCount = BufferCount * 2; - - readonly Fixture _fixture; - - public happy_case_catching_up_to_link_to_events_manual_ack_obsolete(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task Test() => await _fixture.EventsReceived.WithTimeout(); - - public class Fixture : EventStoreClientFixture { - readonly EventData[] _events; - readonly TaskCompletionSource _eventsReceived; - int _eventReceivedCount; - - PersistentSubscription? _subscription; - - public Fixture() { - _events = CreateTestEvents(EventWriteCount) - .Select( - (e, i) => new EventData( - e.EventId, - SystemEventTypes.LinkTo, - Encoding.UTF8.GetBytes($"{i}@test"), - contentType: Constants.Metadata.ContentTypes.ApplicationOctetStream - ) - ) - .ToArray(); - - _eventsReceived = new(); - } - - public Task EventsReceived => _eventsReceived.Task; - - protected override async Task Given() { - foreach (var e in _events) - await StreamsClient.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.Any, new[] { e }); - - await Client.CreateToAllAsync( - Group, - new(startFrom: Position.Start, resolveLinkTos: true), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToAllAsync( - Group, - async (subscription, e, retryCount, ct) => { - await subscription.Ack(e); - - if (e.OriginalStreamId.StartsWith("test-") - && Interlocked.Increment(ref _eventReceivedCount) == _events.Length) - _eventsReceived.TrySetResult(true); - }, - (s, r, e) => { - if (e != null) - _eventsReceived.TrySetException(e); - }, - bufferSize: BufferCount, - userCredentials: TestCredentials.Root - ); - } - - protected override Task When() => Task.CompletedTask; - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/happy_case_catching_up_to_normal_events_manual_ack_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/happy_case_catching_up_to_normal_events_manual_ack_obsolete.cs deleted file mode 100644 index cd1f69ee4..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/happy_case_catching_up_to_normal_events_manual_ack_obsolete.cs +++ /dev/null @@ -1,65 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class happy_case_catching_up_to_normal_events_manual_ack_obsolete : IClassFixture { - const string Group = nameof(Group); - const int BufferCount = 10; - const int EventWriteCount = BufferCount * 2; - - readonly Fixture _fixture; - - public happy_case_catching_up_to_normal_events_manual_ack_obsolete(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task Test() => await _fixture.EventsReceived.WithTimeout(); - - public class Fixture : EventStoreClientFixture { - readonly EventData[] _events; - readonly TaskCompletionSource _eventsReceived; - int _eventReceivedCount; - - PersistentSubscription? _subscription; - - public Fixture() { - _events = CreateTestEvents(EventWriteCount).ToArray(); - _eventsReceived = new(); - } - - public Task EventsReceived => _eventsReceived.Task; - - protected override async Task Given() { - foreach (var e in _events) - await StreamsClient.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.Any, new[] { e }); - - await Client.CreateToAllAsync( - Group, - new(startFrom: Position.Start, resolveLinkTos: true), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToAllAsync( - Group, - async (subscription, e, retryCount, ct) => { - await subscription.Ack(e); - - if (e.OriginalStreamId.StartsWith("test-") - && Interlocked.Increment(ref _eventReceivedCount) == _events.Length) - _eventsReceived.TrySetResult(true); - }, - (s, r, e) => { - if (e != null) - _eventsReceived.TrySetException(e); - }, - bufferSize: BufferCount, - userCredentials: TestCredentials.Root - ); - } - - protected override Task When() => Task.CompletedTask; - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/happy_case_filtered_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/happy_case_filtered_obsolete.cs deleted file mode 100644 index f9169733b..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/happy_case_filtered_obsolete.cs +++ /dev/null @@ -1,72 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class happy_case_filtered_obsolete : IClassFixture { - readonly Fixture _fixture; - - public happy_case_filtered_obsolete(Fixture fixture) => _fixture = fixture; - - public static IEnumerable FilterCases() => Filters.All.Select(filter => new object[] { filter }); - - [SupportsPSToAll.Theory] - [MemberData(nameof(FilterCases))] - public async Task reads_all_existing_filtered_events(string filterName) { - var streamPrefix = $"{filterName}-{_fixture.GetStreamName()}"; - var (getFilter, prepareEvent) = Filters.GetFilter(filterName); - var filter = getFilter(streamPrefix); - - var appeared = new TaskCompletionSource(); - var appearedEvents = new List(); - var events = _fixture.CreateTestEvents(20).Select(e => prepareEvent(streamPrefix, e)).ToArray(); - - foreach (var e in events) - await _fixture.StreamsClient.AppendToStreamAsync( - $"{streamPrefix}_{Guid.NewGuid():n}", - StreamState.NoStream, - new[] { e } - ); - - await _fixture.Client.CreateToAllAsync( - filterName, - filter, - new(startFrom: Position.Start), - userCredentials: TestCredentials.Root - ); - - using var subscription = await _fixture.Client.SubscribeToAllAsync( - filterName, - async (s, e, r, ct) => { - appearedEvents.Add(e.Event); - if (appearedEvents.Count >= events.Length) - appeared.TrySetResult(true); - - await s.Ack(e); - }, - userCredentials: TestCredentials.Root - ) - .WithTimeout(); - - await Task.WhenAll(appeared.Task).WithTimeout(); - - Assert.Equal(events.Select(x => x.EventId), appearedEvents.Select(x => x.EventId)); - } - - public class Fixture : EventStoreClientFixture { - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync( - Guid.NewGuid().ToString(), - StreamState.NoStream, - CreateTestEvents(256) - ); - - await StreamsClient.SetStreamMetadataAsync( - SystemStreams.AllStream, - StreamState.Any, - new(acl: new(SystemRoles.All)), - userCredentials: TestCredentials.Root - ); - } - - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/happy_case_filtered_with_start_from_set_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/happy_case_filtered_with_start_from_set_obsolete.cs deleted file mode 100644 index 111ca4e19..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/happy_case_filtered_with_start_from_set_obsolete.cs +++ /dev/null @@ -1,86 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class happy_case_filtered_with_start_from_set_obsolete : IClassFixture { - readonly Fixture _fixture; - - public happy_case_filtered_with_start_from_set_obsolete(Fixture fixture) => _fixture = fixture; - - public static IEnumerable FilterCases() => Filters.All.Select(filter => new object[] { filter }); - - [SupportsPSToAll.Theory] - [MemberData(nameof(FilterCases))] - public async Task reads_all_existing_filtered_events_from_specified_start(string filterName) { - var streamPrefix = $"{filterName}-{_fixture.GetStreamName()}"; - var (getFilter, prepareEvent) = Filters.GetFilter(filterName); - var filter = getFilter(streamPrefix); - - var appeared = new TaskCompletionSource(); - var appearedEvents = new List(); - var events = _fixture.CreateTestEvents(20).Select(e => prepareEvent(streamPrefix, e)).ToArray(); - var eventsToSkip = events.Take(10).ToArray(); - var eventsToCapture = events.Skip(10).ToArray(); - - IWriteResult? eventToCaptureResult = null; - - foreach (var e in eventsToSkip) - await _fixture.StreamsClient.AppendToStreamAsync( - $"{streamPrefix}_{Guid.NewGuid():n}", - StreamState.NoStream, - new[] { e } - ); - - foreach (var e in eventsToCapture) { - var result = await _fixture.StreamsClient.AppendToStreamAsync( - $"{streamPrefix}_{Guid.NewGuid():n}", - StreamState.NoStream, - new[] { e } - ); - - eventToCaptureResult ??= result; - } - - await _fixture.Client.CreateToAllAsync( - filterName, - filter, - new(startFrom: eventToCaptureResult!.LogPosition), - userCredentials: TestCredentials.Root - ); - - using var subscription = await _fixture.Client.SubscribeToAllAsync( - filterName, - async (s, e, r, ct) => { - appearedEvents.Add(e.Event); - if (appearedEvents.Count >= eventsToCapture.Length) - appeared.TrySetResult(true); - - await s.Ack(e); - }, - userCredentials: TestCredentials.Root - ) - .WithTimeout(); - - await Task.WhenAll(appeared.Task).WithTimeout(); - - Assert.Equal(eventsToCapture.Select(x => x.EventId), appearedEvents.Select(x => x.EventId)); - } - - public class Fixture : EventStoreClientFixture { - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync( - Guid.NewGuid().ToString(), - StreamState.NoStream, - CreateTestEvents(256) - ); - - await StreamsClient.SetStreamMetadataAsync( - SystemStreams.AllStream, - StreamState.Any, - new(acl: new(SystemRoles.All)), - userCredentials: TestCredentials.Root - ); - } - - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/happy_case_writing_and_subscribing_to_normal_events_manual_ack_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/happy_case_writing_and_subscribing_to_normal_events_manual_ack_obsolete.cs deleted file mode 100644 index 2563c488d..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/happy_case_writing_and_subscribing_to_normal_events_manual_ack_obsolete.cs +++ /dev/null @@ -1,65 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class happy_case_writing_and_subscribing_to_normal_events_manual_ack_obsolete - : IClassFixture { - const string Group = nameof(Group); - const int BufferCount = 10; - const int EventWriteCount = BufferCount * 2; - - readonly Fixture _fixture; - - public happy_case_writing_and_subscribing_to_normal_events_manual_ack_obsolete(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task Test() => await _fixture.EventsReceived.WithTimeout(); - - public class Fixture : EventStoreClientFixture { - readonly EventData[] _events; - readonly TaskCompletionSource _eventsReceived; - int _eventReceivedCount; - - PersistentSubscription? _subscription; - - public Fixture() { - _events = CreateTestEvents(EventWriteCount).ToArray(); - _eventsReceived = new(); - } - - public Task EventsReceived => _eventsReceived.Task; - - protected override async Task Given() { - await Client.CreateToAllAsync( - Group, - new(startFrom: Position.End, resolveLinkTos: true), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToAllAsync( - Group, - async (subscription, e, retryCount, ct) => { - await subscription.Ack(e); - if (e.OriginalStreamId.StartsWith("test-") - && Interlocked.Increment(ref _eventReceivedCount) == _events.Length) - _eventsReceived.TrySetResult(true); - }, - (s, r, e) => { - if (e != null) - _eventsReceived.TrySetException(e); - }, - bufferSize: BufferCount, - userCredentials: TestCredentials.Root - ); - } - - protected override async Task When() { - foreach (var e in _events) - await StreamsClient.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.Any, new[] { e }); - } - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/update_existing_with_check_point_filtered_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/update_existing_with_check_point_filtered_obsolete.cs deleted file mode 100644 index 0e9e2be21..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/update_existing_with_check_point_filtered_obsolete.cs +++ /dev/null @@ -1,120 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class update_existing_with_check_point_filtered_obsolete - : IClassFixture { - const string Group = "existing-with-check-point-filtered"; - - readonly Fixture _fixture; - - public update_existing_with_check_point_filtered_obsolete(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task resumes_from_check_point() { - var resumedEvent = await _fixture.Resumed.WithTimeout(TimeSpan.FromSeconds(10)); - Assert.True(resumedEvent.Event.Position > _fixture.CheckPoint); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _appeared; - readonly List _appearedEvents; - readonly TaskCompletionSource<(SubscriptionDroppedReason, Exception?)> _droppedSource; - readonly EventData[] _events; - readonly TaskCompletionSource _resumedSource; - - PersistentSubscription? _firstSubscription; - PersistentSubscription? _secondSubscription; - - public Fixture() { - _droppedSource = new(); - _resumedSource = new(); - _appeared = new(); - _appearedEvents = new(); - _events = CreateTestEvents(5).ToArray(); - } - - public Task Resumed => _resumedSource.Task; - - public Position CheckPoint { get; private set; } - - protected override async Task Given() { - foreach (var e in _events) - await StreamsClient.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.NoStream, new[] { e }); - - await Client.CreateToAllAsync( - Group, - StreamFilter.Prefix("test"), - new( - checkPointLowerBound: 5, - checkPointAfter: TimeSpan.FromSeconds(1), - startFrom: Position.Start - ), - userCredentials: TestCredentials.Root - ); - - _firstSubscription = await Client.SubscribeToAllAsync( - Group, - async (s, e, r, ct) => { - _appearedEvents.Add(e); - - if (_appearedEvents.Count == _events.Length) - _appeared.TrySetResult(true); - - await s.Ack(e); - }, - (subscription, reason, ex) => _droppedSource.TrySetResult((reason, ex)), - TestCredentials.Root - ); - - await Task.WhenAll(_appeared.Task, Checkpointed()).WithTimeout(); - - return; - - async Task Checkpointed() { - await using var subscription = StreamsClient.SubscribeToStream( - $"$persistentsubscription-$all::{Group}-checkpoint", - FromStream.Start, - userCredentials: TestCredentials.Root); - await foreach (var message in subscription.Messages) { - if (message is not StreamMessage.Event(var resolvedEvent)) { - continue; - } - CheckPoint = resolvedEvent.Event.Data.ParsePosition(); - return; - } - } - } - - protected override async Task When() { - // Force restart of the subscription - await Client.UpdateToAllAsync(Group, new(), userCredentials: TestCredentials.Root); - - await _droppedSource.Task.WithTimeout(); - - _secondSubscription = await Client.SubscribeToAllAsync( - Group, - async (s, e, r, ct) => { - _resumedSource.TrySetResult(e); - await s.Ack(e); - s.Dispose(); - }, - (_, reason, ex) => { - if (ex is not null) - _resumedSource.TrySetException(ex); - else - _resumedSource.TrySetResult(default); - }, - TestCredentials.Root - ); - - foreach (var e in _events) - await StreamsClient.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.NoStream, new[] { e }); - } - - public override Task DisposeAsync() { - _firstSubscription?.Dispose(); - _secondSubscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/update_existing_with_subscribers_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/update_existing_with_subscribers_obsolete.cs deleted file mode 100644 index 17a77063c..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/update_existing_with_subscribers_obsolete.cs +++ /dev/null @@ -1,60 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class update_existing_with_subscribers_obsolete - : IClassFixture { - const string Group = "existing"; - - readonly Fixture _fixture; - - public update_existing_with_subscribers_obsolete(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task existing_subscriptions_are_dropped() { - var (reason, exception) = await _fixture.Dropped.WithTimeout(TimeSpan.FromSeconds(10)); - Assert.Equal(SubscriptionDroppedReason.ServerError, reason); - var ex = Assert.IsType(exception); - - Assert.Equal(SystemStreams.AllStream, ex.StreamName); - Assert.Equal(Group, ex.GroupName); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource<(SubscriptionDroppedReason, Exception?)> _droppedSource; - PersistentSubscription? _subscription; - - public Fixture() => _droppedSource = new(); - - public Task<(SubscriptionDroppedReason, Exception?)> Dropped => _droppedSource.Task; - - protected override async Task Given() { - await Client.CreateToAllAsync( - Group, - new(), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToAllAsync( - Group, - delegate { return Task.CompletedTask; }, - (subscription, reason, ex) => _droppedSource.TrySetResult((reason, ex)), - TestCredentials.Root - ); - - // todo: investigate why this test is flaky without this delay - await Task.Delay(500); - } - - protected override Task When() => - Client.UpdateToAllAsync( - Group, - new(), - userCredentials: TestCredentials.Root - ); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/when_writing_and_filtering_out_events_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/when_writing_and_filtering_out_events_obsolete.cs deleted file mode 100644 index 302ac221a..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/when_writing_and_filtering_out_events_obsolete.cs +++ /dev/null @@ -1,108 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class when_writing_and_filtering_out_events_obsolete - : IClassFixture { - const string Group = "filtering-out-events"; - - readonly Fixture _fixture; - - public when_writing_and_filtering_out_events_obsolete(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task it_should_write_a_check_point() { - await Task.Yield(); - Assert.True(_fixture.SecondCheckPoint > _fixture.FirstCheckPoint); - Assert.Equal( - _fixture.Events.Select(e => e.EventId), - _fixture.AppearedEvents.Select(e => e.Event.EventId) - ); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _appeared; - readonly List _appearedEvents, _checkPoints; - readonly EventData[] _events; - - PersistentSubscription? _subscription; - - public Fixture() { - _appeared = new(); - _appearedEvents = new(); - _checkPoints = new(); - _events = CreateTestEvents(10).ToArray(); - } - - public Position SecondCheckPoint { get; private set; } - public Position FirstCheckPoint { get; private set; } - public EventData[] Events => _events.ToArray(); - public ResolvedEvent[] AppearedEvents => _appearedEvents.ToArray(); - - protected override async Task Given() { - foreach (var e in _events) - await StreamsClient.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.Any, new[] { e }); - - await Client.CreateToAllAsync( - Group, - StreamFilter.Prefix("test"), - new( - checkPointLowerBound: 1, - checkPointUpperBound: 5, - checkPointAfter: TimeSpan.FromSeconds(1), - startFrom: Position.Start - ), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToAllAsync( - Group, - async (s, e, r, ct) => { - _appearedEvents.Add(e); - - if (_appearedEvents.Count == _events.Length) - _appeared.TrySetResult(true); - - await s.Ack(e); - }, - userCredentials: TestCredentials.Root - ); - - await Task.WhenAll(_appeared.Task, Checkpointed()).WithTimeout(); - - async Task Checkpointed() { - bool firstCheckpointSet = false; - await using var subscription = StreamsClient.SubscribeToStream( - $"$persistentsubscription-$all::{Group}-checkpoint", - FromStream.Start, - userCredentials: TestCredentials.Root); - await foreach (var message in subscription.Messages) { - if (message is not StreamMessage.Event(var resolvedEvent)) { - continue; - } - - if (!firstCheckpointSet) { - FirstCheckPoint = resolvedEvent.Event.Data.ParsePosition(); - firstCheckpointSet = true; - } else { - SecondCheckPoint = resolvedEvent.Event.Data.ParsePosition(); - return; - } - } - } - } - - protected override async Task When() { - foreach (var e in _events) - await StreamsClient.AppendToStreamAsync( - "filtered-out-stream-" + Guid.NewGuid(), - StreamState.Any, - new[] { e } - ); - } - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/when_writing_and_subscribing_to_normal_events_manual_nack_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/when_writing_and_subscribing_to_normal_events_manual_nack_obsolete.cs deleted file mode 100644 index f18d6ad96..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/when_writing_and_subscribing_to_normal_events_manual_nack_obsolete.cs +++ /dev/null @@ -1,68 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class when_writing_and_subscribing_to_normal_events_manual_nack_obsolete - : IClassFixture { - const string Group = nameof(Group); - const int BufferCount = 10; - const int EventWriteCount = BufferCount * 2; - - readonly Fixture _fixture; - - public when_writing_and_subscribing_to_normal_events_manual_nack_obsolete(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task Test() => await _fixture.EventsReceived.WithTimeout(); - - public class Fixture : EventStoreClientFixture { - readonly EventData[] _events; - readonly TaskCompletionSource _eventsReceived; - int _eventReceivedCount; - - PersistentSubscription? _subscription; - - public Fixture() { - _events = CreateTestEvents(EventWriteCount) - .ToArray(); - - _eventsReceived = new(); - } - - public Task EventsReceived => _eventsReceived.Task; - - protected override async Task Given() { - await Client.CreateToAllAsync( - Group, - new(startFrom: Position.Start, resolveLinkTos: true), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToAllAsync( - Group, - async (subscription, e, retryCount, ct) => { - await subscription.Nack(PersistentSubscriptionNakEventAction.Park, "fail", e); - - if (e.OriginalStreamId.StartsWith("test-") - && Interlocked.Increment(ref _eventReceivedCount) == _events.Length) - _eventsReceived.TrySetResult(true); - }, - (s, r, e) => { - if (e != null) - _eventsReceived.TrySetException(e); - }, - bufferSize: BufferCount, - userCredentials: TestCredentials.Root - ); - } - - protected override async Task When() { - foreach (var e in _events) - await StreamsClient.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.Any, new[] { e }); - } - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/can_create_duplicate_name_on_different_streams.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/can_create_duplicate_name_on_different_streams.cs deleted file mode 100644 index d23e7c911..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/can_create_duplicate_name_on_different_streams.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class can_create_duplicate_name_on_different_streams : IClassFixture { - readonly Fixture _fixture; - - public can_create_duplicate_name_on_different_streams(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public Task the_completion_succeeds() => - _fixture.Client.CreateToStreamAsync("someother", "group3211", new(), userCredentials: TestCredentials.Root); - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - - protected override Task When() => - Client.CreateToAllAsync( - "group3211", - new(), - userCredentials: TestCredentials.Root - ); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_max_one_client.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_max_one_client.cs deleted file mode 100644 index db2818abf..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_max_one_client.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class connect_to_existing_with_max_one_client : IClassFixture { - private const string Group = "maxoneclient"; - - private readonly Fixture _fixture; - - public connect_to_existing_with_max_one_client(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_second_subscription_fails_to_connect2() { - var ex = await Assert.ThrowsAsync( - () => Task.WhenAll(Subscribe().WithTimeout(), Subscribe().WithTimeout())); - - Assert.Equal(SystemStreams.AllStream, ex.StreamName); - Assert.Equal(Group, ex.GroupName); - return; - - async Task Subscribe() { - await using var subscription = _fixture.Client.SubscribeToAll(Group, userCredentials: TestCredentials.Root); - await subscription.Messages.AnyAsync(); - } - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => - Client.CreateToAllAsync(Group, new(maxSubscriberCount: 1), userCredentials: TestCredentials.Root); - - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_permissions.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_permissions.cs deleted file mode 100644 index e10ed9909..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_permissions.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class connect_to_existing_with_permissions : IClassFixture { - private const string Group = "connectwithpermissions"; - private readonly Fixture _fixture; - - public connect_to_existing_with_permissions(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_subscription_succeeds() { - await using var subscription = - _fixture.Client.SubscribeToAll(Group, userCredentials: TestCredentials.Root); - - Assert.True(await subscription.Messages - .FirstAsync().AsTask().WithTimeout() is PersistentSubscriptionMessage.SubscriptionConfirmation); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Client.CreateToAllAsync(Group, new(), userCredentials: TestCredentials.Root); - - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_beginning.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_beginning.cs deleted file mode 100644 index 47e36c620..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_beginning.cs +++ /dev/null @@ -1,52 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class connect_to_existing_with_start_from_beginning - : IClassFixture { - private const string Group = "startfrombeginning"; - private readonly Fixture _fixture; - - public connect_to_existing_with_start_from_beginning(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_subscription_gets_event_zero_as_its_first_event() { - var resolvedEvent = await _fixture.Subscription!.Messages.OfType() - .Select(e => e.ResolvedEvent) - .FirstOrDefaultAsync().AsTask().WithTimeout(); - - Assert.Equal(_fixture.Events[0].Event.EventId, resolvedEvent.Event.EventId); - } - - public class Fixture : EventStoreClientFixture { - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public ResolvedEvent[] Events { get; private set; } = Array.Empty(); - - protected override async Task Given() { - //append 10 events to random streams to make sure we have at least 10 events in the transaction file - foreach (var @event in CreateTestEvents(10)) { - await StreamsClient.AppendToStreamAsync(Guid.NewGuid().ToString(), StreamState.NoStream, - new[] { @event }); - } - - Events = await StreamsClient - .ReadAllAsync(Direction.Forwards, Position.Start, 10, userCredentials: TestCredentials.Root) - .ToArrayAsync(); - - await Client.CreateToAllAsync(Group, new(startFrom: Position.Start), userCredentials: TestCredentials.Root); - } - - protected override Task When() { - Subscription = Client.SubscribeToAll(Group, userCredentials: TestCredentials.Root); - - return Task.CompletedTask; - } - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_not_set.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_not_set.cs deleted file mode 100644 index 17a28d1d6..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_not_set.cs +++ /dev/null @@ -1,44 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class connect_to_existing_with_start_from_not_set - : IClassFixture { - private const string Group = "startfromend1"; - private readonly Fixture _fixture; - - public connect_to_existing_with_start_from_not_set(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_subscription_gets_no_non_system_events() { - await Assert.ThrowsAsync(() => _fixture.Subscription!.Messages - .OfType() - .Where(e => !SystemStreams.IsSystemStream(e.ResolvedEvent.OriginalStreamId)) - .AnyAsync() - .AsTask() - .WithTimeout(TimeSpan.FromMilliseconds(250))); - } - - public class Fixture : EventStoreClientFixture { - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - protected override async Task Given() { - foreach (var @event in CreateTestEvents(10)) - await StreamsClient.AppendToStreamAsync("non-system-stream-" + Guid.NewGuid(), StreamState.Any, - new[] { @event }); - - await Client.CreateToAllAsync(Group, new(), userCredentials: TestCredentials.Root); - } - - protected override Task When() { - Subscription = Client.SubscribeToAll(Group, userCredentials: TestCredentials.Root); - return Task.CompletedTask; - } - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_not_set_then_event_written.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_not_set_then_event_written.cs deleted file mode 100644 index bbd8ef16e..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_not_set_then_event_written.cs +++ /dev/null @@ -1,54 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class connect_to_existing_with_start_from_not_set_then_event_written - : IClassFixture { - private const string Group = "startfromnotset2"; - - private readonly Fixture _fixture; - - public connect_to_existing_with_start_from_not_set_then_event_written(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_subscription_gets_the_written_event_as_its_first_non_system_event() { - var resolvedEvent = await _fixture.Subscription!.Messages.OfType() - .Select(e => e.ResolvedEvent) - .Where(resolvedEvent => !SystemStreams.IsSystemStream(resolvedEvent.OriginalStreamId)) - .FirstOrDefaultAsync().AsTask().WithTimeout(); - - Assert.Equal(_fixture.ExpectedEvent.EventId, resolvedEvent.Event.EventId); - Assert.Equal(_fixture.ExpectedStreamId, resolvedEvent.Event.EventStreamId); - } - - public class Fixture : EventStoreClientFixture { - public readonly EventData ExpectedEvent; - public readonly string ExpectedStreamId; - - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - ExpectedEvent = CreateTestEvents(1).First(); - ExpectedStreamId = Guid.NewGuid().ToString(); - } - - protected override async Task Given() { - foreach (var @event in CreateTestEvents(10)) { - await StreamsClient.AppendToStreamAsync("non-system-stream-" + Guid.NewGuid(), StreamState.Any, - new[] { @event }); - } - - await Client.CreateToAllAsync(Group, new(), userCredentials: TestCredentials.Root); - Subscription = Client.SubscribeToAll(Group, userCredentials: TestCredentials.Root); - } - - protected override async Task When() => - await StreamsClient.AppendToStreamAsync(ExpectedStreamId, StreamState.NoStream, new[] { ExpectedEvent }); - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_set_to_end_position.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_set_to_end_position.cs deleted file mode 100644 index e7f3c9913..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_set_to_end_position.cs +++ /dev/null @@ -1,46 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class connect_to_existing_with_start_from_set_to_end_position - : IClassFixture { - private const string Group = "startfromend1"; - - private readonly Fixture _fixture; - - public connect_to_existing_with_start_from_set_to_end_position(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_subscription_gets_no_non_system_events() { - await Assert.ThrowsAsync(() => _fixture.Subscription!.Messages - .OfType() - .Where(e => !SystemStreams.IsSystemStream(e.ResolvedEvent.OriginalStreamId)) - .AnyAsync() - .AsTask() - .WithTimeout(TimeSpan.FromMilliseconds(250))); - } - - public class Fixture : EventStoreClientFixture { - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - protected override async Task Given() { - foreach (var @event in CreateTestEvents(10)) { - await StreamsClient.AppendToStreamAsync("non-system-stream-" + Guid.NewGuid(), StreamState.Any, - new[] { @event }); - } - - await Client.CreateToAllAsync(Group, new(startFrom: Position.End), userCredentials: TestCredentials.Root); - } - - protected override Task When() { - Subscription = Client.SubscribeToAll(Group, userCredentials: TestCredentials.Root); - return Task.CompletedTask; - } - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_set_to_end_position_then_event_written.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_set_to_end_position_then_event_written.cs deleted file mode 100644 index 835c8538c..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_set_to_end_position_then_event_written.cs +++ /dev/null @@ -1,56 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class - connect_to_existing_with_start_from_set_to_end_position_then_event_written - : IClassFixture { - private const string Group = "startfromnotset2"; - private readonly Fixture _fixture; - - public connect_to_existing_with_start_from_set_to_end_position_then_event_written(Fixture fixture) => - _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_subscription_gets_the_written_event_as_its_first_non_system_event() { - var resolvedEvent = await _fixture.Subscription!.Messages - .OfType() - .Select(e => e.ResolvedEvent) - .Where(resolvedEvent => !SystemStreams.IsSystemStream(resolvedEvent.OriginalStreamId)) - .FirstAsync() - .AsTask() - .WithTimeout(); - Assert.Equal(_fixture.ExpectedEvent.EventId, resolvedEvent.Event.EventId); - Assert.Equal(_fixture.ExpectedStreamId, resolvedEvent.Event.EventStreamId); - } - - public class Fixture : EventStoreClientFixture { - public readonly EventData ExpectedEvent; - public readonly string ExpectedStreamId; - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - ExpectedEvent = CreateTestEvents(1).First(); - ExpectedStreamId = Guid.NewGuid().ToString(); - } - - protected override async Task Given() { - foreach (var @event in CreateTestEvents(10)) { - await StreamsClient.AppendToStreamAsync("non-system-stream-" + Guid.NewGuid(), StreamState.Any, - new[] { @event }); - } - - await Client.CreateToAllAsync(Group, new(startFrom: Position.End), userCredentials: TestCredentials.Root); - Subscription = Client.SubscribeToAll(Group, userCredentials: TestCredentials.Root); - } - - protected override async Task When() => - await StreamsClient.AppendToStreamAsync(ExpectedStreamId, StreamState.NoStream, new[] { ExpectedEvent }); - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_set_to_invalid_middle_position.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_set_to_invalid_middle_position.cs deleted file mode 100644 index b45330a9e..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_set_to_invalid_middle_position.cs +++ /dev/null @@ -1,48 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class connect_to_existing_with_start_from_set_to_invalid_middle_position - : IClassFixture { - private const string Group = "startfrominvalid1"; - private readonly Fixture _fixture; - - public connect_to_existing_with_start_from_set_to_invalid_middle_position(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_subscription_is_dropped() { - var ex = await Assert.ThrowsAsync(async () => - await _fixture.Enumerator!.MoveNextAsync()); - - Assert.Equal(SystemStreams.AllStream, ex.StreamName); - Assert.Equal(Group, ex.GroupName); - } - - public class Fixture : EventStoreClientFixture { - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - public IAsyncEnumerator? Enumerator { get; private set; } - - protected override async Task Given() { - var invalidPosition = new Position(1L, 1L); - await Client.CreateToAllAsync(Group, new(startFrom: invalidPosition), - userCredentials: TestCredentials.Root); - } - - protected override async Task When() { - Subscription = Client.SubscribeToAll(Group, userCredentials: TestCredentials.Root); - Enumerator = Subscription.Messages.GetAsyncEnumerator(); - - await Enumerator.MoveNextAsync(); - } - - public override async Task DisposeAsync() { - if (Enumerator is not null) { - await Enumerator.DisposeAsync(); - } - - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_set_to_valid_middle_position.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_set_to_valid_middle_position.cs deleted file mode 100644 index daaf838a9..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_set_to_valid_middle_position.cs +++ /dev/null @@ -1,51 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class connect_to_existing_with_start_from_set_to_valid_middle_position - : IClassFixture { - private const string Group = "startfromvalid"; - - private readonly Fixture _fixture; - - public connect_to_existing_with_start_from_set_to_valid_middle_position(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_subscription_gets_the_event_at_the_specified_start_position_as_its_first_event() { - var resolvedEvent = await _fixture.Subscription!.Messages.OfType() - .Select(e => e.ResolvedEvent) - .FirstAsync() - .AsTask() - .WithTimeout(); - Assert.Equal(_fixture.ExpectedEvent.OriginalPosition, resolvedEvent.Event.Position); - Assert.Equal(_fixture.ExpectedEvent.Event.EventId, resolvedEvent.Event.EventId); - Assert.Equal(_fixture.ExpectedEvent.Event.EventStreamId, resolvedEvent.Event.EventStreamId); - } - - public class Fixture : EventStoreClientFixture { - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - public ResolvedEvent ExpectedEvent { get; private set; } - - protected override async Task Given() { - var events = await StreamsClient - .ReadAllAsync(Direction.Forwards, Position.Start, 10, userCredentials: TestCredentials.Root) - .ToArrayAsync(); - - ExpectedEvent = events[events.Length / 2]; //just a random event in the middle of the results - - await Client.CreateToAllAsync(Group, new(startFrom: ExpectedEvent.OriginalPosition), - userCredentials: TestCredentials.Root); - } - - protected override Task When() { - Subscription = Client.SubscribeToAll(Group, userCredentials: TestCredentials.Root); - return Task.CompletedTask; - } - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_without_permissions.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_without_permissions.cs deleted file mode 100644 index 865281ec0..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_without_permissions.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class connect_to_existing_without_permissions : IClassFixture { - private readonly Fixture _fixture; - public connect_to_existing_without_permissions(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public Task throws_access_denied() => - Assert.ThrowsAsync( - async () => { - await using var subscription = _fixture.Client.SubscribeToAll("agroupname55"); - await subscription.AnyAsync().AsTask().WithTimeout(); - }); - - public class Fixture : EventStoreClientFixture { - public Fixture() : base(noDefaultCredentials: true) { } - - protected override Task Given() => - Client.CreateToAllAsync("agroupname55", new(), userCredentials: TestCredentials.Root); - - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_without_read_all_permissions.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_without_read_all_permissions.cs deleted file mode 100644 index 56eccd0fe..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_without_read_all_permissions.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class connect_to_existing_without_read_all_permissions - : IClassFixture { - private readonly Fixture _fixture; - public connect_to_existing_without_read_all_permissions(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public Task throws_access_denied() => - Assert.ThrowsAsync( - async () => { - await using var subscription = - _fixture.Client.SubscribeToAll("agroupname55", userCredentials: TestCredentials.TestUser1); - await subscription.Messages.AnyAsync().AsTask().WithTimeout(); - }); - - public class Fixture : EventStoreClientFixture { - public Fixture() : base(noDefaultCredentials: true) { } - - protected override Task Given() => - Client.CreateToAllAsync("agroupname55", new(), userCredentials: TestCredentials.Root); - - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_non_existing_with_permissions.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_non_existing_with_permissions.cs deleted file mode 100644 index 40a541040..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_non_existing_with_permissions.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class connect_to_non_existing_with_permissions - : IClassFixture { - private const string Group = "foo"; - - private readonly Fixture _fixture; - - public connect_to_non_existing_with_permissions(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task throws_persistent_subscription_not_found() { - await using var subscription = _fixture.Client.SubscribeToAll(Group, userCredentials: TestCredentials.Root); - - Assert.True(await subscription.Messages.OfType().AnyAsync() - .AsTask() - .WithTimeout()); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_with_retries.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_with_retries.cs deleted file mode 100644 index ea4236278..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_with_retries.cs +++ /dev/null @@ -1,49 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class connect_with_retries : IClassFixture { - private const string Group = "retries"; - private readonly Fixture _fixture; - - public connect_with_retries(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task events_are_retried_until_success() { - var retryCount = await _fixture.Subscription!.Messages.OfType() - .SelectAwait(async e => { - if (e.RetryCount > 4) { - await _fixture.Subscription.Ack(e.ResolvedEvent); - } else { - await _fixture.Subscription.Nack(PersistentSubscriptionNakEventAction.Retry, - "Not yet tried enough times", e.ResolvedEvent); - } - - return e.RetryCount; - }) - .Where(retryCount => retryCount > 4) - .FirstOrDefaultAsync() - .AsTask() - .WithTimeout(); - - Assert.Equal(5, retryCount); - } - - public class Fixture : EventStoreClientFixture { - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - protected override async Task Given() { - await Client.CreateToAllAsync(Group, new(startFrom: Position.Start), userCredentials: TestCredentials.Root); - - Subscription = Client.SubscribeToAll(Group, userCredentials: TestCredentials.Root); - } - - protected override Task When() => Task.CompletedTask; - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_after_deleting_the_same.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_after_deleting_the_same.cs deleted file mode 100644 index a3c673f48..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_after_deleting_the_same.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class create_after_deleting_the_same : IClassFixture { - readonly Fixture _fixture; - - public create_after_deleting_the_same(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_completion_succeeds() => - await _fixture.Client.CreateToAllAsync( - "existing", - new(), - userCredentials: TestCredentials.Root - ); - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - - protected override async Task When() { - await Client.CreateToAllAsync( - "existing", - new(), - userCredentials: TestCredentials.Root - ); - - await Client.DeleteToAllAsync( - "existing", - userCredentials: TestCredentials.Root - ); - } - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_duplicate.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_duplicate.cs deleted file mode 100644 index abe410c26..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_duplicate.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Grpc.Core; - -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class create_duplicate : IClassFixture { - readonly Fixture _fixture; - - public create_duplicate(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_completion_fails() { - var ex = await Assert.ThrowsAsync( - () => _fixture.Client.CreateToAllAsync( - "group32", - new(), - userCredentials: TestCredentials.Root - ) - ); - - Assert.Equal(StatusCode.AlreadyExists, ex.StatusCode); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - - protected override Task When() => - Client.CreateToAllAsync( - "group32", - new(), - userCredentials: TestCredentials.Root - ); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_filtered.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_filtered.cs deleted file mode 100644 index 8eff2a425..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_filtered.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class create_filtered : IClassFixture { - readonly Fixture _fixture; - - public create_filtered(Fixture fixture) => _fixture = fixture; - - public static IEnumerable FilterCases() => Filters.All.Select(filter => new object[] { filter }); - - [SupportsPSToAll.Theory] - [MemberData(nameof(FilterCases))] - public async Task the_completion_succeeds(string filterName) { - var streamPrefix = _fixture.GetStreamName(); - var (getFilter, _) = Filters.GetFilter(filterName); - var filter = getFilter(streamPrefix); - - await _fixture.Client.CreateToAllAsync( - filterName, - filter, - new(), - userCredentials: TestCredentials.Root - ); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_on_all_stream.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_on_all_stream.cs deleted file mode 100644 index 92aa86e1d..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_on_all_stream.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class create_on_all_stream : IClassFixture { - readonly Fixture _fixture; - - public create_on_all_stream(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public Task the_completion_succeeds() => _fixture.Client.CreateToAllAsync("existing", new(), userCredentials: TestCredentials.Root); - - [SupportsPSToAll.Fact] - public Task throws_argument_exception_if_wrong_start_from_type_passed() => - Assert.ThrowsAsync( - () => _fixture.Client.CreateToAllAsync("existing", new(startFrom: StreamPosition.End), userCredentials: TestCredentials.Root) - ); - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_persistent_subscription_with_dont_timeout.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_persistent_subscription_with_dont_timeout.cs deleted file mode 100644 index f44c830f0..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_persistent_subscription_with_dont_timeout.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class create_with_dont_timeout - : IClassFixture { - readonly Fixture _fixture; - - public create_with_dont_timeout(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public Task the_subscription_is_created_without_error() => - _fixture.Client.CreateToAllAsync( - "dont-timeout", - new(messageTimeout: TimeSpan.Zero), - userCredentials: TestCredentials.Root - ); - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_with_commit_position_equal_to_last_indexed_position.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_with_commit_position_equal_to_last_indexed_position.cs deleted file mode 100644 index e6db02901..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_with_commit_position_equal_to_last_indexed_position.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class create_with_commit_position_equal_to_last_indexed_position : IClassFixture { - readonly Fixture _fixture; - - public create_with_commit_position_equal_to_last_indexed_position(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_completion_succeeds() => - await _fixture.Client.CreateToAllAsync( - "group57", - new(startFrom: new Position(_fixture.LastCommitPosition, _fixture.LastCommitPosition)), - userCredentials: TestCredentials.Root - ); - - public class Fixture : EventStoreClientFixture { - public ulong LastCommitPosition; - - protected override async Task Given() { - var lastEvent = await StreamsClient.ReadAllAsync( - Direction.Backwards, - Position.End, - 1, - userCredentials: TestCredentials.Root - ).FirstAsync(); - - LastCommitPosition = lastEvent.OriginalPosition?.CommitPosition ?? throw new(); - } - - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_with_commit_position_larger_than_last_indexed_position.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_with_commit_position_larger_than_last_indexed_position.cs deleted file mode 100644 index 7769f8b70..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_with_commit_position_larger_than_last_indexed_position.cs +++ /dev/null @@ -1,41 +0,0 @@ -using Grpc.Core; - -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class create_with_commit_position_larger_than_last_indexed_position - : IClassFixture { - readonly Fixture _fixture; - - public create_with_commit_position_larger_than_last_indexed_position(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task fails() { - var ex = await Assert.ThrowsAsync( - () => - _fixture.Client.CreateToAllAsync( - "group57", - new(startFrom: new Position(_fixture.LastCommitPosition + 1, _fixture.LastCommitPosition)), - userCredentials: TestCredentials.Root - ) - ); - - Assert.Equal(StatusCode.Internal, ex.StatusCode); - } - - public class Fixture : EventStoreClientFixture { - public ulong LastCommitPosition; - - protected override async Task Given() { - var lastEvent = await StreamsClient.ReadAllAsync( - Direction.Backwards, - Position.End, - 1, - userCredentials: TestCredentials.Root - ).FirstAsync(); - - LastCommitPosition = lastEvent.OriginalPosition?.CommitPosition ?? throw new(); - } - - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_with_prepare_position_larger_than_commit_position.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_with_prepare_position_larger_than_commit_position.cs deleted file mode 100644 index 434e90d7a..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_with_prepare_position_larger_than_commit_position.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class create_with_prepare_position_larger_than_commit_position - : IClassFixture { - readonly Fixture _fixture; - - public create_with_prepare_position_larger_than_commit_position(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public Task fails_with_argument_out_of_range_exception() => - Assert.ThrowsAsync( - () => - _fixture.Client.CreateToAllAsync( - "group57", - new(startFrom: new Position(0, 1)), - userCredentials: TestCredentials.Root - ) - ); - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_without_permissions.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_without_permissions.cs deleted file mode 100644 index 71d87a128..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_without_permissions.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class create_without_permissions - : IClassFixture { - readonly Fixture _fixture; - - public create_without_permissions(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public Task the_completion_fails_with_access_denied() => - Assert.ThrowsAsync( - () => - _fixture.Client.CreateToAllAsync( - "group57", - new() - ) - ); - - public class Fixture : EventStoreClientFixture { - public Fixture() : base(noDefaultCredentials: true) { } - - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/deleting_existing_with_permissions.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/deleting_existing_with_permissions.cs deleted file mode 100644 index a81180092..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/deleting_existing_with_permissions.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class deleting_existing_with_permissions - : IClassFixture { - readonly Fixture _fixture; - - public deleting_existing_with_permissions(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public Task the_delete_of_group_succeeds() => - _fixture.Client.DeleteToAllAsync( - "groupname123", - userCredentials: TestCredentials.Root - ); - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - - protected override Task When() => - Client.CreateToAllAsync( - "groupname123", - new(), - userCredentials: TestCredentials.Root - ); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/deleting_existing_with_subscriber.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/deleting_existing_with_subscriber.cs deleted file mode 100644 index 4db83e251..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/deleting_existing_with_subscriber.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class deleting_existing_with_subscriber : IClassFixture { - public const string Group = "groupname123"; - private readonly Fixture _fixture; - - public deleting_existing_with_subscriber(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_subscription_is_dropped_with_not_found() { - await using var subscription = _fixture.Client.SubscribeToAll(Group, userCredentials: TestCredentials.Root); - - Assert.True(await subscription.Messages.OfType().AnyAsync() - .AsTask() - .WithTimeout()); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Client.CreateToAllAsync(Group, new(), userCredentials: TestCredentials.Root); - - protected override Task When() => Client.DeleteToAllAsync(Group, userCredentials: TestCredentials.Root); - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/deleting_filtered.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/deleting_filtered.cs deleted file mode 100644 index 7a461ebf9..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/deleting_filtered.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class deleting_filtered - : IClassFixture { - const string Group = "to-be-deleted"; - readonly Fixture _fixture; - - public deleting_filtered(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_completion_succeeds() => await _fixture.Client.DeleteToAllAsync(Group, userCredentials: TestCredentials.Root); - - public class Fixture : EventStoreClientFixture { - protected override async Task Given() => - await Client.CreateToAllAsync( - Group, - EventTypeFilter.Prefix("prefix-filter-"), - new(), - userCredentials: TestCredentials.Root - ); - - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/deleting_nonexistent.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/deleting_nonexistent.cs deleted file mode 100644 index 804850e89..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/deleting_nonexistent.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class deleting_nonexistent - : IClassFixture { - readonly Fixture _fixture; - - public deleting_nonexistent(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_delete_fails_with_argument_exception() => - await Assert.ThrowsAsync( - () => _fixture.Client.DeleteToAllAsync(Guid.NewGuid().ToString(), userCredentials: TestCredentials.Root) - ); - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/deleting_without_permissions.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/deleting_without_permissions.cs deleted file mode 100644 index 13e1339a9..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/deleting_without_permissions.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class deleting_without_permissions - : IClassFixture { - readonly Fixture _fixture; - - public deleting_without_permissions(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_delete_fails_with_access_denied() => - await Assert.ThrowsAsync(() => _fixture.Client.DeleteToAllAsync(Guid.NewGuid().ToString())); - - public class Fixture : EventStoreClientFixture { - public Fixture() : base(noDefaultCredentials: true) { } - - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/get_info.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/get_info.cs deleted file mode 100644 index ab748a5d5..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/get_info.cs +++ /dev/null @@ -1,181 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class get_info : IClassFixture { - private const string GroupName = nameof(get_info); - - private static readonly PersistentSubscriptionSettings Settings = new( - resolveLinkTos: true, - startFrom: Position.Start, - extraStatistics: true, - messageTimeout: TimeSpan.FromSeconds(9), - maxRetryCount: 11, - liveBufferSize: 303, - readBatchSize: 30, - historyBufferSize: 909, - checkPointAfter: TimeSpan.FromSeconds(1), - checkPointLowerBound: 1, - checkPointUpperBound: 1, - maxSubscriberCount: 500, - consumerStrategyName: SystemConsumerStrategies.Pinned); - - private readonly Fixture _fixture; - - public get_info(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task throws_when_not_supported() { - if (SupportsPSToAll.No) { - await Assert.ThrowsAsync(async () => - await _fixture.Client.GetInfoToAllAsync(GroupName, userCredentials: TestCredentials.Root)); - } - } - - [SupportsPSToAll.Fact] - public async Task returns_expected_result() { - var result = await _fixture.Client.GetInfoToAllAsync(GroupName, userCredentials: TestCredentials.Root); - - Assert.Equal("$all", result.EventSource); - Assert.Equal(GroupName, result.GroupName); - Assert.Equal("Live", result.Status); - - Assert.NotNull(Settings.StartFrom); - Assert.True(result.Stats.TotalItems > 0); - Assert.True(result.Stats.OutstandingMessagesCount > 0); - Assert.True(result.Stats.AveragePerSecond >= 0); - Assert.True(result.Stats.ParkedMessageCount > 0); - Assert.True(result.Stats.AveragePerSecond >= 0); - Assert.True(result.Stats.CountSinceLastMeasurement >= 0); - Assert.True(result.Stats.TotalInFlightMessages >= 0); - Assert.NotNull(result.Stats.LastKnownEventPosition); - Assert.NotNull(result.Stats.LastCheckpointedEventPosition); - Assert.True(result.Stats.LiveBufferCount >= 0); - - Assert.NotNull(result.Connections); - Assert.NotEmpty(result.Connections); - - var connection = result.Connections.First(); - Assert.NotNull(connection.From); - Assert.Equal(TestCredentials.Root.Username, connection.Username); - Assert.NotEmpty(connection.ConnectionName); - Assert.True(connection.AverageItemsPerSecond >= 0); - Assert.True(connection.TotalItems > 0); - Assert.True(connection.CountSinceLastMeasurement >= 0); - Assert.True(connection.AvailableSlots >= 0); - Assert.True(connection.InFlightMessages >= 0); - Assert.NotNull(connection.ExtraStatistics); - Assert.NotEmpty(connection.ExtraStatistics); - - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Highest); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Mean); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Median); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Fastest); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Quintile1); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Quintile2); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Quintile3); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Quintile4); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Quintile5); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.NinetyPercent); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.NinetyFivePercent); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.NinetyNinePercent); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.NinetyNinePointFivePercent); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.NinetyNinePointNinePercent); - - Assert.NotNull(result.Settings); - Assert.Equal(Settings.StartFrom, result.Settings!.StartFrom); - Assert.Equal(Settings.ResolveLinkTos, result.Settings!.ResolveLinkTos); - Assert.Equal(Settings.ExtraStatistics, result.Settings!.ExtraStatistics); - Assert.Equal(Settings.MessageTimeout, result.Settings!.MessageTimeout); - Assert.Equal(Settings.MaxRetryCount, result.Settings!.MaxRetryCount); - Assert.Equal(Settings.LiveBufferSize, result.Settings!.LiveBufferSize); - Assert.Equal(Settings.ReadBatchSize, result.Settings!.ReadBatchSize); - Assert.Equal(Settings.HistoryBufferSize, result.Settings!.HistoryBufferSize); - Assert.Equal(Settings.CheckPointAfter, result.Settings!.CheckPointAfter); - Assert.Equal(Settings.CheckPointLowerBound, result.Settings!.CheckPointLowerBound); - Assert.Equal(Settings.CheckPointUpperBound, result.Settings!.CheckPointUpperBound); - Assert.Equal(Settings.MaxSubscriberCount, result.Settings!.MaxSubscriberCount); - Assert.Equal(Settings.ConsumerStrategyName, result.Settings!.ConsumerStrategyName); - } - - [SupportsPSToAll.Fact] - public async Task throws_with_non_existing_subscription() => - await Assert.ThrowsAsync( - async () => await _fixture.Client.GetInfoToAllAsync("NonExisting", userCredentials: TestCredentials.Root)); - - [SupportsPSToAll.Fact] - public async Task throws_with_no_credentials() => - await Assert.ThrowsAsync(async () => - await _fixture.Client.GetInfoToAllAsync("NonExisting")); - - [SupportsPSToAll.Fact] - public async Task throws_with_non_existing_user() => - await Assert.ThrowsAsync(async () => - await _fixture.Client.GetInfoToAllAsync("NonExisting", userCredentials: TestCredentials.TestBadUser)); - - [SupportsPSToAll.Fact] - public async Task returns_result_with_normal_user_credentials() { - var result = await _fixture.Client.GetInfoToAllAsync(GroupName, userCredentials: TestCredentials.TestUser1); - - Assert.Equal("$all", result.EventSource); - } - - private void AssertKeyAndValue(IDictionary items, string key) { - Assert.True(items.ContainsKey(key)); - Assert.True(items[key] > 0); - } - - public class Fixture : EventStoreClientFixture { - private EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? _subscription; - private IAsyncEnumerator? _enumerator; - public Fixture() : base(noDefaultCredentials: true) { } - - protected override async Task Given() { - if (SupportsPSToAll.No) - return; - - await Client.CreateToAllAsync(GroupName, get_info.Settings, userCredentials: TestCredentials.Root); - - foreach (var eventData in CreateTestEvents(20)) { - await StreamsClient.AppendToStreamAsync($"test-{Guid.NewGuid():n}", StreamState.NoStream, - new[] { eventData }, userCredentials: TestCredentials.Root); - } - } - - protected override async Task When() { - if (SupportsPSToAll.No) - return; - - var counter = 0; - - _subscription = Client.SubscribeToAll(GroupName, userCredentials: TestCredentials.Root); - _enumerator = _subscription.Messages.GetAsyncEnumerator(); - - while (await _enumerator.MoveNextAsync()) { - if (_enumerator.Current is not PersistentSubscriptionMessage.Event (var resolvedEvent, _)) { - continue; - } - - counter++; - - if (counter == 1) { - await _subscription.Nack(PersistentSubscriptionNakEventAction.Park, "Test", resolvedEvent); - } - - if (counter > 10) { - return; - } - } - } - - public override async Task DisposeAsync() { - if (_enumerator is not null) { - await _enumerator.DisposeAsync(); - } - - if (_subscription is not null) { - await _subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/happy_case_catching_up_to_link_to_events_manual_ack.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/happy_case_catching_up_to_link_to_events_manual_ack.cs deleted file mode 100644 index dbcc44b43..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/happy_case_catching_up_to_link_to_events_manual_ack.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System.Text; - -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class happy_case_catching_up_to_link_to_events_manual_ack - : IClassFixture { - private const string Group = nameof(Group); - private const int BufferCount = 10; - private const int EventWriteCount = BufferCount * 2; - - private readonly Fixture _fixture; - - public happy_case_catching_up_to_link_to_events_manual_ack(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task Test() { - await _fixture.Subscription!.Messages.OfType() - .Take(_fixture.Events.Length) - .ForEachAwaitAsync(e => _fixture.Subscription.Ack(e.ResolvedEvent)) - .WithTimeout(); - - } - - public class Fixture : EventStoreClientFixture { - public readonly EventData[] Events; - - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - Events = CreateTestEvents(EventWriteCount) - .Select((e, i) => new EventData(e.EventId, SystemEventTypes.LinkTo, Encoding.UTF8.GetBytes($"{i}@test"), - contentType: Constants.Metadata.ContentTypes.ApplicationOctetStream)) - .ToArray(); - } - - protected override async Task Given() { - foreach (var e in Events) { - await StreamsClient.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.Any, new[] { e }); - } - - await Client.CreateToAllAsync(Group, new(startFrom: Position.Start, resolveLinkTos: true), - userCredentials: TestCredentials.Root); - - Subscription = Client.SubscribeToAll(Group, bufferSize: BufferCount, userCredentials: TestCredentials.Root); - } - - protected override Task When() => Task.CompletedTask; - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/happy_case_catching_up_to_normal_events_manual_ack.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/happy_case_catching_up_to_normal_events_manual_ack.cs deleted file mode 100644 index 05612443d..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/happy_case_catching_up_to_normal_events_manual_ack.cs +++ /dev/null @@ -1,51 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class happy_case_catching_up_to_normal_events_manual_ack - : IClassFixture { - private const string Group = nameof(Group); - private const int BufferCount = 10; - private const int EventWriteCount = BufferCount * 2; - - private readonly Fixture _fixture; - - public happy_case_catching_up_to_normal_events_manual_ack(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task Test() { - await _fixture.Subscription!.Messages.OfType() - .Take(_fixture.Events.Length) - .ForEachAwaitAsync(e => _fixture.Subscription.Ack(e.ResolvedEvent)) - .WithTimeout(); - } - - - public class Fixture : EventStoreClientFixture { - public readonly EventData[] Events; - - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - Events = CreateTestEvents(EventWriteCount).ToArray(); - } - - protected override async Task Given() { - foreach (var e in Events) - await StreamsClient.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.Any, new[] { e }); - - await Client.CreateToAllAsync(Group, new(startFrom: Position.Start, resolveLinkTos: true), - userCredentials: TestCredentials.Root); - - Subscription = Client.SubscribeToAll(Group, bufferSize: BufferCount, userCredentials: TestCredentials.Root); - } - - protected override Task When() => Task.CompletedTask; - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/happy_case_filtered.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/happy_case_filtered.cs deleted file mode 100644 index 9d89fddb1..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/happy_case_filtered.cs +++ /dev/null @@ -1,54 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class happy_case_filtered : IClassFixture { - private readonly Fixture _fixture; - - public happy_case_filtered(Fixture fixture) => _fixture = fixture; - - public static IEnumerable FilterCases() => Filters.All.Select(filter => new object[] { filter }); - - [SupportsPSToAll.Theory] - [MemberData(nameof(FilterCases))] - public async Task reads_all_existing_filtered_events(string filterName) { - var streamPrefix = $"{filterName}-{_fixture.GetStreamName()}"; - var (getFilter, prepareEvent) = Filters.GetFilter(filterName); - var filter = getFilter(streamPrefix); - - var appearedEvents = new List(); - var events = _fixture.CreateTestEvents(20).Select(e => prepareEvent(streamPrefix, e)).ToArray(); - - foreach (var e in events) { - await _fixture.StreamsClient.AppendToStreamAsync($"{streamPrefix}_{Guid.NewGuid():n}", StreamState.NoStream, - new[] { e }); - } - - await _fixture.Client.CreateToAllAsync(filterName, filter, new(startFrom: Position.Start), - userCredentials: TestCredentials.Root); - - await using var subscription = - _fixture.Client.SubscribeToAll(filterName, userCredentials: TestCredentials.Root); - await subscription.Messages - .OfType() - .Take(events.Length) - .ForEachAwaitAsync(async e => { - var (resolvedEvent, _) = e; - appearedEvents.Add(resolvedEvent.Event); - await subscription.Ack(resolvedEvent); - }) - .WithTimeout(); - - Assert.Equal(events.Select(x => x.EventId), appearedEvents.Select(x => x.EventId)); - } - - public class Fixture : EventStoreClientFixture { - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Guid.NewGuid().ToString(), StreamState.NoStream, - CreateTestEvents(256)); - - await StreamsClient.SetStreamMetadataAsync(SystemStreams.AllStream, StreamState.Any, - new(acl: new(SystemRoles.All)), userCredentials: TestCredentials.Root); - } - - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/happy_case_filtered_with_start_from_set.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/happy_case_filtered_with_start_from_set.cs deleted file mode 100644 index 065782783..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/happy_case_filtered_with_start_from_set.cs +++ /dev/null @@ -1,62 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class happy_case_filtered_with_start_from_set : IClassFixture { - private readonly Fixture _fixture; - - public happy_case_filtered_with_start_from_set(Fixture fixture) => _fixture = fixture; - - public static IEnumerable FilterCases() => Filters.All.Select(filter => new object[] { filter }); - - [SupportsPSToAll.Theory] - [MemberData(nameof(FilterCases))] - public async Task reads_all_existing_filtered_events_from_specified_start(string filterName) { - var streamPrefix = $"{filterName}-{_fixture.GetStreamName()}"; - var (getFilter, prepareEvent) = Filters.GetFilter(filterName); - var filter = getFilter(streamPrefix); - - var events = _fixture.CreateTestEvents(20).Select(e => prepareEvent(streamPrefix, e)).ToArray(); - var eventsToSkip = events.Take(10).ToArray(); - var eventsToCapture = events.Skip(10).ToArray(); - - IWriteResult? eventToCaptureResult = null; - - foreach (var e in eventsToSkip) { - await _fixture.StreamsClient.AppendToStreamAsync($"{streamPrefix}_{Guid.NewGuid():n}", StreamState.NoStream, - new[] { e }); - } - - foreach (var e in eventsToCapture) { - var result = await _fixture.StreamsClient.AppendToStreamAsync($"{streamPrefix}_{Guid.NewGuid():n}", - StreamState.NoStream, new[] { e }); - - eventToCaptureResult ??= result; - } - - await _fixture.Client.CreateToAllAsync(filterName, filter, new(startFrom: eventToCaptureResult!.LogPosition), - userCredentials: TestCredentials.Root); - - await using var subscription = - _fixture.Client.SubscribeToAll(filterName, userCredentials: TestCredentials.Root); - - var appearedEvents = await subscription.Messages.OfType() - .Take(10) - .Select(e => e.ResolvedEvent.Event) - .ToArrayAsync() - .AsTask() - .WithTimeout(); - - Assert.Equal(eventsToCapture.Select(x => x.EventId), appearedEvents.Select(x => x.EventId)); - } - - public class Fixture : EventStoreClientFixture { - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Guid.NewGuid().ToString(), StreamState.NoStream, - CreateTestEvents(256)); - - await StreamsClient.SetStreamMetadataAsync(SystemStreams.AllStream, StreamState.Any, - new(acl: new(SystemRoles.All)), userCredentials: TestCredentials.Root); - } - - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/happy_case_writing_and_subscribing_to_normal_events_manual_ack.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/happy_case_writing_and_subscribing_to_normal_events_manual_ack.cs deleted file mode 100644 index 100e49f27..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/happy_case_writing_and_subscribing_to_normal_events_manual_ack.cs +++ /dev/null @@ -1,57 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class happy_case_writing_and_subscribing_to_normal_events_manual_ack - : IClassFixture { - private const string Group = nameof(Group); - private const int BufferCount = 10; - private const int EventWriteCount = BufferCount * 2; - - private readonly Fixture _fixture; - - public happy_case_writing_and_subscribing_to_normal_events_manual_ack(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task Test() { - await _fixture.Subscription!.Messages.OfType() - .SelectAwait(async e => { - await _fixture.Subscription.Ack(e.ResolvedEvent); - return e; - }) - .Where(e => e.ResolvedEvent.OriginalStreamId.StartsWith("test-")) - .Take(_fixture.Events.Length) - .ToArrayAsync() - .AsTask() - .WithTimeout(); - } - - public class Fixture : EventStoreClientFixture { - public readonly EventData[] Events; - - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - Events = CreateTestEvents(EventWriteCount).ToArray(); - } - - protected override async Task Given() { - await Client.CreateToAllAsync(Group, new(startFrom: Position.End, resolveLinkTos: true), - userCredentials: TestCredentials.Root); - - Subscription = Client.SubscribeToAll(Group, bufferSize: BufferCount, userCredentials: TestCredentials.Root); - } - - protected override async Task When() { - foreach (var e in Events) { - await StreamsClient.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.Any, new[] { e }); - } - } - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/list_with_persistent_subscriptions.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/list_with_persistent_subscriptions.cs deleted file mode 100644 index 443a9d04e..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/list_with_persistent_subscriptions.cs +++ /dev/null @@ -1,82 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class list_with_persistent_subscriptions : IClassFixture { - const int AllStreamSubscriptionCount = 3; - const int StreamSubscriptionCount = 4; - const string GroupName = nameof(list_with_persistent_subscriptions); - const string StreamName = nameof(list_with_persistent_subscriptions); - - readonly Fixture _fixture; - - public list_with_persistent_subscriptions(Fixture fixture) => _fixture = fixture; - - int TotalSubscriptionCount => - SupportsPSToAll.No - ? StreamSubscriptionCount - : StreamSubscriptionCount + AllStreamSubscriptionCount; - - [Fact] - public async Task throws_when_not_supported() { - if (SupportsPSToAll.No) - await Assert.ThrowsAsync(async () => { await _fixture.Client.ListToAllAsync(userCredentials: TestCredentials.Root); }); - } - - [SupportsPSToAll.Fact] - public async Task returns_subscriptions_to_all_stream() { - var result = (await _fixture.Client.ListToAllAsync(userCredentials: TestCredentials.Root)).ToList(); - Assert.Equal(AllStreamSubscriptionCount, result.Count); - Assert.All(result, s => Assert.Equal("$all", s.EventSource)); - } - - [Fact] - public async Task returns_all_subscriptions() { - var result = (await _fixture.Client.ListAllAsync(userCredentials: TestCredentials.Root)).ToList(); - Assert.Equal(TotalSubscriptionCount, result.Count()); - } - - [SupportsPSToAll.Fact] - public async Task throws_with_no_credentials() => - await Assert.ThrowsAsync( - async () => - await _fixture.Client.ListToAllAsync() - ); - - [SupportsPSToAll.Fact] - public async Task throws_with_non_existing_user() => - await Assert.ThrowsAsync( - async () => - await _fixture.Client.ListToAllAsync(userCredentials: TestCredentials.TestBadUser) - ); - - [SupportsPSToAll.Fact] - public async Task returns_result_with_normal_user_credentials() { - var result = await _fixture.Client.ListToAllAsync(userCredentials: TestCredentials.TestUser1); - Assert.Equal(AllStreamSubscriptionCount, result.Count()); - } - - public class Fixture : EventStoreClientFixture { - public Fixture() : base(skipPSWarmUp: true, noDefaultCredentials: true) { } - - protected override async Task Given() { - for (var i = 0; i < StreamSubscriptionCount; i++) - await Client.CreateToStreamAsync( - StreamName, - GroupName + i, - new(), - userCredentials: TestCredentials.Root - ); - - if (SupportsPSToAll.No) - return; - - for (var i = 0; i < AllStreamSubscriptionCount; i++) - await Client.CreateToAllAsync( - GroupName + i, - new(), - userCredentials: TestCredentials.Root - ); - } - - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/list_without_persistent_subscriptions.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/list_without_persistent_subscriptions.cs deleted file mode 100644 index 0a9c435be..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/list_without_persistent_subscriptions.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class list_without_persistent_subscriptions : IClassFixture { - readonly Fixture _fixture; - - public list_without_persistent_subscriptions(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task throws() { - if (SupportsPSToAll.No) { - await Assert.ThrowsAsync(async () => { await _fixture.Client.ListToAllAsync(userCredentials: TestCredentials.Root); }); - - return; - } - - await Assert.ThrowsAsync( - async () => - await _fixture.Client.ListToAllAsync(userCredentials: TestCredentials.Root) - ); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/replay_parked.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/replay_parked.cs deleted file mode 100644 index 501500abd..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/replay_parked.cs +++ /dev/null @@ -1,90 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class replay_parked : IClassFixture { - const string GroupName = nameof(replay_parked); - - readonly Fixture _fixture; - - public replay_parked(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task throws_when_not_supported() { - if (SupportsPSToAll.No) - await Assert.ThrowsAsync( - async () => { - await _fixture.Client.ReplayParkedMessagesToAllAsync( - GroupName, - userCredentials: TestCredentials.Root - ); - } - ); - } - - [SupportsPSToAll.Fact] - public async Task does_not_throw() { - await _fixture.Client.ReplayParkedMessagesToAllAsync( - GroupName, - userCredentials: TestCredentials.Root - ); - - await _fixture.Client.ReplayParkedMessagesToAllAsync( - GroupName, - 100, - userCredentials: TestCredentials.Root - ); - } - - [SupportsPSToAll.Fact] - public async Task throws_when_given_non_existing_subscription() => - await Assert.ThrowsAsync( - () => - _fixture.Client.ReplayParkedMessagesToAllAsync( - "NonExisting", - userCredentials: TestCredentials.Root - ) - ); - - [SupportsPSToAll.Fact] - public async Task throws_with_no_credentials() => - await Assert.ThrowsAsync( - () => - _fixture.Client.ReplayParkedMessagesToAllAsync(GroupName) - ); - - [SupportsPSToAll.Fact] - public async Task throws_with_non_existing_user() => - await Assert.ThrowsAsync( - () => - _fixture.Client.ReplayParkedMessagesToAllAsync( - GroupName, - userCredentials: TestCredentials.TestBadUser - ) - ); - - [SupportsPSToAll.Fact] - public async Task throws_with_normal_user_credentials() => - await Assert.ThrowsAsync( - () => - _fixture.Client.ReplayParkedMessagesToAllAsync( - GroupName, - userCredentials: TestCredentials.TestUser1 - ) - ); - - public class Fixture : EventStoreClientFixture { - public Fixture() : base(noDefaultCredentials: true) { } - - protected override async Task Given() { - if (SupportsPSToAll.No) - return; - - await Client.CreateToAllAsync( - GroupName, - new(), - userCredentials: TestCredentials.Root - ); - } - - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing.cs deleted file mode 100644 index c1fac1c1f..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class update_existing : IClassFixture { - const string Group = "existing"; - - readonly Fixture _fixture; - - public update_existing(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_completion_succeeds() => - await _fixture.Client.UpdateToAllAsync( - Group, - new(), - userCredentials: TestCredentials.Root - ); - - public class Fixture : EventStoreClientFixture { - protected override async Task Given() => - await Client.CreateToAllAsync( - Group, - new(), - userCredentials: TestCredentials.Root - ); - - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_filtered.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_filtered.cs deleted file mode 100644 index ff0f5ab5d..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_filtered.cs +++ /dev/null @@ -1,30 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class update_existing_filtered - : IClassFixture { - const string Group = "existing-filtered"; - - readonly Fixture _fixture; - - public update_existing_filtered(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_completion_succeeds() => - await _fixture.Client.UpdateToAllAsync( - Group, - new(true), - userCredentials: TestCredentials.Root - ); - - public class Fixture : EventStoreClientFixture { - protected override async Task Given() => - await Client.CreateToAllAsync( - Group, - EventTypeFilter.Prefix("prefix-filter-"), - new(), - userCredentials: TestCredentials.Root - ); - - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_with_check_point.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_with_check_point.cs deleted file mode 100644 index 05d6a70e3..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_with_check_point.cs +++ /dev/null @@ -1,108 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class update_existing_with_check_point : IClassFixture { - private const string Group = "existing-with-check-point"; - - private readonly Fixture _fixture; - - public update_existing_with_check_point(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public void resumes_from_check_point() { - Assert.True(_fixture.Resumed.Event.Position > _fixture.CheckPoint); - } - - public class Fixture : EventStoreClientFixture { - private readonly List _appearedEvents; - private readonly EventData[] _events; - - private EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? _subscription; - private IAsyncEnumerator? _enumerator; - - public ResolvedEvent Resumed { get; private set; } - public Position CheckPoint { get; private set; } - - public Fixture() { - _appearedEvents = new(); - _events = CreateTestEvents(5).ToArray(); - } - - protected override async Task Given() { - foreach (var e in _events) { - await StreamsClient.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.Any, new[] { e }); - } - - await Client.CreateToAllAsync(Group, - new(checkPointLowerBound: 5, checkPointAfter: TimeSpan.FromSeconds(1), startFrom: Position.Start), - userCredentials: TestCredentials.Root); - - _subscription = Client.SubscribeToAll(Group, userCredentials: TestCredentials.Root); - _enumerator = _subscription.Messages.GetAsyncEnumerator(); - await _enumerator.MoveNextAsync(); - - await Task.WhenAll(Subscribe().WithTimeout(), WaitForCheckpoint().WithTimeout()); - - return; - - async Task Subscribe() { - while (await _enumerator.MoveNextAsync()) { - if (_enumerator.Current is not PersistentSubscriptionMessage.Event(var resolvedEvent, _)) { - continue; - } - - _appearedEvents.Add(resolvedEvent); - await _subscription.Ack(resolvedEvent); - if (_appearedEvents.Count == _events.Length) { - break; - } - } - } - - async Task WaitForCheckpoint() { - await using var subscription = StreamsClient.SubscribeToStream( - $"$persistentsubscription-$all::{Group}-checkpoint", FromStream.Start, - userCredentials: TestCredentials.Root); - await foreach (var message in subscription.Messages) { - if (message is not StreamMessage.Event(var resolvedEvent)) { - continue; - } - - CheckPoint = resolvedEvent.Event.Data.ParsePosition(); - return; - } - } } - - protected override async Task When() { - // Force restart of the subscription - await Client.UpdateToAllAsync(Group, new(), userCredentials: TestCredentials.Root); - - try { - while (await _enumerator!.MoveNextAsync()) { } - } catch (PersistentSubscriptionDroppedByServerException) { } - - foreach (var e in _events) { - await StreamsClient.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.NoStream, new[] { e }); - } - - await using var subscription = Client.SubscribeToAll(Group, userCredentials: TestCredentials.Root); - Resumed = await subscription.Messages.OfType() - .Select(e => e.ResolvedEvent) - .Take(1) - .FirstAsync() - .AsTask() - .WithTimeout(); - } - - public override async Task DisposeAsync() { - if (_enumerator is not null) { - await _enumerator.DisposeAsync(); - } - - if (_subscription is not null) { - await _subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_with_check_point_filtered.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_with_check_point_filtered.cs deleted file mode 100644 index 829aca768..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_with_check_point_filtered.cs +++ /dev/null @@ -1,111 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class update_existing_with_check_point_filtered - : IClassFixture { - private const string Group = "existing-with-check-point-filtered"; - - private readonly Fixture _fixture; - - public update_existing_with_check_point_filtered(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public void resumes_from_check_point() { - Assert.True(_fixture.Resumed.Event.Position > _fixture.CheckPoint); - } - - public class Fixture : EventStoreClientFixture { - private readonly List _appearedEvents; - private readonly EventData[] _events; - - private EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? _subscription; - private IAsyncEnumerator? _enumerator; - - public ResolvedEvent Resumed { get; private set; } - public Position CheckPoint { get; private set; } - - public Fixture() { - _appearedEvents = new(); - _events = CreateTestEvents(5).ToArray(); - } - - - protected override async Task Given() { - foreach (var e in _events) { - await StreamsClient.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.NoStream, new[] { e }); - } - - await Client.CreateToAllAsync(Group, StreamFilter.Prefix("test"), - new(checkPointLowerBound: 5, checkPointAfter: TimeSpan.FromSeconds(1), startFrom: Position.Start), - userCredentials: TestCredentials.Root); - - _subscription = Client.SubscribeToAll(Group, userCredentials: TestCredentials.Root); - _enumerator = _subscription.Messages.GetAsyncEnumerator(); - await _enumerator.MoveNextAsync(); - - await Task.WhenAll(Subscribe().WithTimeout(), WaitForCheckpoint().WithTimeout()); - - return; - - async Task Subscribe() { - while (await _enumerator.MoveNextAsync()) { - if (_enumerator.Current is not PersistentSubscriptionMessage.Event(var resolvedEvent, _)) { - continue; - } - - _appearedEvents.Add(resolvedEvent); - await _subscription.Ack(resolvedEvent); - if (_appearedEvents.Count == _events.Length) { - break; - } - } - } - - async Task WaitForCheckpoint() { - await using var subscription = StreamsClient.SubscribeToStream( - $"$persistentsubscription-$all::{Group}-checkpoint", FromStream.Start, - userCredentials: TestCredentials.Root); - await foreach (var message in subscription.Messages) { - if (message is not StreamMessage.Event(var resolvedEvent)) { - continue; - } - - CheckPoint = resolvedEvent.Event.Data.ParsePosition(); - return; - } - } - } - - protected override async Task When() { - // Force restart of the subscription - await Client.UpdateToAllAsync(Group, new(), userCredentials: TestCredentials.Root); - - try { - while (await _enumerator!.MoveNextAsync()) { } - } catch (PersistentSubscriptionDroppedByServerException) { } - - foreach (var e in _events) { - await StreamsClient.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.NoStream, new[] { e }); - } - - await using var subscription = Client.SubscribeToAll(Group, userCredentials: TestCredentials.Root); - Resumed = await subscription.Messages.OfType() - .Select(e => e.ResolvedEvent) - .Take(1) - .FirstAsync() - .AsTask() - .WithTimeout(); - } - - public override async Task DisposeAsync() { - if (_enumerator is not null) { - await _enumerator.DisposeAsync(); - } - - if (_subscription is not null) { - await _subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_with_commit_position_equal_to_last_indexed_position.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_with_commit_position_equal_to_last_indexed_position.cs deleted file mode 100644 index 983349b85..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_with_commit_position_equal_to_last_indexed_position.cs +++ /dev/null @@ -1,41 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class update_existing_with_commit_position_equal_to_last_indexed_position - : IClassFixture { - const string Group = "existing"; - - readonly Fixture _fixture; - - public update_existing_with_commit_position_equal_to_last_indexed_position(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_completion_succeeds() => - await _fixture.Client.UpdateToAllAsync( - Group, - new(startFrom: new Position(_fixture.LastCommitPosition, _fixture.LastCommitPosition)), - userCredentials: TestCredentials.Root - ); - - public class Fixture : EventStoreClientFixture { - public ulong LastCommitPosition; - - protected override async Task Given() { - await Client.CreateToAllAsync( - Group, - new(), - userCredentials: TestCredentials.Root - ); - - var lastEvent = await StreamsClient.ReadAllAsync( - Direction.Backwards, - Position.End, - 1, - userCredentials: TestCredentials.Root - ).FirstAsync(); - - LastCommitPosition = lastEvent.OriginalPosition?.CommitPosition ?? throw new(); - } - - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_with_commit_position_larger_than_last_indexed_position.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_with_commit_position_larger_than_last_indexed_position.cs deleted file mode 100644 index 864e6a806..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_with_commit_position_larger_than_last_indexed_position.cs +++ /dev/null @@ -1,49 +0,0 @@ -using Grpc.Core; - -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class update_existing_with_commit_position_larger_than_last_indexed_position - : IClassFixture { - const string Group = "existing"; - - readonly Fixture _fixture; - - public update_existing_with_commit_position_larger_than_last_indexed_position(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task fails() { - var ex = await Assert.ThrowsAsync( - () => - _fixture.Client.UpdateToAllAsync( - Group, - new(startFrom: new Position(_fixture.LastCommitPosition + 1, _fixture.LastCommitPosition)), - userCredentials: TestCredentials.Root - ) - ); - - Assert.Equal(StatusCode.Internal, ex.StatusCode); - } - - public class Fixture : EventStoreClientFixture { - public ulong LastCommitPosition; - - protected override async Task When() { - await Client.CreateToAllAsync( - Group, - new(), - userCredentials: TestCredentials.Root - ); - - var lastEvent = await StreamsClient.ReadAllAsync( - Direction.Backwards, - Position.End, - 1, - userCredentials: TestCredentials.Root - ).FirstAsync(); - - LastCommitPosition = lastEvent.OriginalPosition?.CommitPosition ?? throw new(); - } - - protected override Task Given() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_with_subscribers.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_with_subscribers.cs deleted file mode 100644 index 71e89d260..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_with_subscribers.cs +++ /dev/null @@ -1,49 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class update_existing_with_subscribers : IClassFixture { - private const string Group = "existing"; - - private readonly Fixture _fixture; - - public update_existing_with_subscribers(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task existing_subscriptions_are_dropped() { - var ex = await Assert.ThrowsAsync(async () => { - while (await _fixture.Enumerator!.MoveNextAsync()) { - } - }).WithTimeout(); - - Assert.Equal(SystemStreams.AllStream, ex.StreamName); - Assert.Equal(Group, ex.GroupName); - } - - public class Fixture : EventStoreClientFixture { - private EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? _subscription; - public IAsyncEnumerator? Enumerator { get; private set; } - - protected override async Task Given() { - await Client.CreateToAllAsync(Group, new(startFrom: Position.Start), userCredentials: TestCredentials.Root); - - _subscription = Client.SubscribeToAll(Group, userCredentials: TestCredentials.Root); - - Enumerator = _subscription.Messages.GetAsyncEnumerator(); - - await Enumerator.MoveNextAsync(); - } - - protected override Task When() => Client.UpdateToAllAsync(Group, new(), userCredentials: TestCredentials.Root); - - public override async Task DisposeAsync() { - if (Enumerator is not null) { - await Enumerator.DisposeAsync(); - } - - if (_subscription is not null) { - await _subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_without_permissions.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_without_permissions.cs deleted file mode 100644 index fa72629ca..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_without_permissions.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class update_existing_without_permissions - : IClassFixture { - const string Group = "existing"; - - readonly Fixture _fixture; - - public update_existing_without_permissions(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_completion_fails_with_access_denied() => - await Assert.ThrowsAsync( - () => _fixture.Client.UpdateToAllAsync( - Group, - new() - ) - ); - - public class Fixture : EventStoreClientFixture { - public Fixture() : base(noDefaultCredentials: true) { } - - protected override async Task Given() => - await Client.CreateToAllAsync( - Group, - new(), - userCredentials: TestCredentials.Root - ); - - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_non_existent.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_non_existent.cs deleted file mode 100644 index 5082e86d0..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_non_existent.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class update_non_existent - : IClassFixture { - const string Group = "nonexistent"; - - readonly Fixture _fixture; - - public update_non_existent(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_completion_fails_with_not_found() => - await Assert.ThrowsAsync( - () => _fixture.Client.UpdateToAllAsync( - Group, - new(), - userCredentials: TestCredentials.Root - ) - ); - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_with_prepare_position_larger_than_commit_position.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_with_prepare_position_larger_than_commit_position.cs deleted file mode 100644 index ce53d81ae..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_with_prepare_position_larger_than_commit_position.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class update_with_prepare_position_larger_than_commit_position - : IClassFixture { - const string Group = "existing"; - - readonly Fixture _fixture; - - public update_with_prepare_position_larger_than_commit_position(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public Task fails_with_argument_out_of_range_exception() => - Assert.ThrowsAsync( - () => - _fixture.Client.UpdateToAllAsync( - Group, - new(startFrom: new Position(0, 1)), - userCredentials: TestCredentials.Root - ) - ); - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/when_writing_and_filtering_out_events.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/when_writing_and_filtering_out_events.cs deleted file mode 100644 index cda94d8b3..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/when_writing_and_filtering_out_events.cs +++ /dev/null @@ -1,87 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class when_writing_and_filtering_out_events : IClassFixture { - private const string Group = "filtering-out-events"; - - private readonly Fixture _fixture; - - public when_writing_and_filtering_out_events(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public void it_should_write_a_check_point() { - Assert.True(_fixture.SecondCheckPoint > _fixture.FirstCheckPoint); - Assert.Equal(_fixture.Events.Select(e => e.EventId), _fixture.AppearedEvents.Select(e => e.Event.EventId)); - } - - public class Fixture : EventStoreClientFixture { - private readonly List _appearedEvents; - - public Fixture() { - Events = CreateTestEvents(10).ToArray(); - _appearedEvents = new(); - } - - public Position SecondCheckPoint { get; private set; } - public Position FirstCheckPoint { get; private set; } - public EventData[] Events { get; } - public ResolvedEvent[] AppearedEvents => _appearedEvents.ToArray(); - - protected override async Task Given() { - foreach (var e in Events) { - await StreamsClient.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.Any, new[] { e }); - } - - await Client.CreateToAllAsync(Group, StreamFilter.Prefix("test"), - new(checkPointLowerBound: 1, checkPointUpperBound: 5, checkPointAfter: TimeSpan.FromSeconds(1), - startFrom: Position.Start), userCredentials: TestCredentials.Root); - - await using var subscription = Client.SubscribeToAll(Group, userCredentials: TestCredentials.Root); - await using var enumerator = subscription.Messages.GetAsyncEnumerator(); - - await Task.WhenAll(Subscribe().WithTimeout(), WaitForCheckpoints().WithTimeout()); - - return; - - async Task Subscribe() { - while (await enumerator.MoveNextAsync()) { - if (enumerator.Current is not PersistentSubscriptionMessage.Event(var resolvedEvent, _)) { - continue; - } - - _appearedEvents.Add(resolvedEvent); - await subscription.Ack(resolvedEvent); - if (_appearedEvents.Count == Events.Length) { - break; - } - } - } - - async Task WaitForCheckpoints() { - bool firstCheckpointSet = false; - await using var subscription = StreamsClient.SubscribeToStream( - $"$persistentsubscription-$all::{Group}-checkpoint", FromStream.Start, - userCredentials: TestCredentials.Root); - await foreach (var message in subscription.Messages) { - if (message is not StreamMessage.Event(var resolvedEvent)) { - continue; - } - - if (!firstCheckpointSet) { - FirstCheckPoint = resolvedEvent.Event.Data.ParsePosition(); - firstCheckpointSet = true; - } else { - SecondCheckPoint = resolvedEvent.Event.Data.ParsePosition(); - return; - } - } - } - } - - protected override async Task When() { - foreach (var e in Events) { - await StreamsClient.AppendToStreamAsync("filtered-out-stream-" + Guid.NewGuid(), StreamState.Any, - new[] { e }); - } - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/when_writing_and_subscribing_to_normal_events_manual_nack.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/when_writing_and_subscribing_to_normal_events_manual_nack.cs deleted file mode 100644 index 72e0cfd00..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/when_writing_and_subscribing_to_normal_events_manual_nack.cs +++ /dev/null @@ -1,57 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class when_writing_and_subscribing_to_normal_events_manual_nack - : IClassFixture { - private const string Group = nameof(Group); - private const int BufferCount = 10; - private const int EventWriteCount = BufferCount * 2; - - private readonly Fixture _fixture; - - public when_writing_and_subscribing_to_normal_events_manual_nack(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task Test() { - await _fixture.Subscription!.Messages.OfType() - .SelectAwait(async e => { - await _fixture.Subscription.Nack(PersistentSubscriptionNakEventAction.Park, "fail", e.ResolvedEvent); - return e; - }) - .Where(e => e.ResolvedEvent.OriginalStreamId.StartsWith("test-")) - .Take(_fixture.Events.Length) - .ToArrayAsync() - .AsTask() - .WithTimeout(); - } - - public class Fixture : EventStoreClientFixture { - public readonly EventData[] Events; - - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - Events = CreateTestEvents(EventWriteCount).ToArray(); - } - - protected override async Task Given() { - await Client.CreateToAllAsync(Group, new(startFrom: Position.Start, resolveLinkTos: true), - userCredentials: TestCredentials.Root); - - Subscription = Client.SubscribeToAll(Group, bufferSize: BufferCount, userCredentials: TestCredentials.Root); - } - - protected override async Task When() { - foreach (var e in Events) { - await StreamsClient.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.Any, new[] { e }); - } - } - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_max_one_client_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_max_one_client_obsolete.cs deleted file mode 100644 index 8f290088c..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_max_one_client_obsolete.cs +++ /dev/null @@ -1,47 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_with_max_one_client_obsolete - : IClassFixture { - const string Group = "startinbeginning1"; - const string Stream = nameof(connect_to_existing_with_max_one_client_obsolete); - readonly Fixture _fixture; - - public connect_to_existing_with_max_one_client_obsolete(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_second_subscription_fails_to_connect() { - using var first = await _fixture.Client.SubscribeToStreamAsync( - Stream, - Group, - delegate { return Task.CompletedTask; }, - userCredentials: TestCredentials.Root - ).WithTimeout(); - - var ex = await Assert.ThrowsAsync( - async () => { - using var _ = await _fixture.Client.SubscribeToStreamAsync( - Stream, - Group, - delegate { return Task.CompletedTask; }, - userCredentials: TestCredentials.Root - ); - } - ).WithTimeout(); - - Assert.Equal(Stream, ex.StreamName); - Assert.Equal(Group, ex.GroupName); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => - Client.CreateToStreamAsync( - Stream, - Group, - new(maxSubscriberCount: 1), - userCredentials: TestCredentials.Root - ); - - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_permissions_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_permissions_obsolete.cs deleted file mode 100644 index 70ada6f17..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_permissions_obsolete.cs +++ /dev/null @@ -1,39 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_with_permissions_obsolete - : IClassFixture { - const string Stream = nameof(connect_to_existing_with_permissions_obsolete); - - readonly Fixture _fixture; - - public connect_to_existing_with_permissions_obsolete(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_subscription_succeeds() { - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - using var subscription = await _fixture.Client.SubscribeToStreamAsync( - Stream, - "agroupname17", - delegate { return Task.CompletedTask; }, - (s, reason, ex) => dropped.TrySetResult((reason, ex)), - TestCredentials.Root - ).WithTimeout(); - - Assert.NotNull(subscription); - - await Assert.ThrowsAsync(() => dropped.Task.WithTimeout()); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => - Client.CreateToStreamAsync( - Stream, - "agroupname17", - new(), - userCredentials: TestCredentials.Root - ); - - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_beginning_and_events_in_it_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_beginning_and_events_in_it_obsolete.cs deleted file mode 100644 index c023db1f8..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_beginning_and_events_in_it_obsolete.cs +++ /dev/null @@ -1,65 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_with_start_from_beginning_and_events_in_it_obsolete - : IClassFixture { - const string Group = "startinbeginning1"; - - const string Stream = - nameof(connect_to_existing_with_start_from_beginning_and_events_in_it_obsolete); - - readonly Fixture _fixture; - - public connect_to_existing_with_start_from_beginning_and_events_in_it_obsolete(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_event_zero_as_its_first_event() { - var resolvedEvent = await _fixture.FirstEvent.WithTimeout(TimeSpan.FromSeconds(10)); - Assert.Equal(StreamPosition.Start, resolvedEvent.Event.EventNumber); - Assert.Equal(_fixture.Events[0].EventId, resolvedEvent.Event.EventId); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _firstEventSource; - public readonly EventData[] Events; - PersistentSubscription? _subscription; - - public Fixture() { - _firstEventSource = new(); - Events = CreateTestEvents(10).ToArray(); - } - - public Task FirstEvent => _firstEventSource.Task; - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events); - await Client.CreateToStreamAsync( - Stream, - Group, - new(startFrom: StreamPosition.Start), - userCredentials: TestCredentials.Root - ); - } - - protected override async Task When() => - _subscription = await Client.SubscribeToStreamAsync( - Stream, - Group, - async (subscription, e, r, ct) => { - _firstEventSource.TrySetResult(e); - await subscription.Ack(e); - }, - (subscription, reason, ex) => { - if (reason != SubscriptionDroppedReason.Disposed) - _firstEventSource.TrySetException(ex!); - }, - TestCredentials.TestUser1 - ); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_beginning_and_no_stream_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_beginning_and_no_stream_obsolete.cs deleted file mode 100644 index 037ec52e5..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_beginning_and_no_stream_obsolete.cs +++ /dev/null @@ -1,65 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_with_start_from_beginning_and_no_stream_obsolete - : IClassFixture { - const string Group = "startinbeginning1"; - - const string Stream = - nameof(connect_to_existing_with_start_from_beginning_and_no_stream_obsolete); - - readonly Fixture _fixture; - - public connect_to_existing_with_start_from_beginning_and_no_stream_obsolete(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_event_zero_as_its_first_event() { - var firstEvent = await _fixture.FirstEvent.WithTimeout(TimeSpan.FromSeconds(10)); - Assert.Equal(StreamPosition.Start, firstEvent.Event.EventNumber); - Assert.Equal(_fixture.EventId, firstEvent.Event.EventId); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _firstEventSource; - public readonly EventData[] Events; - PersistentSubscription? _subscription; - - public Fixture() { - _firstEventSource = new(); - Events = CreateTestEvents().ToArray(); - } - - public Task FirstEvent => _firstEventSource.Task; - public Uuid EventId => Events.Single().EventId; - - protected override async Task Given() { - await Client.CreateToStreamAsync( - Stream, - Group, - new(), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToStreamAsync( - Stream, - Group, - async (subscription, e, r, ct) => { - _firstEventSource.TrySetResult(e); - await subscription.Ack(e); - }, - (subscription, reason, ex) => { - if (reason != SubscriptionDroppedReason.Disposed) - _firstEventSource.TrySetException(ex!); - }, - TestCredentials.TestUser1 - ); - } - - protected override Task When() => StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_not_set_and_events_in_it_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_not_set_and_events_in_it_obsolete.cs deleted file mode 100644 index f0bd49b06..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_not_set_and_events_in_it_obsolete.cs +++ /dev/null @@ -1,61 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_with_start_from_not_set_and_events_in_it_obsolete - : IClassFixture { - const string Group = "startinbeginning1"; - - const string Stream = - nameof(connect_to_existing_with_start_from_not_set_and_events_in_it_obsolete); - - readonly Fixture _fixture; - - public connect_to_existing_with_start_from_not_set_and_events_in_it_obsolete(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_no_events() => await Assert.ThrowsAsync(() => _fixture.FirstEvent.WithTimeout()); - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _firstEventSource; - public readonly EventData[] Events; - PersistentSubscription? _subscription; - - public Fixture() { - _firstEventSource = new(); - Events = CreateTestEvents(10).ToArray(); - } - - public Task FirstEvent => _firstEventSource.Task; - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events); - await Client.CreateToStreamAsync( - Stream, - Group, - new(), - userCredentials: TestCredentials.Root - ); - } - - protected override async Task When() => - _subscription = await Client.SubscribeToStreamAsync( - Stream, - Group, - async (subscription, e, r, ct) => { - _firstEventSource.TrySetResult(e); - await subscription.Ack(e); - }, - (subscription, reason, ex) => { - if (reason != SubscriptionDroppedReason.Disposed) - _firstEventSource.TrySetException(ex!); - }, - TestCredentials.TestUser1 - ); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_not_set_and_events_in_it_then_event_written_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_not_set_and_events_in_it_then_event_written_obsolete.cs deleted file mode 100644 index ea1987ceb..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_not_set_and_events_in_it_then_event_written_obsolete.cs +++ /dev/null @@ -1,67 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_with_start_from_not_set_and_events_in_it_then_event_written_obsolete - : IClassFixture { - const string Group = "startinbeginning1"; - const string Stream = nameof(connect_to_existing_with_start_from_not_set_and_events_in_it_then_event_written_obsolete); - - readonly Fixture _fixture; - - public - connect_to_existing_with_start_from_not_set_and_events_in_it_then_event_written_obsolete(Fixture fixture) => - _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_the_written_event_as_its_first_event() { - var resolvedEvent = await _fixture.FirstEvent.WithTimeout(); - Assert.Equal(new(10), resolvedEvent.Event.EventNumber); - Assert.Equal(_fixture.Events.Last().EventId, resolvedEvent.Event.EventId); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _firstEventSource; - - public readonly EventData[] Events; - - PersistentSubscription? _subscription; - - public Fixture() { - _firstEventSource = new(); - Events = CreateTestEvents(11).ToArray(); - } - - public Task FirstEvent => _firstEventSource.Task; - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events.Take(10)); - await Client.CreateToStreamAsync( - Stream, - Group, - new(), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToStreamAsync( - Stream, - Group, - async (subscription, e, r, ct) => { - _firstEventSource.TrySetResult(e); - await subscription.Ack(e); - }, - (subscription, reason, ex) => { - if (reason != SubscriptionDroppedReason.Disposed) - _firstEventSource.TrySetException(ex!); - }, - TestCredentials.TestUser1 - ); - } - - protected override Task When() => StreamsClient.AppendToStreamAsync(Stream, new StreamRevision(9), Events.Skip(10)); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_obsolete.cs deleted file mode 100644 index b25765019..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_obsolete.cs +++ /dev/null @@ -1,60 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_obsolete - : IClassFixture { - const string Group = "startinbeginning1"; - - const string Stream = - nameof(connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_obsolete); - - readonly Fixture _fixture; - - public connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_obsolete(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_no_events() => await Assert.ThrowsAsync(() => _fixture.FirstEvent.WithTimeout()); - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _firstEventSource; - public readonly EventData[] Events; - PersistentSubscription? _subscription; - - public Fixture() { - _firstEventSource = new(); - Events = CreateTestEvents(10).ToArray(); - } - - public Task FirstEvent => _firstEventSource.Task; - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events); - await Client.CreateToStreamAsync( - Stream, - Group, - new(startFrom: StreamPosition.End), - userCredentials: TestCredentials.Root - ); - } - - protected override async Task When() => - _subscription = await Client.SubscribeToStreamAsync( - Stream, - Group, - async (subscription, e, r, ct) => { - _firstEventSource.TrySetResult(e); - await subscription.Ack(e); - }, - (subscription, reason, ex) => { - if (reason != SubscriptionDroppedReason.Disposed) - _firstEventSource.TrySetException(ex!); - }, - TestCredentials.TestUser1 - ); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_then_event_written_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_then_event_written_obsolete.cs deleted file mode 100644 index 9bc45141b..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_then_event_written_obsolete.cs +++ /dev/null @@ -1,72 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class - connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_then_event_written_obsolete - : IClassFixture< - connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_then_event_written_obsolete - .Fixture> { - const string Group = "startinbeginning1"; - - const string Stream = - nameof( - connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_then_event_written_obsolete - ); - - readonly Fixture _fixture; - - public - connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_then_event_written_obsolete(Fixture fixture) => - _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_the_written_event_as_its_first_event() { - var resolvedEvent = await _fixture.FirstEvent.WithTimeout(); - Assert.Equal(new(10), resolvedEvent.Event.EventNumber); - Assert.Equal(_fixture.Events.Last().EventId, resolvedEvent.Event.EventId); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _firstEventSource; - public readonly EventData[] Events; - PersistentSubscription? _subscription; - - public Fixture() { - _firstEventSource = new(); - Events = CreateTestEvents(11).ToArray(); - } - - public Task FirstEvent => _firstEventSource.Task; - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events.Take(10)); - await Client.CreateToStreamAsync( - Stream, - Group, - new(startFrom: StreamPosition.End), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToStreamAsync( - Stream, - Group, - async (subscription, e, r, ct) => { - _firstEventSource.TrySetResult(e); - await subscription.Ack(e); - }, - (subscription, reason, ex) => { - if (reason != SubscriptionDroppedReason.Disposed) - _firstEventSource.TrySetException(ex!); - }, - TestCredentials.TestUser1 - ); - } - - protected override Task When() => StreamsClient.AppendToStreamAsync(Stream, new StreamRevision(9), Events.Skip(10)); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_two_and_no_stream_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_two_and_no_stream_obsolete.cs deleted file mode 100644 index 09d6e4f21..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_two_and_no_stream_obsolete.cs +++ /dev/null @@ -1,65 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_with_start_from_two_and_no_stream_obsolete - : IClassFixture { - const string Group = "startinbeginning1"; - - const string Stream = - nameof(connect_to_existing_with_start_from_two_and_no_stream_obsolete); - - readonly Fixture _fixture; - - public connect_to_existing_with_start_from_two_and_no_stream_obsolete(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_event_two_as_its_first_event() { - var resolvedEvent = await _fixture.FirstEvent.WithTimeout(TimeSpan.FromSeconds(10)); - Assert.Equal(new(2), resolvedEvent.Event.EventNumber); - Assert.Equal(_fixture.EventId, resolvedEvent.Event.EventId); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _firstEventSource; - public readonly EventData[] Events; - PersistentSubscription? _subscription; - - public Fixture() { - _firstEventSource = new(); - Events = CreateTestEvents(3).ToArray(); - } - - public Task FirstEvent => _firstEventSource.Task; - public Uuid EventId => Events.Last().EventId; - - protected override async Task Given() { - await Client.CreateToStreamAsync( - Stream, - Group, - new(startFrom: new StreamPosition(2)), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToStreamAsync( - Stream, - Group, - async (subscription, e, r, ct) => { - _firstEventSource.TrySetResult(e); - await subscription.Ack(e); - }, - (subscription, reason, ex) => { - if (reason != SubscriptionDroppedReason.Disposed) - _firstEventSource.TrySetException(ex!); - }, - TestCredentials.TestUser1 - ); - } - - protected override Task When() => StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_x_set_and_events_in_it_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_x_set_and_events_in_it_obsolete.cs deleted file mode 100644 index c74f8b45f..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_x_set_and_events_in_it_obsolete.cs +++ /dev/null @@ -1,65 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_with_start_from_x_set_and_events_in_it_obsolete - : IClassFixture { - const string Group = "startinx2"; - - const string Stream = - nameof(connect_to_existing_with_start_from_x_set_and_events_in_it_obsolete); - - readonly Fixture _fixture; - - public connect_to_existing_with_start_from_x_set_and_events_in_it_obsolete(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_the_written_event_as_its_first_event() { - var resolvedEvent = await _fixture.FirstEvent.WithTimeout(); - Assert.Equal(new(4), resolvedEvent.Event.EventNumber); - Assert.Equal(_fixture.Events.Skip(4).First().EventId, resolvedEvent.Event.EventId); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _firstEventSource; - public readonly EventData[] Events; - PersistentSubscription? _subscription; - - public Fixture() { - _firstEventSource = new(); - Events = CreateTestEvents(10).ToArray(); - } - - public Task FirstEvent => _firstEventSource.Task; - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events.Take(10)); - await Client.CreateToStreamAsync( - Stream, - Group, - new(startFrom: new StreamPosition(4)), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToStreamAsync( - Stream, - Group, - async (subscription, e, r, ct) => { - _firstEventSource.TrySetResult(e); - await subscription.Ack(e); - }, - (subscription, reason, ex) => { - if (reason != SubscriptionDroppedReason.Disposed) - _firstEventSource.TrySetException(ex!); - }, - TestCredentials.TestUser1 - ); - } - - protected override Task When() => StreamsClient.AppendToStreamAsync(Stream, new StreamRevision(9), Events.Skip(10)); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_x_set_and_events_in_it_then_event_written_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_x_set_and_events_in_it_then_event_written_obsolete.cs deleted file mode 100644 index a3fae30a1..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_x_set_and_events_in_it_then_event_written_obsolete.cs +++ /dev/null @@ -1,68 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_with_start_from_x_set_and_events_in_it_then_event_written_obsolete - : IClassFixture< - connect_to_existing_with_start_from_x_set_and_events_in_it_then_event_written_obsolete. - Fixture> { - const string Group = "startinbeginning1"; - - const string Stream = - nameof(connect_to_existing_with_start_from_x_set_and_events_in_it_then_event_written_obsolete - ); - - readonly Fixture _fixture; - - public connect_to_existing_with_start_from_x_set_and_events_in_it_then_event_written_obsolete(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_the_written_event_as_its_first_event() { - var resolvedEvent = await _fixture.FirstEvent.WithTimeout(); - Assert.Equal(new(10), resolvedEvent.Event.EventNumber); - Assert.Equal(_fixture.Events.Last().EventId, resolvedEvent.Event.EventId); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _firstEventSource; - public readonly EventData[] Events; - PersistentSubscription? _subscription; - - public Fixture() { - _firstEventSource = new(); - Events = CreateTestEvents(11).ToArray(); - } - - public Task FirstEvent => _firstEventSource.Task; - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events.Take(10)); - await Client.CreateToStreamAsync( - Stream, - Group, - new(startFrom: new StreamPosition(10)), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToStreamAsync( - Stream, - Group, - async (subscription, e, r, ct) => { - _firstEventSource.TrySetResult(e); - await subscription.Ack(e); - }, - (subscription, reason, ex) => { - if (reason != SubscriptionDroppedReason.Disposed) - _firstEventSource.TrySetException(ex!); - }, - TestCredentials.TestUser1 - ); - } - - protected override Task When() => StreamsClient.AppendToStreamAsync(Stream, new StreamRevision(9), Events.Skip(10)); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_x_set_higher_than_x_and_events_in_it_then_event_written_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_x_set_higher_than_x_and_events_in_it_then_event_written_obsolete.cs deleted file mode 100644 index 59198a660..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_x_set_higher_than_x_and_events_in_it_then_event_written_obsolete.cs +++ /dev/null @@ -1,72 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class - connect_to_existing_with_start_from_x_set_higher_than_x_and_events_in_it_then_event_written_obsolete - : IClassFixture< - connect_to_existing_with_start_from_x_set_higher_than_x_and_events_in_it_then_event_written_obsolete - .Fixture> { - const string Group = "startinbeginning1"; - - const string Stream = - nameof( - connect_to_existing_with_start_from_x_set_higher_than_x_and_events_in_it_then_event_written_obsolete - ); - - readonly Fixture _fixture; - - public - connect_to_existing_with_start_from_x_set_higher_than_x_and_events_in_it_then_event_written_obsolete(Fixture fixture) => - _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_the_written_event_as_its_first_event() { - var resolvedEvent = await _fixture.FirstEvent.WithTimeout(); - Assert.Equal(new(11), resolvedEvent.Event.EventNumber); - Assert.Equal(_fixture.Events.Last().EventId, resolvedEvent.Event.EventId); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _firstEventSource; - public readonly EventData[] Events; - PersistentSubscription? _subscription; - - public Fixture() { - _firstEventSource = new(); - Events = CreateTestEvents(12).ToArray(); - } - - public Task FirstEvent => _firstEventSource.Task; - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events.Take(11)); - await Client.CreateToStreamAsync( - Stream, - Group, - new(startFrom: new StreamPosition(11)), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToStreamAsync( - Stream, - Group, - async (subscription, e, r, ct) => { - _firstEventSource.TrySetResult(e); - await subscription.Ack(e); - }, - (subscription, reason, ex) => { - if (reason != SubscriptionDroppedReason.Disposed) - _firstEventSource.TrySetException(ex!); - }, - TestCredentials.TestUser1 - ); - } - - protected override Task When() => StreamsClient.AppendToStreamAsync(Stream, new StreamRevision(10), Events.Skip(11)); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_without_permissions_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_without_permissions_obsolete.cs deleted file mode 100644 index 25942cd05..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_without_permissions_obsolete.cs +++ /dev/null @@ -1,35 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_without_permissions_obsolete - : IClassFixture { - const string Stream = "$" + nameof(connect_to_existing_without_permissions_obsolete); - readonly Fixture _fixture; - public connect_to_existing_without_permissions_obsolete(Fixture fixture) => _fixture = fixture; - - [Fact] - public Task throws_access_denied() => - Assert.ThrowsAsync( - async () => { - using var _ = await _fixture.Client.SubscribeToStreamAsync( - Stream, - "agroupname55", - delegate { return Task.CompletedTask; } - ); - } - ).WithTimeout(); - - public class Fixture : EventStoreClientFixture { - public Fixture() : base(noDefaultCredentials: true) { } - - protected override Task Given() => - Client.CreateToStreamAsync( - Stream, - "agroupname55", - new(), - userCredentials: TestCredentials.Root - ); - - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_non_existing_with_permissions_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_non_existing_with_permissions_obsolete.cs deleted file mode 100644 index dd9d74900..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_non_existing_with_permissions_obsolete.cs +++ /dev/null @@ -1,34 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_non_existing_with_permissions_obsolete - : IClassFixture { - const string Stream = nameof(connect_to_non_existing_with_permissions_obsolete); - const string Group = "foo"; - - readonly Fixture _fixture; - - public connect_to_non_existing_with_permissions_obsolete(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task throws_persistent_subscription_not_found() { - var ex = await Assert.ThrowsAsync( - async () => { - using var _ = await _fixture.Client.SubscribeToStreamAsync( - Stream, - Group, - delegate { return Task.CompletedTask; }, - userCredentials: TestCredentials.Root - ); - } - ).WithTimeout(); - - Assert.Equal(Stream, ex.StreamName); - Assert.Equal(Group, ex.GroupName); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_with_retries_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_with_retries_obsolete.cs deleted file mode 100644 index d31fcc961..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_with_retries_obsolete.cs +++ /dev/null @@ -1,70 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_with_retries_obsolete : IClassFixture { - const string Group = "retries"; - const string Stream = nameof(connect_with_retries_obsolete); - - readonly Fixture _fixture; - - public connect_with_retries_obsolete(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task events_are_retried_until_success() => Assert.Equal(5, await _fixture.RetryCount.WithTimeout()); - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _retryCountSource; - - public readonly EventData[] Events; - - PersistentSubscription? _subscription; - - public Fixture() { - _retryCountSource = new(); - - Events = CreateTestEvents().ToArray(); - } - - public Task RetryCount => _retryCountSource.Task; - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events); - await Client.CreateToStreamAsync( - Stream, - Group, - new(startFrom: StreamPosition.Start), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToStreamAsync( - Stream, - Group, - async (subscription, e, r, ct) => { - if (r > 4) { - _retryCountSource.TrySetResult(r.Value); - await subscription.Ack(e.Event.EventId); - } - else { - await subscription.Nack( - PersistentSubscriptionNakEventAction.Retry, - "Not yet tried enough times", - e - ); - } - }, - (subscription, reason, ex) => { - if (reason != SubscriptionDroppedReason.Disposed) - _retryCountSource.TrySetException(ex!); - }, - TestCredentials.TestUser1 - ); - } - - protected override Task When() => StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connecting_to_a_persistent_subscription_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connecting_to_a_persistent_subscription_obsolete.cs deleted file mode 100644 index af09f9867..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connecting_to_a_persistent_subscription_obsolete.cs +++ /dev/null @@ -1,72 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class - connecting_to_a_persistent_subscription_obsolete - : IClassFixture< - connecting_to_a_persistent_subscription_obsolete - .Fixture> { - const string Group = "startinbeginning1"; - - const string Stream = - nameof( - connecting_to_a_persistent_subscription_obsolete - ); - - readonly Fixture _fixture; - - public - connecting_to_a_persistent_subscription_obsolete(Fixture fixture) => - _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_the_written_event_as_its_first_event() { - var resolvedEvent = await _fixture.FirstEvent.WithTimeout(); - Assert.Equal(new(11), resolvedEvent.Event.EventNumber); - Assert.Equal(_fixture.Events.Last().EventId, resolvedEvent.Event.EventId); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _firstEventSource; - public readonly EventData[] Events; - PersistentSubscription? _subscription; - - public Fixture() { - _firstEventSource = new(); - Events = CreateTestEvents(12).ToArray(); - } - - public Task FirstEvent => _firstEventSource.Task; - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events.Take(11)); - await Client.CreateToStreamAsync( - Stream, - Group, - new(startFrom: new StreamPosition(11)), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToStreamAsync( - Stream, - Group, - async (subscription, e, r, ct) => { - _firstEventSource.TrySetResult(e); - await subscription.Ack(e); - }, - (subscription, reason, ex) => { - if (reason != SubscriptionDroppedReason.Disposed) - _firstEventSource.TrySetException(ex!); - }, - TestCredentials.TestUser1 - ); - } - - protected override Task When() => StreamsClient.AppendToStreamAsync(Stream, new StreamRevision(10), Events.Skip(11)); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/deleting_existing_with_subscriber_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/deleting_existing_with_subscriber_obsolete.cs deleted file mode 100644 index d684c76af..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/deleting_existing_with_subscriber_obsolete.cs +++ /dev/null @@ -1,67 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class deleting_existing_with_subscriber_obsolete - : IClassFixture { - const string Stream = nameof(deleting_existing_with_subscriber_obsolete); - readonly Fixture _fixture; - - public deleting_existing_with_subscriber_obsolete(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_subscription_is_dropped() { - var (reason, exception) = await _fixture.Dropped.WithTimeout(); - Assert.Equal(SubscriptionDroppedReason.ServerError, reason); - var ex = Assert.IsType(exception); - - Assert.Equal(Stream, ex.StreamName); - Assert.Equal("groupname123", ex.GroupName); - } - - [Fact(Skip = "Isn't this how it should work?")] - public async Task the_subscription_is_dropped_with_not_found() { - var (reason, exception) = await _fixture.Dropped.WithTimeout(); - Assert.Equal(SubscriptionDroppedReason.ServerError, reason); - var ex = Assert.IsType(exception); - Assert.Equal(Stream, ex.StreamName); - Assert.Equal("groupname123", ex.GroupName); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource<(SubscriptionDroppedReason, Exception?)> _dropped; - PersistentSubscription? _subscription; - - public Fixture() => _dropped = new(); - - public Task<(SubscriptionDroppedReason, Exception?)> Dropped => _dropped.Task; - - protected override async Task Given() { - await Client.CreateToStreamAsync( - Stream, - "groupname123", - new(), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToStreamAsync( - Stream, - "groupname123", - (_, _, _, _) => Task.CompletedTask, - (_, r, e) => _dropped.TrySetResult((r, e)), - TestCredentials.Root - ); - } - - protected override Task When() => - Client.DeleteToStreamAsync( - Stream, - "groupname123", - userCredentials: TestCredentials.Root - ); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/get_info_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/get_info_obsolete.cs deleted file mode 100644 index 34068a937..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/get_info_obsolete.cs +++ /dev/null @@ -1,199 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class get_info_obsolete : IClassFixture { - const string GroupName = nameof(get_info_obsolete); - const string StreamName = nameof(get_info_obsolete); - - static readonly PersistentSubscriptionSettings _settings = new( - true, - StreamPosition.Start, - true, - TimeSpan.FromSeconds(9), - 11, - 303, - 30, - 909, - TimeSpan.FromSeconds(1), - 1, - 1, - 500, - SystemConsumerStrategies.RoundRobin - ); - - readonly Fixture _fixture; - - public get_info_obsolete(Fixture fixture) => _fixture = fixture; - - public static IEnumerable AllowedUsers() { - yield return new object[] { TestCredentials.Root }; - yield return new object[] { TestCredentials.TestUser1 }; - } - - [Theory] - [MemberData(nameof(AllowedUsers))] - public async Task returns_expected_result(UserCredentials credentials) { - var result = await _fixture.Client.GetInfoToStreamAsync( - StreamName, - GroupName, - userCredentials: credentials - ); - - Assert.Equal(StreamName, result.EventSource); - Assert.Equal(GroupName, result.GroupName); - Assert.NotNull(_settings.StartFrom); - Assert.True(result.Stats.TotalItems > 0); - Assert.True(result.Stats.OutstandingMessagesCount > 0); - Assert.True(result.Stats.AveragePerSecond >= 0); - Assert.True(result.Stats.ParkedMessageCount >= 0); - Assert.True(result.Stats.AveragePerSecond >= 0); - Assert.True(result.Stats.ReadBufferCount >= 0); - Assert.True(result.Stats.RetryBufferCount >= 0); - Assert.True(result.Stats.CountSinceLastMeasurement >= 0); - Assert.True(result.Stats.TotalInFlightMessages >= 0); - Assert.NotNull(result.Stats.LastKnownEventPosition); - Assert.NotNull(result.Stats.LastCheckpointedEventPosition); - Assert.True(result.Stats.LiveBufferCount >= 0); - - Assert.NotNull(result.Connections); - Assert.NotEmpty(result.Connections); - var connection = result.Connections.First(); - Assert.NotNull(connection.From); - Assert.Equal(TestCredentials.Root.Username, connection.Username); - Assert.NotEmpty(connection.ConnectionName); - Assert.True(connection.AverageItemsPerSecond >= 0); - Assert.True(connection.TotalItems >= 0); - Assert.True(connection.CountSinceLastMeasurement >= 0); - Assert.True(connection.AvailableSlots >= 0); - Assert.True(connection.InFlightMessages >= 0); - Assert.NotNull(connection.ExtraStatistics); - Assert.NotEmpty(connection.ExtraStatistics); - - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Highest); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Mean); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Median); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Fastest); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Quintile1); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Quintile2); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Quintile3); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Quintile4); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Quintile5); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.NinetyPercent); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.NinetyFivePercent); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.NinetyNinePercent); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.NinetyNinePointFivePercent); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.NinetyNinePointNinePercent); - - Assert.NotNull(result.Settings); - Assert.Equal(_settings.StartFrom, result.Settings!.StartFrom); - Assert.Equal(_settings.ResolveLinkTos, result.Settings!.ResolveLinkTos); - Assert.Equal(_settings.ExtraStatistics, result.Settings!.ExtraStatistics); - Assert.Equal(_settings.MessageTimeout, result.Settings!.MessageTimeout); - Assert.Equal(_settings.MaxRetryCount, result.Settings!.MaxRetryCount); - Assert.Equal(_settings.LiveBufferSize, result.Settings!.LiveBufferSize); - Assert.Equal(_settings.ReadBatchSize, result.Settings!.ReadBatchSize); - Assert.Equal(_settings.HistoryBufferSize, result.Settings!.HistoryBufferSize); - Assert.Equal(_settings.CheckPointAfter, result.Settings!.CheckPointAfter); - Assert.Equal(_settings.CheckPointLowerBound, result.Settings!.CheckPointLowerBound); - Assert.Equal(_settings.CheckPointUpperBound, result.Settings!.CheckPointUpperBound); - Assert.Equal(_settings.MaxSubscriberCount, result.Settings!.MaxSubscriberCount); - Assert.Equal(_settings.ConsumerStrategyName, result.Settings!.ConsumerStrategyName); - } - - [Fact] - public async Task throws_when_given_non_existing_subscription() => - await Assert.ThrowsAsync( - async () => { - await _fixture.Client.GetInfoToStreamAsync( - "NonExisting", - "NonExisting", - userCredentials: TestCredentials.Root - ); - } - ); - - [Fact(Skip = "Unable to produce same behavior with HTTP fallback!")] - public async Task throws_with_non_existing_user() => - await Assert.ThrowsAsync( - async () => { - await _fixture.Client.GetInfoToStreamAsync( - "NonExisting", - "NonExisting", - userCredentials: TestCredentials.TestBadUser - ); - } - ); - - [Fact] - public async Task throws_with_no_credentials() => - await Assert.ThrowsAsync( - async () => { - await _fixture.Client.GetInfoToStreamAsync( - "NonExisting", - "NonExisting" - ); - } - ); - - [Fact] - public async Task returns_result_for_normal_user() { - var result = await _fixture.Client.GetInfoToStreamAsync( - StreamName, - GroupName, - userCredentials: TestCredentials.TestUser1 - ); - - Assert.NotNull(result); - } - - void AssertKeyAndValue(IDictionary items, string key) { - Assert.True(items.ContainsKey(key)); - Assert.True(items[key] > 0); - } - - public class Fixture : EventStoreClientFixture { - public Fixture() : base(noDefaultCredentials: true) { } - - protected override Task Given() => - Client.CreateToStreamAsync( - groupName: GroupName, - streamName: StreamName, - settings: _settings, - userCredentials: TestCredentials.Root - ); - - protected override async Task When() { - var counter = 0; - var tcs = new TaskCompletionSource(); - - await Client.SubscribeToStreamAsync( - StreamName, - GroupName, - (s, e, r, ct) => { - counter++; - - if (counter == 1) - s.Nack(PersistentSubscriptionNakEventAction.Park, "Test", e); - - if (counter > 10) - tcs.TrySetResult(); - - return Task.CompletedTask; - }, - userCredentials: TestCredentials.Root - ); - - for (var i = 0; i < 15; i++) - await StreamsClient.AppendToStreamAsync( - StreamName, - StreamState.Any, - new[] { - new EventData(Uuid.NewUuid(), "test-event", ReadOnlyMemory.Empty) - }, - userCredentials: TestCredentials.Root - ); - - await tcs.Task; - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/happy_case_catching_up_to_link_to_events_manual_ack_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/happy_case_catching_up_to_link_to_events_manual_ack_obsolete.cs deleted file mode 100644 index e69e88fb2..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/happy_case_catching_up_to_link_to_events_manual_ack_obsolete.cs +++ /dev/null @@ -1,80 +0,0 @@ -using System.Text; - -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class happy_case_catching_up_to_link_to_events_manual_ack_obsolete - : IClassFixture { - const string Stream = nameof(happy_case_catching_up_to_link_to_events_manual_ack_obsolete); - const string Group = nameof(Group); - const int BufferCount = 10; - const int EventWriteCount = BufferCount * 2; - - readonly Fixture _fixture; - - public happy_case_catching_up_to_link_to_events_manual_ack_obsolete(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task Test() => await _fixture.EventsReceived.WithTimeout(); - - public class Fixture : EventStoreClientFixture { - readonly EventData[] _events; - readonly TaskCompletionSource _eventsReceived; - int _eventReceivedCount; - - PersistentSubscription? _subscription; - - public Fixture() { - _events = CreateTestEvents(EventWriteCount) - .Select( - (e, i) => new EventData( - e.EventId, - SystemEventTypes.LinkTo, - Encoding.UTF8.GetBytes($"{i}@{Stream}"), - contentType: Constants.Metadata.ContentTypes.ApplicationOctetStream - ) - ) - .ToArray(); - - _eventsReceived = new(); - } - - public Task EventsReceived => _eventsReceived.Task; - - protected override async Task Given() { - foreach (var e in _events) - await StreamsClient.AppendToStreamAsync(Stream, StreamState.Any, new[] { e }); - - await Client.CreateToStreamAsync( - Stream, - Group, - new(startFrom: StreamPosition.Start, resolveLinkTos: true), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToStreamAsync( - Stream, - Group, - async (subscription, e, retryCount, ct) => { - await subscription.Ack(e); - - if (Interlocked.Increment(ref _eventReceivedCount) == _events.Length) - _eventsReceived.TrySetResult(true); - }, - (s, r, e) => { - if (e != null) - _eventsReceived.TrySetException(e); - }, - bufferSize: BufferCount, - userCredentials: TestCredentials.Root - ); - } - - protected override Task When() => Task.CompletedTask; - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/happy_case_catching_up_to_normal_events_manual_ack_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/happy_case_catching_up_to_normal_events_manual_ack_obsolete.cs deleted file mode 100644 index 6973087cc..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/happy_case_catching_up_to_normal_events_manual_ack_obsolete.cs +++ /dev/null @@ -1,67 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class happy_case_catching_up_to_normal_events_manual_ack_obsolete : IClassFixture { - const string Stream = nameof(happy_case_catching_up_to_normal_events_manual_ack_obsolete); - const string Group = nameof(Group); - const int BufferCount = 10; - const int EventWriteCount = BufferCount * 2; - - readonly Fixture _fixture; - - public happy_case_catching_up_to_normal_events_manual_ack_obsolete(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task Test() => await _fixture.EventsReceived.WithTimeout(); - - public class Fixture : EventStoreClientFixture { - readonly EventData[] _events; - readonly TaskCompletionSource _eventsReceived; - int _eventReceivedCount; - - PersistentSubscription? _subscription; - - public Fixture() { - _events = CreateTestEvents(EventWriteCount).ToArray(); - _eventsReceived = new(); - } - - public Task EventsReceived => _eventsReceived.Task; - - protected override async Task Given() { - foreach (var e in _events) - await StreamsClient.AppendToStreamAsync(Stream, StreamState.Any, new[] { e }); - - await Client.CreateToStreamAsync( - Stream, - Group, - new(startFrom: StreamPosition.Start, resolveLinkTos: true), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToStreamAsync( - Stream, - Group, - async (subscription, e, retryCount, ct) => { - await subscription.Ack(e); - - if (Interlocked.Increment(ref _eventReceivedCount) == _events.Length) - _eventsReceived.TrySetResult(true); - }, - (s, r, e) => { - if (e != null) - _eventsReceived.TrySetException(e); - }, - bufferSize: BufferCount, - userCredentials: TestCredentials.Root - ); - } - - protected override Task When() => Task.CompletedTask; - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/happy_case_writing_and_subscribing_to_normal_events_manual_ack_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/happy_case_writing_and_subscribing_to_normal_events_manual_ack_obsolete.cs deleted file mode 100644 index af07bcb4c..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/happy_case_writing_and_subscribing_to_normal_events_manual_ack_obsolete.cs +++ /dev/null @@ -1,67 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class happy_case_writing_and_subscribing_to_normal_events_manual_ack_obsolete - : IClassFixture { - const string Stream = nameof(happy_case_writing_and_subscribing_to_normal_events_manual_ack_obsolete); - const string Group = nameof(Group); - const int BufferCount = 10; - const int EventWriteCount = BufferCount * 2; - - readonly Fixture _fixture; - - public happy_case_writing_and_subscribing_to_normal_events_manual_ack_obsolete(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task Test() => await _fixture.EventsReceived.WithTimeout(); - - public class Fixture : EventStoreClientFixture { - readonly EventData[] _events; - readonly TaskCompletionSource _eventsReceived; - int _eventReceivedCount; - - PersistentSubscription? _subscription; - - public Fixture() { - _events = CreateTestEvents(EventWriteCount).ToArray(); - _eventsReceived = new(); - } - - public Task EventsReceived => _eventsReceived.Task; - - protected override async Task Given() { - await Client.CreateToStreamAsync( - Stream, - Group, - new(startFrom: StreamPosition.End, resolveLinkTos: true), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToStreamAsync( - Stream, - Group, - async (subscription, e, retryCount, ct) => { - await subscription.Ack(e); - if (Interlocked.Increment(ref _eventReceivedCount) == _events.Length) - _eventsReceived.TrySetResult(true); - }, - (s, r, e) => { - if (e != null) - _eventsReceived.TrySetException(e); - }, - bufferSize: BufferCount, - userCredentials: TestCredentials.Root - ); - } - - protected override async Task When() { - foreach (var e in _events) - await StreamsClient.AppendToStreamAsync(Stream, StreamState.Any, new[] { e }); - } - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/update_existing_with_check_point_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/update_existing_with_check_point_obsolete.cs deleted file mode 100644 index f5922c746..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/update_existing_with_check_point_obsolete.cs +++ /dev/null @@ -1,124 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class update_existing_with_check_point_obsolete - : IClassFixture { - const string Stream = nameof(update_existing_with_check_point_obsolete); - const string Group = "existing-with-check-point"; - readonly Fixture _fixture; - - public update_existing_with_check_point_obsolete(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task resumes_from_check_point() { - var resumedEvent = await _fixture.Resumed.WithTimeout(TimeSpan.FromSeconds(10)); - Assert.Equal(_fixture.CheckPoint.Next(), resumedEvent.Event.EventNumber); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _appeared; - readonly List _appearedEvents; - - readonly TaskCompletionSource<(SubscriptionDroppedReason, Exception?)> _droppedSource; - readonly EventData[] _events; - readonly TaskCompletionSource _resumedSource; - PersistentSubscription? _firstSubscription; - PersistentSubscription? _secondSubscription; - - public Fixture() { - _droppedSource = new(); - _resumedSource = new(); - _appeared = new(); - _appearedEvents = new(); - _events = CreateTestEvents(5).ToArray(); - } - - public Task Resumed => _resumedSource.Task; - public StreamPosition CheckPoint { get; private set; } - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, _events); - - await Client.CreateToStreamAsync( - Stream, - Group, - new( - checkPointLowerBound: 5, - checkPointAfter: TimeSpan.FromSeconds(1), - startFrom: StreamPosition.Start - ), - userCredentials: TestCredentials.Root - ); - - var checkPointStream = $"$persistentsubscription-{Stream}::{Group}-checkpoint"; - - _firstSubscription = await Client.SubscribeToStreamAsync( - Stream, - Group, - async (s, e, _, _) => { - _appearedEvents.Add(e); - await s.Ack(e); - - if (_appearedEvents.Count == _events.Length) - _appeared.TrySetResult(true); - }, - (_, reason, ex) => _droppedSource.TrySetResult((reason, ex)), - TestCredentials.Root - ); - - await Task.WhenAll(_appeared.Task.WithTimeout(), Checkpointed()); - - return; - - async Task Checkpointed() { - await using var subscription = StreamsClient.SubscribeToStream(checkPointStream, FromStream.Start, - userCredentials: TestCredentials.Root); - await foreach (var message in subscription.Messages) { - if (message is not StreamMessage.Event(var resolvedEvent)) { - continue; - } - CheckPoint = resolvedEvent.Event.Data.ParseStreamPosition(); - return; - } - - throw new InvalidOperationException(); - } - } - - protected override async Task When() { - // Force restart of the subscription - await Client.UpdateToStreamAsync( - Stream, - Group, - new(), - userCredentials: TestCredentials.Root - ); - - await _droppedSource.Task.WithTimeout(); - - _secondSubscription = await Client.SubscribeToStreamAsync( - Stream, - Group, - async (s, e, _, _) => { - _resumedSource.TrySetResult(e); - await s.Ack(e); - }, - (_, reason, ex) => { - if (ex is not null) - _resumedSource.TrySetException(ex); - else - _resumedSource.TrySetResult(default); - }, - TestCredentials.Root - ); - - await StreamsClient.AppendToStreamAsync(Stream, StreamState.Any, CreateTestEvents(1)); - } - - public override Task DisposeAsync() { - _firstSubscription?.Dispose(); - _secondSubscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/update_existing_with_subscribers_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/update_existing_with_subscribers_obsolete.cs deleted file mode 100644 index 7ff215206..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/update_existing_with_subscribers_obsolete.cs +++ /dev/null @@ -1,61 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class update_existing_with_subscribers_obsolete - : IClassFixture { - const string Stream = nameof(update_existing_with_subscribers_obsolete); - const string Group = "existing"; - readonly Fixture _fixture; - - public update_existing_with_subscribers_obsolete(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task existing_subscriptions_are_dropped() { - var (reason, exception) = await _fixture.Dropped.WithTimeout(TimeSpan.FromSeconds(10)); - Assert.Equal(SubscriptionDroppedReason.ServerError, reason); - var ex = Assert.IsType(exception); - - Assert.Equal(Stream, ex.StreamName); - Assert.Equal(Group, ex.GroupName); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource<(SubscriptionDroppedReason, Exception?)> _droppedSource; - PersistentSubscription? _subscription; - - public Fixture() => _droppedSource = new(); - - public Task<(SubscriptionDroppedReason, Exception?)> Dropped => _droppedSource.Task; - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, CreateTestEvents()); - await Client.CreateToStreamAsync( - Stream, - Group, - new(), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToStreamAsync( - Stream, - Group, - delegate { return Task.CompletedTask; }, - (_, reason, ex) => _droppedSource.TrySetResult((reason, ex)), - TestCredentials.Root - ); - } - - protected override Task When() => - Client.UpdateToStreamAsync( - Stream, - Group, - new(), - userCredentials: TestCredentials.Root - ); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/when_writing_and_subscribing_to_normal_events_manual_nack_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/when_writing_and_subscribing_to_normal_events_manual_nack_obsolete.cs deleted file mode 100644 index 96a2d0af0..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/when_writing_and_subscribing_to_normal_events_manual_nack_obsolete.cs +++ /dev/null @@ -1,70 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class when_writing_and_subscribing_to_normal_events_manual_nack_obsolete - : IClassFixture { - const string Stream = nameof(when_writing_and_subscribing_to_normal_events_manual_nack_obsolete); - const string Group = nameof(Group); - const int BufferCount = 10; - const int EventWriteCount = BufferCount * 2; - - readonly Fixture _fixture; - - public when_writing_and_subscribing_to_normal_events_manual_nack_obsolete(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task Test() => await _fixture.EventsReceived.WithTimeout(); - - public class Fixture : EventStoreClientFixture { - readonly EventData[] _events; - readonly TaskCompletionSource _eventsReceived; - int _eventReceivedCount; - - PersistentSubscription? _subscription; - - public Fixture() { - _events = CreateTestEvents(EventWriteCount) - .ToArray(); - - _eventsReceived = new(); - } - - public Task EventsReceived => _eventsReceived.Task; - - protected override async Task Given() { - await Client.CreateToStreamAsync( - Stream, - Group, - new(startFrom: StreamPosition.Start, resolveLinkTos: true), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToStreamAsync( - Stream, - Group, - async (subscription, e, retryCount, ct) => { - await subscription.Nack(PersistentSubscriptionNakEventAction.Park, "fail", e); - - if (Interlocked.Increment(ref _eventReceivedCount) == _events.Length) - _eventsReceived.TrySetResult(true); - }, - (s, r, e) => { - if (e != null) - _eventsReceived.TrySetException(e); - }, - bufferSize: BufferCount, - userCredentials: TestCredentials.Root - ); - } - - protected override async Task When() { - foreach (var e in _events) - await StreamsClient.AppendToStreamAsync(Stream, StreamState.Any, new[] { e }); - } - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/can_create_duplicate_name_on_different_streams.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/can_create_duplicate_name_on_different_streams.cs deleted file mode 100644 index cb9af1bd6..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/can_create_duplicate_name_on_different_streams.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class can_create_duplicate_name_on_different_streams - : IClassFixture { - const string Stream = - nameof(can_create_duplicate_name_on_different_streams); - - readonly Fixture _fixture; - - public can_create_duplicate_name_on_different_streams(Fixture fixture) => _fixture = fixture; - - [Fact] - public Task the_completion_succeeds() => - _fixture.Client.CreateToStreamAsync( - "someother" + Stream, - "group3211", - new(), - userCredentials: TestCredentials.Root - ); - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - - protected override Task When() => - Client.CreateToStreamAsync( - Stream, - "group3211", - new(), - userCredentials: TestCredentials.Root - ); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_max_one_client.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_max_one_client.cs deleted file mode 100644 index eb5e442ae..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_max_one_client.cs +++ /dev/null @@ -1,33 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class connect_to_existing_with_max_one_client - : IClassFixture { - private const string Group = "startinbeginning1"; - private const string Stream = nameof(connect_to_existing_with_max_one_client); - private readonly Fixture _fixture; - - public connect_to_existing_with_max_one_client(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_second_subscription_fails_to_connect() { - var ex = await Assert.ThrowsAsync( - () => Task.WhenAll(Subscribe().WithTimeout(), Subscribe().WithTimeout())); - - Assert.Equal(Stream, ex.StreamName); - Assert.Equal(Group, ex.GroupName); - return; - - async Task Subscribe() { - await using var subscription = - _fixture.Client.SubscribeToStream(Stream, Group, userCredentials: TestCredentials.Root); - await subscription.Messages.AnyAsync(); - } - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Client.CreateToStreamAsync(Stream, Group, new(maxSubscriberCount: 1), - userCredentials: TestCredentials.Root); - - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_permissions.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_permissions.cs deleted file mode 100644 index 70f4b51f0..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_permissions.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class connect_to_existing_with_permissions - : IClassFixture { - private const string Stream = nameof(connect_to_existing_with_permissions); - - private readonly Fixture _fixture; - - public connect_to_existing_with_permissions(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_subscription_succeeds() { - await using var subscription = - _fixture.Client.SubscribeToStream(Stream, "agroupname17", userCredentials: TestCredentials.Root); - - Assert.True(await subscription.Messages - .FirstAsync().AsTask().WithTimeout() is PersistentSubscriptionMessage.SubscriptionConfirmation); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => - Client.CreateToStreamAsync(Stream, "agroupname17", new(), userCredentials: TestCredentials.Root); - - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_beginning_and_events_in_it.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_beginning_and_events_in_it.cs deleted file mode 100644 index 2c0f5225e..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_beginning_and_events_in_it.cs +++ /dev/null @@ -1,51 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class connect_to_existing_with_start_from_beginning_and_events_in_it - : IClassFixture { - private const string Group = "startinbeginning1"; - private const string Stream = nameof(connect_to_existing_with_start_from_beginning_and_events_in_it); - - private readonly Fixture _fixture; - - public connect_to_existing_with_start_from_beginning_and_events_in_it(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_event_zero_as_its_first_event() { - var resolvedEvent = await _fixture.Subscription!.Messages.OfType() - .Select(e => e.ResolvedEvent) - .FirstOrDefaultAsync().AsTask().WithTimeout(); - - Assert.Equal(StreamPosition.Start, resolvedEvent.Event.EventNumber); - Assert.Equal(_fixture.Events[0].EventId, resolvedEvent.Event.EventId); - } - - public class Fixture : EventStoreClientFixture { - public readonly EventData[] Events; - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - Events = CreateTestEvents(10).ToArray(); - } - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events); - await Client.CreateToStreamAsync(Stream, Group, new(startFrom: StreamPosition.Start), - userCredentials: TestCredentials.Root); - } - - protected override Task When() { - Subscription = Client.SubscribeToStream(Stream, Group, userCredentials: TestCredentials.TestUser1); - - return Task.CompletedTask; - } - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_beginning_and_no_stream.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_beginning_and_no_stream.cs deleted file mode 100644 index a6e9cb26b..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_beginning_and_no_stream.cs +++ /dev/null @@ -1,51 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class connect_to_existing_with_start_from_beginning_and_no_stream - : IClassFixture { - private const string Group = "startinbeginning1"; - private const string Stream = nameof(connect_to_existing_with_start_from_beginning_and_no_stream); - - private readonly Fixture _fixture; - - public connect_to_existing_with_start_from_beginning_and_no_stream(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_event_zero_as_its_first_event() { - var resolvedEvent = await _fixture.Subscription!.Messages.OfType() - .Select(e => e.ResolvedEvent) - .FirstOrDefaultAsync().AsTask().WithTimeout(); - - Assert.Equal(StreamPosition.Start, resolvedEvent.Event.EventNumber); - Assert.Equal(_fixture.EventId, resolvedEvent.Event.EventId); - } - - public class Fixture : EventStoreClientFixture { - public readonly EventData[] Events; - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - Events = CreateTestEvents().ToArray(); - } - - public Uuid EventId => Events.Single().EventId; - - protected override async Task Given() { - await Client.CreateToStreamAsync( - Stream, - Group, - new(), - userCredentials: TestCredentials.Root); - - Subscription = Client.SubscribeToStream(Stream, Group, userCredentials: TestCredentials.TestUser1); - } - - protected override Task When() => StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events); - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_not_set_and_events_in_it.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_not_set_and_events_in_it.cs deleted file mode 100644 index cef6a28a7..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_not_set_and_events_in_it.cs +++ /dev/null @@ -1,52 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -[Obsolete] -public class connect_to_existing_with_start_from_not_set_and_events_in_it - : IClassFixture { - private const string Group = "startinbeginning1"; - - private const string Stream = nameof(connect_to_existing_with_start_from_not_set_and_events_in_it); - private readonly Fixture _fixture; - - public connect_to_existing_with_start_from_not_set_and_events_in_it(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_no_events() => - await Assert.ThrowsAsync( - () => _fixture.Subscription!.Messages.AnyAsync(message => message is PersistentSubscriptionMessage.Event) - .AsTask().WithTimeout(TimeSpan.FromMilliseconds(250))); - - public class Fixture : EventStoreClientFixture { - public readonly EventData[] Events; - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - Events = CreateTestEvents(10).ToArray(); - } - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events); - await Client.CreateToStreamAsync( - Stream, - Group, - new(), - userCredentials: TestCredentials.Root - ); - } - - protected override Task When() { - Subscription = Client.SubscribeToStream( - Stream, - Group, - userCredentials: TestCredentials.TestUser1); - return Task.CompletedTask; - } - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_not_set_and_events_in_it_then_event_written.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_not_set_and_events_in_it_then_event_written.cs deleted file mode 100644 index 08a2172d4..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_not_set_and_events_in_it_then_event_written.cs +++ /dev/null @@ -1,58 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class connect_to_existing_with_start_from_not_set_and_events_in_it_then_event_written - : IClassFixture { - private const string Group = "startinbeginning1"; - - private const string Stream = - nameof(connect_to_existing_with_start_from_not_set_and_events_in_it_then_event_written); - - private readonly Fixture _fixture; - - public connect_to_existing_with_start_from_not_set_and_events_in_it_then_event_written(Fixture fixture) => - _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_the_written_event_as_its_first_event() { - var resolvedEvent = await _fixture.Subscription!.Messages.OfType() - .Select(e => e.ResolvedEvent) - .FirstOrDefaultAsync().AsTask().WithTimeout(); - - Assert.Equal(new(10), resolvedEvent.Event.EventNumber); - Assert.Equal(_fixture.Events.Last().EventId, resolvedEvent.Event.EventId); - } - - public class Fixture : EventStoreClientFixture { - public readonly EventData[] Events; - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - Events = CreateTestEvents(11).ToArray(); - } - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events.Take(10)); - await Client.CreateToStreamAsync( - Stream, - Group, - new(), - userCredentials: TestCredentials.Root - ); - - Subscription = Client.SubscribeToStream( - Stream, - Group, - userCredentials: TestCredentials.TestUser1); - } - - protected override Task When() => - StreamsClient.AppendToStreamAsync(Stream, new StreamRevision(9), Events.Skip(10)); - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_set_to_end_position_and_events_in_it.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_set_to_end_position_and_events_in_it.cs deleted file mode 100644 index f2bf5e807..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_set_to_end_position_and_events_in_it.cs +++ /dev/null @@ -1,53 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class connect_to_existing_with_start_from_set_to_end_position_and_events_in_it - : IClassFixture { - private const string Group = "startinbeginning1"; - private const string Stream = nameof(connect_to_existing_with_start_from_set_to_end_position_and_events_in_it); - - private readonly Fixture _fixture; - - public connect_to_existing_with_start_from_set_to_end_position_and_events_in_it(Fixture fixture) => - _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_no_events() => - await Assert.ThrowsAsync( - () => _fixture.Subscription!.Messages.AnyAsync(message => message is PersistentSubscriptionMessage.Event) - .AsTask().WithTimeout(TimeSpan.FromMilliseconds(250))); - - public class Fixture : EventStoreClientFixture { - public readonly EventData[] Events; - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - Events = CreateTestEvents(10).ToArray(); - } - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events); - await Client.CreateToStreamAsync( - Stream, - Group, - new(startFrom: StreamPosition.End), - userCredentials: TestCredentials.Root - ); - } - - protected override Task When() { - Subscription = Client.SubscribeToStream( - Stream, - Group, - userCredentials: TestCredentials.TestUser1); - return Task.CompletedTask; - } - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_then_event_written.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_then_event_written.cs deleted file mode 100644 index 2e7b8a4c1..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_then_event_written.cs +++ /dev/null @@ -1,57 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_then_event_written - : IClassFixture { - private const string Group = "startinbeginning1"; - - private const string Stream = - nameof(connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_then_event_written); - - private readonly Fixture _fixture; - - public - connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_then_event_written(Fixture fixture) => - _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_the_written_event_as_its_first_event() { - var resolvedEvent = await _fixture.Subscription!.Messages.OfType() - .Select(e => e.ResolvedEvent) - .FirstOrDefaultAsync().AsTask().WithTimeout(); - - Assert.Equal(new(10), resolvedEvent.Event.EventNumber); - Assert.Equal(_fixture.Events.Last().EventId, resolvedEvent.Event.EventId); - } - - public class Fixture : EventStoreClientFixture { - public readonly EventData[] Events; - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - Events = CreateTestEvents(11).ToArray(); - } - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events.Take(10)); - await Client.CreateToStreamAsync( - Stream, - Group, - new(startFrom: StreamPosition.End), - userCredentials: TestCredentials.Root); - - Subscription = Client.SubscribeToStream(Stream, Group, userCredentials: TestCredentials.TestUser1); - } - - protected override Task When() => - StreamsClient.AppendToStreamAsync(Stream, new StreamRevision(9), Events.Skip(10)); - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_two_and_no_stream.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_two_and_no_stream.cs deleted file mode 100644 index 0199eaa3b..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_two_and_no_stream.cs +++ /dev/null @@ -1,55 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class connect_to_existing_with_start_from_two_and_no_stream - : IClassFixture { - private const string Group = "startinbeginning1"; - private const string Stream = nameof(connect_to_existing_with_start_from_two_and_no_stream); - - private readonly Fixture _fixture; - - public connect_to_existing_with_start_from_two_and_no_stream(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_event_two_as_its_first_event() { - var resolvedEvent = await _fixture.Subscription!.Messages.OfType() - .Select(e => e.ResolvedEvent) - .FirstOrDefaultAsync().AsTask().WithTimeout(); - - Assert.Equal(new(2), resolvedEvent.Event.EventNumber); - Assert.Equal(_fixture.EventId, resolvedEvent.Event.EventId); - } - - public class Fixture : EventStoreClientFixture { - public readonly EventData[] Events; - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - Events = CreateTestEvents(3).ToArray(); - } - - public Uuid EventId => Events.Last().EventId; - - protected override async Task Given() { - await Client.CreateToStreamAsync( - Stream, - Group, - new(startFrom: new StreamPosition(2)), - userCredentials: TestCredentials.Root); - - Subscription = Client.SubscribeToStream( - Stream, - Group, - userCredentials: TestCredentials.TestUser1); - } - - protected override Task When() => StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events); - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_x_set_and_events_in_it.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_x_set_and_events_in_it.cs deleted file mode 100644 index 3a7edafba..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_x_set_and_events_in_it.cs +++ /dev/null @@ -1,55 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class connect_to_existing_with_start_from_x_set_and_events_in_it - : IClassFixture { - private const string Group = "startinx2"; - private const string Stream = nameof(connect_to_existing_with_start_from_x_set_and_events_in_it); - - private readonly Fixture _fixture; - - public connect_to_existing_with_start_from_x_set_and_events_in_it(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_the_written_event_as_its_first_event() { - var resolvedEvent = await _fixture.Subscription!.Messages - .OfType() - .Select(e => e.ResolvedEvent) - .FirstOrDefaultAsync().AsTask().WithTimeout(); - Assert.Equal(new(4), resolvedEvent.Event.EventNumber); - Assert.Equal(_fixture.Events.Skip(4).First().EventId, resolvedEvent.Event.EventId); - } - - public class Fixture : EventStoreClientFixture { - public readonly EventData[] Events; - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - Events = CreateTestEvents(10).ToArray(); - } - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events.Take(10)); - await Client.CreateToStreamAsync( - Stream, - Group, - new(startFrom: new StreamPosition(4)), - userCredentials: TestCredentials.Root); - - Subscription = Client.SubscribeToStream( - Stream, - Group, - userCredentials: TestCredentials.TestUser1); - } - - protected override Task When() => - StreamsClient.AppendToStreamAsync(Stream, new StreamRevision(9), Events.Skip(10)); - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_x_set_and_events_in_it_then_event_written.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_x_set_and_events_in_it_then_event_written.cs deleted file mode 100644 index 276bae9aa..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_x_set_and_events_in_it_then_event_written.cs +++ /dev/null @@ -1,54 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class connect_to_existing_with_start_from_x_set_and_events_in_it_then_event_written - : IClassFixture { - private const string Group = "startinbeginning1"; - private const string Stream = nameof(connect_to_existing_with_start_from_x_set_and_events_in_it_then_event_written); - private readonly Fixture _fixture; - - public connect_to_existing_with_start_from_x_set_and_events_in_it_then_event_written(Fixture fixture) => - _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_the_written_event_as_its_first_event() { - var resolvedEvent = await _fixture.Subscription!.Messages.OfType() - .Select(e => e.ResolvedEvent) - .FirstOrDefaultAsync().AsTask().WithTimeout(); - Assert.Equal(new(10), resolvedEvent.Event.EventNumber); - Assert.Equal(_fixture.Events.Last().EventId, resolvedEvent.Event.EventId); - } - - public class Fixture : EventStoreClientFixture { - public readonly EventData[] Events; - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - Events = CreateTestEvents(11).ToArray(); - } - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events.Take(10)); - await Client.CreateToStreamAsync( - Stream, - Group, - new(startFrom: new StreamPosition(10)), - userCredentials: TestCredentials.Root); - - Subscription = Client.SubscribeToStream( - Stream, - Group, - userCredentials: TestCredentials.TestUser1); - } - - protected override Task When() => - StreamsClient.AppendToStreamAsync(Stream, new StreamRevision(9), Events.Skip(10)); - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_x_set_higher_than_x_and_events_in_it_then_event_written.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_x_set_higher_than_x_and_events_in_it_then_event_written.cs deleted file mode 100644 index f4b249372..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_x_set_higher_than_x_and_events_in_it_then_event_written.cs +++ /dev/null @@ -1,58 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class connect_to_existing_with_start_from_x_set_higher_than_x_and_events_in_it_then_event_written : - IClassFixture { - private const string Group = "startinbeginning1"; - private const string Stream = - nameof(connect_to_existing_with_start_from_x_set_higher_than_x_and_events_in_it_then_event_written); - - private readonly Fixture _fixture; - - public - connect_to_existing_with_start_from_x_set_higher_than_x_and_events_in_it_then_event_written(Fixture fixture) => - _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_the_written_event_as_its_first_event() { - var resolvedEvent = await _fixture.Subscription!.Messages.OfType() - .Select(e => e.ResolvedEvent) - .FirstOrDefaultAsync().AsTask().WithTimeout(); - Assert.Equal(new(11), resolvedEvent.Event.EventNumber); - Assert.Equal(_fixture.Events.Last().EventId, resolvedEvent.Event.EventId); - } - - public class Fixture : EventStoreClientFixture { - public readonly EventData[] Events; - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - Events = CreateTestEvents(12).ToArray(); - } - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events.Take(11)); - await Client.CreateToStreamAsync( - Stream, - Group, - new(startFrom: new StreamPosition(11)), - userCredentials: TestCredentials.Root); - - Subscription = Client.SubscribeToStream( - Stream, - Group, - userCredentials: TestCredentials.TestUser1); - } - - protected override Task When() => - StreamsClient.AppendToStreamAsync(Stream, new StreamRevision(10), Events.Skip(11)); - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_without_permissions.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_without_permissions.cs deleted file mode 100644 index 756de2519..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_without_permissions.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class connect_to_existing_without_permissions : IClassFixture { - private const string Stream = $"${nameof(connect_to_existing_without_permissions)}"; - private readonly Fixture _fixture; - public connect_to_existing_without_permissions(Fixture fixture) => _fixture = fixture; - - [Fact] - public Task throws_access_denied() => - Assert.ThrowsAsync( - async () => { - await using var subscription = _fixture.Client.SubscribeToStream(Stream, "agroupname55"); - await subscription.Messages.AnyAsync(); - }).WithTimeout(); - - public class Fixture : EventStoreClientFixture { - public Fixture() : base(noDefaultCredentials: true) { } - - protected override Task Given() => - Client.CreateToStreamAsync( - Stream, - "agroupname55", - new(), - userCredentials: TestCredentials.Root - ); - - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_non_existing_with_permissions.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_non_existing_with_permissions.cs deleted file mode 100644 index 3e13c3983..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_non_existing_with_permissions.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class connect_to_non_existing_with_permissions : IClassFixture { - private const string Stream = nameof(connect_to_non_existing_with_permissions); - private const string Group = "foo"; - - private readonly Fixture _fixture; - - public connect_to_non_existing_with_permissions(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task throws_persistent_subscription_not_found() { - await using var subscription = _fixture.Client.SubscribeToStream(Stream, Group, userCredentials: TestCredentials.Root); - Assert.True(await subscription.Messages.OfType() - .AnyAsync() - .AsTask() - .WithTimeout()); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_with_retries.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_with_retries.cs deleted file mode 100644 index 89995fedf..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_with_retries.cs +++ /dev/null @@ -1,60 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class connect_with_retries : IClassFixture { - private const string Group = "retries"; - private const string Stream = nameof(connect_with_retries); - - private readonly Fixture _fixture; - - public connect_with_retries(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task events_are_retried_until_success() { - var retryCount = await _fixture.Subscription!.Messages.OfType() - .SelectAwait(async e => { - if (e.RetryCount > 4) { - await _fixture.Subscription.Ack(e.ResolvedEvent); - } else { - await _fixture.Subscription.Nack(PersistentSubscriptionNakEventAction.Retry, - "Not yet tried enough times", e.ResolvedEvent); - } - - return e.RetryCount; - }) - .Where(retryCount => retryCount > 4) - .FirstOrDefaultAsync() - .AsTask() - .WithTimeout(); - - Assert.Equal(5, retryCount); - } - - public class Fixture : EventStoreClientFixture { - - public readonly EventData[] Events; - - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - Events = CreateTestEvents().ToArray(); - } - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events); - await Client.CreateToStreamAsync(Stream, Group, new(startFrom: StreamPosition.Start), - userCredentials: TestCredentials.Root); - - Subscription = Client.SubscribeToStream(Stream, Group, userCredentials: TestCredentials.TestUser1); - } - - protected override Task When() => StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events); - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connecting_to_a_persistent_subscription.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connecting_to_a_persistent_subscription.cs deleted file mode 100644 index a9dbb4b59..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connecting_to_a_persistent_subscription.cs +++ /dev/null @@ -1,47 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class connecting_to_a_persistent_subscription : IClassFixture { - private const string Group = "startinbeginning1"; - private const string Stream = nameof(connecting_to_a_persistent_subscription); - - private readonly Fixture _fixture; - - public connecting_to_a_persistent_subscription(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_the_written_event_as_its_first_event() { - var resolvedEvent = await _fixture.Subscription!.Messages.OfType() - .Select(e => e.ResolvedEvent) - .FirstOrDefaultAsync().AsTask().WithTimeout(); - Assert.Equal(new(11), resolvedEvent.Event.EventNumber); - Assert.Equal(_fixture.Events.Last().EventId, resolvedEvent.Event.EventId); - } - - public class Fixture : EventStoreClientFixture { - public readonly EventData[] Events; - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - Events = CreateTestEvents(12).ToArray(); - } - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events.Take(11)); - await Client.CreateToStreamAsync(Stream, Group, new(startFrom: new StreamPosition(11)), - userCredentials: TestCredentials.Root); - - Subscription = Client.SubscribeToStream(Stream, Group, userCredentials: TestCredentials.TestUser1); - } - - protected override Task When() => - StreamsClient.AppendToStreamAsync(Stream, new StreamRevision(10), Events.Skip(11)); - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_after_deleting_the_same.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_after_deleting_the_same.cs deleted file mode 100644 index 3e8e0a6c5..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_after_deleting_the_same.cs +++ /dev/null @@ -1,38 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class create_after_deleting_the_same - : IClassFixture { - const string Stream = nameof(create_after_deleting_the_same); - readonly Fixture _fixture; - - public create_after_deleting_the_same(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_completion_succeeds() => - await _fixture.Client.CreateToStreamAsync( - Stream, - "existing", - new(), - userCredentials: TestCredentials.Root - ); - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - - protected override async Task When() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.Any, CreateTestEvents()); - await Client.CreateToStreamAsync( - Stream, - "existing", - new(), - userCredentials: TestCredentials.Root - ); - - await Client.DeleteToStreamAsync( - Stream, - "existing", - userCredentials: TestCredentials.Root - ); - } - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_duplicate.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_duplicate.cs deleted file mode 100644 index c67748a7a..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_duplicate.cs +++ /dev/null @@ -1,37 +0,0 @@ -using Grpc.Core; - -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class create_duplicate - : IClassFixture { - const string Stream = nameof(create_duplicate); - readonly Fixture _fixture; - - public create_duplicate(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_completion_fails() { - var ex = await Assert.ThrowsAsync( - () => _fixture.Client.CreateToStreamAsync( - Stream, - "group32", - new(), - userCredentials: TestCredentials.Root - ) - ); - - Assert.Equal(StatusCode.AlreadyExists, ex.StatusCode); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - - protected override Task When() => - Client.CreateToStreamAsync( - Stream, - "group32", - new(), - userCredentials: TestCredentials.Root - ); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_on_existing_stream.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_on_existing_stream.cs deleted file mode 100644 index 6ad81a6db..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_on_existing_stream.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class create_on_existing_stream - : IClassFixture { - const string Stream = nameof(create_on_existing_stream); - readonly Fixture _fixture; - - public create_on_existing_stream(Fixture fixture) => _fixture = fixture; - - [Fact] - public Task the_completion_succeeds() => - _fixture.Client.CreateToStreamAsync( - Stream, - "existing", - new(), - userCredentials: TestCredentials.Root - ); - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - - protected override async Task When() => await StreamsClient.AppendToStreamAsync(Stream, StreamState.Any, CreateTestEvents()); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_on_non_existing_stream.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_on_non_existing_stream.cs deleted file mode 100644 index f0d7e0fba..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_on_non_existing_stream.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class create_on_non_existing_stream - : IClassFixture { - const string Stream = nameof(create_on_non_existing_stream); - readonly Fixture _fixture; - - public create_on_non_existing_stream(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_completion_succeeds() => - await _fixture.Client.CreateToStreamAsync( - Stream, - "nonexistinggroup", - new(), - userCredentials: TestCredentials.Root - ); - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_persistent_subscription_with_dont_timeout.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_persistent_subscription_with_dont_timeout.cs deleted file mode 100644 index d32c65b4c..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_persistent_subscription_with_dont_timeout.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class create_with_dont_timeout - : IClassFixture { - const string Stream = nameof(create_with_dont_timeout); - readonly Fixture _fixture; - - public create_with_dont_timeout(Fixture fixture) => _fixture = fixture; - - [Fact] - public Task the_subscription_is_created_without_error() => - _fixture.Client.CreateToStreamAsync( - Stream, - "dont-timeout", - new(messageTimeout: TimeSpan.Zero), - userCredentials: TestCredentials.Root - ); - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_without_permissions.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_without_permissions.cs deleted file mode 100644 index d2838cf34..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_without_permissions.cs +++ /dev/null @@ -1,27 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class create_without_permissions - : IClassFixture { - const string Stream = nameof(create_without_permissions); - readonly Fixture _fixture; - - public create_without_permissions(Fixture fixture) => _fixture = fixture; - - [Fact] - public Task the_completion_fails_with_access_denied() => - Assert.ThrowsAsync( - () => - _fixture.Client.CreateToStreamAsync( - Stream, - "group57", - new() - ) - ); - - public class Fixture : EventStoreClientFixture { - public Fixture() : base(noDefaultCredentials: true) { } - - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/deleting_existing_with_permissions.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/deleting_existing_with_permissions.cs deleted file mode 100644 index 4d3a0f17d..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/deleting_existing_with_permissions.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class deleting_existing_with_permissions - : IClassFixture { - const string Stream = nameof(deleting_existing_with_permissions); - readonly Fixture _fixture; - - public deleting_existing_with_permissions(Fixture fixture) => _fixture = fixture; - - [Fact] - public Task the_delete_of_group_succeeds() => - _fixture.Client.DeleteToStreamAsync( - Stream, - "groupname123", - userCredentials: TestCredentials.Root - ); - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - - protected override Task When() => - Client.CreateToStreamAsync( - Stream, - "groupname123", - new(), - userCredentials: TestCredentials.Root - ); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/deleting_existing_with_subscriber.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/deleting_existing_with_subscriber.cs deleted file mode 100644 index dae83cec6..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/deleting_existing_with_subscriber.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class deleting_existing_with_subscriber : IClassFixture { - private const string Stream = nameof(deleting_existing_with_subscriber); - private readonly Fixture _fixture; - - public deleting_existing_with_subscriber(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_subscription_is_dropped_with_not_found() { - await using var subscription = _fixture.Client.SubscribeToStream(Stream, "groupname123", userCredentials: TestCredentials.Root); - - Assert.True(await subscription.Messages.OfType().AnyAsync() - .AsTask() - .WithTimeout()); - } - - public class Fixture : EventStoreClientFixture { - protected override async Task Given() { - await Client.CreateToStreamAsync(Stream, "groupname123", new(), userCredentials: TestCredentials.Root); - } - - protected override Task When() => - Client.DeleteToStreamAsync(Stream, "groupname123", userCredentials: TestCredentials.Root); - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/deleting_nonexistent.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/deleting_nonexistent.cs deleted file mode 100644 index 58ad6bc13..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/deleting_nonexistent.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class deleting_nonexistent - : IClassFixture { - const string Stream = nameof(deleting_nonexistent); - readonly Fixture _fixture; - - public deleting_nonexistent(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_delete_fails_with_argument_exception() => - await Assert.ThrowsAsync( - () => _fixture.Client.DeleteToStreamAsync( - Stream, - Guid.NewGuid().ToString(), - userCredentials: TestCredentials.Root - ) - ); - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/deleting_without_permissions.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/deleting_without_permissions.cs deleted file mode 100644 index 31dab0ba4..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/deleting_without_permissions.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class deleting_without_permissions - : IClassFixture { - const string Stream = nameof(deleting_without_permissions); - readonly Fixture _fixture; - - public deleting_without_permissions(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_delete_fails_with_access_denied() => - await Assert.ThrowsAsync( - () => _fixture.Client.DeleteToStreamAsync( - Stream, - Guid.NewGuid().ToString() - ) - ); - - public class Fixture : EventStoreClientFixture { - public Fixture() : base(noDefaultCredentials: true) { } - - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/get_info.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/get_info.cs deleted file mode 100644 index bec3c4118..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/get_info.cs +++ /dev/null @@ -1,198 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class get_info : IClassFixture { - private const string GroupName = nameof(get_info); - private const string StreamName = nameof(get_info); - - private static readonly PersistentSubscriptionSettings _settings = new( - true, - StreamPosition.Start, - true, - TimeSpan.FromSeconds(9), - 11, - 303, - 30, - 909, - TimeSpan.FromSeconds(1), - 1, - 1, - 500, - SystemConsumerStrategies.RoundRobin - ); - - private readonly Fixture _fixture; - - public get_info(Fixture fixture) => _fixture = fixture; - - public static IEnumerable AllowedUsers() { - yield return new object[] { TestCredentials.Root }; - yield return new object[] { TestCredentials.TestUser1 }; - } - - [Theory] - [MemberData(nameof(AllowedUsers))] - public async Task returns_expected_result(UserCredentials credentials) { - var result = await _fixture.Client.GetInfoToStreamAsync(StreamName, GroupName, userCredentials: credentials); - - Assert.Equal(StreamName, result.EventSource); - Assert.Equal(GroupName, result.GroupName); - Assert.NotNull(_settings.StartFrom); - Assert.True(result.Stats.TotalItems > 0); - Assert.True(result.Stats.OutstandingMessagesCount > 0); - Assert.True(result.Stats.AveragePerSecond >= 0); - Assert.True(result.Stats.ParkedMessageCount >= 0); - Assert.True(result.Stats.AveragePerSecond >= 0); - Assert.True(result.Stats.ReadBufferCount >= 0); - Assert.True(result.Stats.RetryBufferCount >= 0); - Assert.True(result.Stats.CountSinceLastMeasurement >= 0); - Assert.True(result.Stats.TotalInFlightMessages >= 0); - Assert.NotNull(result.Stats.LastKnownEventPosition); - Assert.NotNull(result.Stats.LastCheckpointedEventPosition); - Assert.True(result.Stats.LiveBufferCount >= 0); - - Assert.NotNull(result.Connections); - Assert.NotEmpty(result.Connections); - var connection = result.Connections.First(); - Assert.NotNull(connection.From); - Assert.Equal(TestCredentials.Root.Username, connection.Username); - Assert.NotEmpty(connection.ConnectionName); - Assert.True(connection.AverageItemsPerSecond >= 0); - Assert.True(connection.TotalItems >= 0); - Assert.True(connection.CountSinceLastMeasurement >= 0); - Assert.True(connection.AvailableSlots >= 0); - Assert.True(connection.InFlightMessages >= 0); - Assert.NotNull(connection.ExtraStatistics); - Assert.NotEmpty(connection.ExtraStatistics); - - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Highest); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Mean); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Median); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Fastest); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Quintile1); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Quintile2); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Quintile3); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Quintile4); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Quintile5); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.NinetyPercent); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.NinetyFivePercent); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.NinetyNinePercent); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.NinetyNinePointFivePercent); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.NinetyNinePointNinePercent); - - Assert.NotNull(result.Settings); - Assert.Equal(_settings.StartFrom, result.Settings!.StartFrom); - Assert.Equal(_settings.ResolveLinkTos, result.Settings!.ResolveLinkTos); - Assert.Equal(_settings.ExtraStatistics, result.Settings!.ExtraStatistics); - Assert.Equal(_settings.MessageTimeout, result.Settings!.MessageTimeout); - Assert.Equal(_settings.MaxRetryCount, result.Settings!.MaxRetryCount); - Assert.Equal(_settings.LiveBufferSize, result.Settings!.LiveBufferSize); - Assert.Equal(_settings.ReadBatchSize, result.Settings!.ReadBatchSize); - Assert.Equal(_settings.HistoryBufferSize, result.Settings!.HistoryBufferSize); - Assert.Equal(_settings.CheckPointAfter, result.Settings!.CheckPointAfter); - Assert.Equal(_settings.CheckPointLowerBound, result.Settings!.CheckPointLowerBound); - Assert.Equal(_settings.CheckPointUpperBound, result.Settings!.CheckPointUpperBound); - Assert.Equal(_settings.MaxSubscriberCount, result.Settings!.MaxSubscriberCount); - Assert.Equal(_settings.ConsumerStrategyName, result.Settings!.ConsumerStrategyName); - } - - [Fact] - public async Task throws_when_given_non_existing_subscription() => - await Assert.ThrowsAsync( - async () => { - await _fixture.Client.GetInfoToStreamAsync( - "NonExisting", - "NonExisting", - userCredentials: TestCredentials.Root - ); - } - ); - - [Fact(Skip = "Unable to produce same behavior with HTTP fallback!")] - public async Task throws_with_non_existing_user() => - await Assert.ThrowsAsync( - async () => { - await _fixture.Client.GetInfoToStreamAsync( - "NonExisting", - "NonExisting", - userCredentials: TestCredentials.TestBadUser - ); - } - ); - - [Fact] - public async Task throws_with_no_credentials() => - await Assert.ThrowsAsync( - async () => { - await _fixture.Client.GetInfoToStreamAsync( - "NonExisting", - "NonExisting" - ); - } - ); - - [Fact] - public async Task returns_result_for_normal_user() { - var result = await _fixture.Client.GetInfoToStreamAsync( - StreamName, - GroupName, - userCredentials: TestCredentials.TestUser1 - ); - - Assert.NotNull(result); - } - - private void AssertKeyAndValue(IDictionary items, string key) { - Assert.True(items.ContainsKey(key)); - Assert.True(items[key] > 0); - } - - public class Fixture : EventStoreClientFixture { - private EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? _subscription; - private IAsyncEnumerator? _enumerator; - public Fixture() : base(noDefaultCredentials: true) { } - - protected override Task Given() => - Client.CreateToStreamAsync(groupName: GroupName, streamName: StreamName, settings: _settings, - userCredentials: TestCredentials.Root); - - protected override async Task When() { - var counter = 0; - _subscription = Client.SubscribeToStream(StreamName, GroupName, userCredentials: TestCredentials.Root); - _enumerator = _subscription.Messages.GetAsyncEnumerator(); - - for (var i = 0; i < 15; i++) { - await StreamsClient.AppendToStreamAsync(StreamName, StreamState.Any, - new[] { new EventData(Uuid.NewUuid(), "test-event", ReadOnlyMemory.Empty) }, - userCredentials: TestCredentials.Root); - } - - while (await _enumerator.MoveNextAsync()) { - if (_enumerator.Current is not PersistentSubscriptionMessage.Event(var resolvedEvent, _)) { - continue; - } - - counter++; - - if (counter == 1) { - await _subscription.Nack(PersistentSubscriptionNakEventAction.Park, "Test", resolvedEvent); - } - - if (counter > 10) { - return; - } - } - } - - public override async Task DisposeAsync() { - if (_enumerator is not null) { - await _enumerator.DisposeAsync(); - } - - if (_subscription is not null) { - await _subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/happy_case_catching_up_to_link_to_events_manual_ack.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/happy_case_catching_up_to_link_to_events_manual_ack.cs deleted file mode 100644 index 864eccd8a..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/happy_case_catching_up_to_link_to_events_manual_ack.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System.Text; - -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class happy_case_catching_up_to_link_to_events_manual_ack - : IClassFixture { - private const string Stream = nameof(happy_case_catching_up_to_link_to_events_manual_ack); - private const string Group = nameof(Group); - private const int BufferCount = 10; - private const int EventWriteCount = BufferCount * 2; - - private readonly Fixture _fixture; - - public happy_case_catching_up_to_link_to_events_manual_ack(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task Test() { - await _fixture.Subscription!.Messages.OfType() - .Take(_fixture.Events.Length) - .ForEachAwaitAsync(e => _fixture.Subscription.Ack(e.ResolvedEvent)) - .WithTimeout(); - } - - public class Fixture : EventStoreClientFixture { - public readonly EventData[] Events; - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - Events = CreateTestEvents(EventWriteCount) - .Select((e, i) => new EventData( - e.EventId, - SystemEventTypes.LinkTo, - Encoding.UTF8.GetBytes($"{i}@{Stream}"), - contentType: Constants.Metadata.ContentTypes.ApplicationOctetStream - )).ToArray(); - } - - protected override async Task Given() { - foreach (var e in Events) - await StreamsClient.AppendToStreamAsync(Stream, StreamState.Any, new[] { e }); - - await Client.CreateToStreamAsync(Stream, Group, new(startFrom: StreamPosition.Start, resolveLinkTos: true), - userCredentials: TestCredentials.Root); - - Subscription = Client.SubscribeToStream(Stream, Group, bufferSize: BufferCount, - userCredentials: TestCredentials.Root); - } - - protected override Task When() => Task.CompletedTask; - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/happy_case_catching_up_to_normal_events_manual_ack.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/happy_case_catching_up_to_normal_events_manual_ack.cs deleted file mode 100644 index 5bcf18171..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/happy_case_catching_up_to_normal_events_manual_ack.cs +++ /dev/null @@ -1,53 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class happy_case_catching_up_to_normal_events_manual_ack - : IClassFixture { - private const string Stream = nameof(happy_case_catching_up_to_normal_events_manual_ack); - private const string Group = nameof(Group); - private const int BufferCount = 10; - private const int EventWriteCount = BufferCount * 2; - - private readonly Fixture _fixture; - - public happy_case_catching_up_to_normal_events_manual_ack(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task Test() { - await _fixture.Subscription!.Messages.OfType() - .Take(_fixture.Events.Length) - .ForEachAwaitAsync(e => _fixture.Subscription.Ack(e.ResolvedEvent)) - .WithTimeout(); - } - - public class Fixture : EventStoreClientFixture { - public readonly EventData[] Events; - - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - - public Fixture() { - Events = CreateTestEvents(EventWriteCount).ToArray(); - } - - protected override async Task Given() { - foreach (var e in Events) - await StreamsClient.AppendToStreamAsync(Stream, StreamState.Any, new[] { e }); - - await Client.CreateToStreamAsync(Stream, Group, new(startFrom: StreamPosition.Start, resolveLinkTos: true), - userCredentials: TestCredentials.Root); - - Subscription = Client.SubscribeToStream(Stream, Group, bufferSize: BufferCount, - userCredentials: TestCredentials.Root); - } - - protected override Task When() => Task.CompletedTask; - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/happy_case_writing_and_subscribing_to_normal_events_manual_ack.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/happy_case_writing_and_subscribing_to_normal_events_manual_ack.cs deleted file mode 100644 index b4f957d47..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/happy_case_writing_and_subscribing_to_normal_events_manual_ack.cs +++ /dev/null @@ -1,52 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class happy_case_writing_and_subscribing_to_normal_events_manual_ack - : IClassFixture { - private const string Stream = nameof(happy_case_writing_and_subscribing_to_normal_events_manual_ack); - private const string Group = nameof(Group); - private const int BufferCount = 10; - private const int EventWriteCount = BufferCount * 2; - - private readonly Fixture _fixture; - - public happy_case_writing_and_subscribing_to_normal_events_manual_ack(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task Test() { - await _fixture.Subscription!.Messages.OfType() - .Take(_fixture.Events.Length) - .ForEachAwaitAsync(e => _fixture.Subscription.Ack(e.ResolvedEvent)) - .WithTimeout(); - } - - public class Fixture : EventStoreClientFixture { - public readonly EventData[] Events; - - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - Events = CreateTestEvents(EventWriteCount).ToArray(); - } - - protected override async Task Given() { - await Client.CreateToStreamAsync(Stream, Group, new(startFrom: StreamPosition.End, resolveLinkTos: true), - userCredentials: TestCredentials.Root); - - Subscription = Client.SubscribeToStream(Stream, Group, bufferSize: BufferCount, - userCredentials: TestCredentials.Root); - } - - protected override async Task When() { - foreach (var e in Events) - await StreamsClient.AppendToStreamAsync(Stream, StreamState.Any, new[] { e }); - } - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/list_with_persistent_subscriptions.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/list_with_persistent_subscriptions.cs deleted file mode 100644 index 61f93cb11..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/list_with_persistent_subscriptions.cs +++ /dev/null @@ -1,82 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class list_with_persistent_subscriptions : IClassFixture { - const int AllStreamSubscriptionCount = 4; - const int StreamSubscriptionCount = 3; - const string GroupName = nameof(list_with_persistent_subscriptions); - const string StreamName = nameof(list_with_persistent_subscriptions); - readonly Fixture _fixture; - - public list_with_persistent_subscriptions(Fixture fixture) => _fixture = fixture; - - int TotalSubscriptionCount => - SupportsPSToAll.No - ? StreamSubscriptionCount - : AllStreamSubscriptionCount + StreamSubscriptionCount; - - [Fact] - public async Task returns_subscriptions_to_stream() { - var result = (await _fixture.Client.ListToStreamAsync(StreamName, userCredentials: TestCredentials.Root)).ToList(); - Assert.Equal(StreamSubscriptionCount, result.Count); - Assert.All(result, p => Assert.Equal(StreamName, p.EventSource)); - } - - [Fact] - public async Task returns_all_subscriptions() { - var result = (await _fixture.Client.ListAllAsync(userCredentials: TestCredentials.Root)).ToList(); - Assert.Equal(TotalSubscriptionCount, result.Count); - } - - [Fact] - public async Task throws_for_non_existing() => - await Assert.ThrowsAsync( - async () => - await _fixture.Client.ListToStreamAsync("NonExistingStream", userCredentials: TestCredentials.Root) - ); - - [Fact] - public async Task throws_with_no_credentials() => - await Assert.ThrowsAsync( - async () => - await _fixture.Client.ListToStreamAsync("NonExistingStream") - ); - - [Fact] - public async Task throws_with_non_existing_user() => - await Assert.ThrowsAsync( - async () => - await _fixture.Client.ListAllAsync(userCredentials: TestCredentials.TestBadUser) - ); - - [Fact] - public async Task returns_result_with_normal_user_credentials() { - var result = await _fixture.Client.ListAllAsync(userCredentials: TestCredentials.TestUser1); - Assert.Equal(TotalSubscriptionCount, result.Count()); - } - - public class Fixture : EventStoreClientFixture { - public Fixture() : base(skipPSWarmUp: true, noDefaultCredentials: true) { } - - protected override async Task Given() { - for (var i = 0; i < StreamSubscriptionCount; i++) - await Client.CreateToStreamAsync( - StreamName, - GroupName + i, - new(), - userCredentials: TestCredentials.Root - ); - - if (SupportsPSToAll.No) - return; - - for (var i = 0; i < AllStreamSubscriptionCount; i++) - await Client.CreateToAllAsync( - GroupName + i, - new(), - userCredentials: TestCredentials.Root - ); - } - - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/list_without_persistent_subscriptions.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/list_without_persistent_subscriptions.cs deleted file mode 100644 index 7e3ec3ad6..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/list_without_persistent_subscriptions.cs +++ /dev/null @@ -1,36 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class list_without_persistent_subscriptions : IClassFixture { - readonly Fixture _fixture; - - public list_without_persistent_subscriptions(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task throws() { - if (SupportsPSToAll.No) - return; - - await Assert.ThrowsAsync( - async () => - await _fixture.Client.ListToStreamAsync("stream", userCredentials: TestCredentials.Root) - ); - } - - [Fact] - public async Task returns_empty_collection() { - if (SupportsPSToAll.No) - return; - - var result = await _fixture.Client.ListAllAsync(userCredentials: TestCredentials.Root); - - Assert.Empty(result); - } - - public class Fixture : EventStoreClientFixture { - public Fixture() : base(skipPSWarmUp: true) { } - - protected override Task Given() => Task.CompletedTask; - - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/replay_parked.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/replay_parked.cs deleted file mode 100644 index 562449e52..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/replay_parked.cs +++ /dev/null @@ -1,80 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class replay_parked : IClassFixture { - const string GroupName = nameof(replay_parked); - const string StreamName = nameof(replay_parked); - - readonly Fixture _fixture; - - public replay_parked(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task does_not_throw() { - await _fixture.Client.ReplayParkedMessagesToStreamAsync( - StreamName, - GroupName, - userCredentials: TestCredentials.Root - ); - - await _fixture.Client.ReplayParkedMessagesToStreamAsync( - StreamName, - GroupName, - 100, - userCredentials: TestCredentials.Root - ); - } - - [Fact] - public async Task throws_when_given_non_existing_subscription() => - await Assert.ThrowsAsync( - () => - _fixture.Client.ReplayParkedMessagesToStreamAsync( - "NonExisting", - "NonExisting", - userCredentials: TestCredentials.Root - ) - ); - - [Fact] - public async Task throws_with_no_credentials() => - await Assert.ThrowsAsync( - () => - _fixture.Client.ReplayParkedMessagesToStreamAsync(StreamName, GroupName) - ); - - [Fact(Skip = "Unable to produce same behavior with HTTP fallback!")] - public async Task throws_with_non_existing_user() => - await Assert.ThrowsAsync( - () => - _fixture.Client.ReplayParkedMessagesToStreamAsync( - StreamName, - GroupName, - userCredentials: TestCredentials.TestBadUser - ) - ); - - [Fact] - public async Task throws_with_normal_user_credentials() => - await Assert.ThrowsAsync( - () => - _fixture.Client.ReplayParkedMessagesToStreamAsync( - StreamName, - GroupName, - userCredentials: TestCredentials.TestUser1 - ) - ); - - public class Fixture : EventStoreClientFixture { - public Fixture() : base(noDefaultCredentials: true) { } - - protected override Task Given() => - Client.CreateToStreamAsync( - StreamName, - GroupName, - new(), - userCredentials: TestCredentials.Root - ); - - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/update_existing.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/update_existing.cs deleted file mode 100644 index b76d5b189..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/update_existing.cs +++ /dev/null @@ -1,33 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class update_existing - : IClassFixture { - const string Stream = nameof(update_existing); - const string Group = "existing"; - readonly Fixture _fixture; - - public update_existing(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_completion_succeeds() => - await _fixture.Client.UpdateToStreamAsync( - Stream, - Group, - new(), - userCredentials: TestCredentials.Root - ); - - public class Fixture : EventStoreClientFixture { - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, CreateTestEvents()); - await Client.CreateToStreamAsync( - Stream, - Group, - new(), - userCredentials: TestCredentials.Root - ); - } - - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/update_existing_with_check_point.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/update_existing_with_check_point.cs deleted file mode 100644 index 09020a8df..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/update_existing_with_check_point.cs +++ /dev/null @@ -1,95 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class update_existing_with_check_point - : IClassFixture { - private const string Stream = nameof(update_existing_with_check_point); - private const string Group = "existing-with-check-point"; - private readonly Fixture _fixture; - - public update_existing_with_check_point(Fixture fixture) { - _fixture = fixture; - } - - [Fact] - public async Task resumes_from_check_point() { - await using var subscription = - _fixture.Client.SubscribeToStream(Stream, Group, userCredentials: TestCredentials.Root); - - var resolvedEvent = await subscription.Messages - .OfType() - .Select(e => e.ResolvedEvent) - .FirstAsync() - .AsTask() - .WithTimeout(); - - Assert.Equal(_fixture.CheckPoint.Next(), resolvedEvent.Event.EventNumber); - } - - public class Fixture : EventStoreClientFixture { - private readonly EventData[] _events; - - public Fixture() { - _events = CreateTestEvents(5).ToArray(); - } - - public StreamPosition CheckPoint { get; private set; } - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, _events); - - await Client.CreateToStreamAsync(Stream, Group, - new(checkPointLowerBound: 5, checkPointAfter: TimeSpan.FromSeconds(1), startFrom: StreamPosition.Start), - userCredentials: TestCredentials.Root); - - await using var subscription = - Client.SubscribeToStream(Stream, Group, userCredentials: TestCredentials.Root); - - await using var enumerator = subscription.Messages.GetAsyncEnumerator(); - - await enumerator.MoveNextAsync(); - - await Task.WhenAll(Subscribe().WithTimeout(), WaitForCheckpoint().WithTimeout()); - - return; - - async Task Subscribe() { - var count = 0; - - while (await enumerator.MoveNextAsync()) { - if (enumerator.Current is not PersistentSubscriptionMessage.Event(var resolvedEvent, _)) { - continue; - } - - count++; - - await subscription.Ack(resolvedEvent); - if (count >= _events.Length) { - break; - } - } - } - - async Task WaitForCheckpoint() { - await using var subscription = StreamsClient.SubscribeToStream( - $"$persistentsubscription-{Stream}::{Group}-checkpoint", FromStream.Start, - userCredentials: TestCredentials.Root); - - await foreach (var message in subscription.Messages) { - if (message is not StreamMessage.Event (var resolvedEvent)) { - continue; - } - - CheckPoint = resolvedEvent.Event.Data.ParseStreamPosition(); - return; - } - } - } - - protected override async Task When() { - // Force restart of the subscription - await Client.UpdateToStreamAsync(Stream, Group, new(), userCredentials: TestCredentials.Root); - - await StreamsClient.AppendToStreamAsync(Stream, StreamState.Any, CreateTestEvents(1)); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/update_existing_with_subscribers.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/update_existing_with_subscribers.cs deleted file mode 100644 index e472aec9d..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/update_existing_with_subscribers.cs +++ /dev/null @@ -1,50 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class update_existing_with_subscribers : IClassFixture { - private const string Stream = nameof(update_existing_with_subscribers); - private const string Group = "existing"; - private readonly Fixture _fixture; - - public update_existing_with_subscribers(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task existing_subscriptions_are_dropped() { - var ex = await Assert.ThrowsAsync(async () => { - while (await _fixture.Enumerator!.MoveNextAsync()) { - } - }).WithTimeout(); - - Assert.Equal(Stream, ex.StreamName); - Assert.Equal(Group, ex.GroupName); - } - - public class Fixture : EventStoreClientFixture { - private EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? _subscription; - public IAsyncEnumerator? Enumerator { get; private set; } - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, CreateTestEvents()); - await Client.CreateToStreamAsync(Stream, Group, new(), userCredentials: TestCredentials.Root); - - _subscription = Client.SubscribeToStream(Stream, Group, userCredentials: TestCredentials.Root); - Enumerator = _subscription.Messages.GetAsyncEnumerator(); - - await Enumerator.MoveNextAsync(); - } - - protected override Task When() => - Client.UpdateToStreamAsync(Stream, Group, new(), userCredentials: TestCredentials.Root); - - public override async Task DisposeAsync() { - if (Enumerator is not null) { - await Enumerator.DisposeAsync(); - } - - if (_subscription is not null) { - await _subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/update_existing_without_permissions.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/update_existing_without_permissions.cs deleted file mode 100644 index 021aa47b9..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/update_existing_without_permissions.cs +++ /dev/null @@ -1,42 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class update_existing_without_permissions - : IClassFixture { - const string Stream = nameof(update_existing_without_permissions); - const string Group = "existing"; - readonly Fixture _fixture; - - public update_existing_without_permissions(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_completion_fails_with_access_denied() => - await Assert.ThrowsAsync( - () => _fixture.Client.UpdateToStreamAsync( - Stream, - Group, - new() - ) - ); - - public class Fixture : EventStoreClientFixture { - public Fixture() : base(noDefaultCredentials: true) { } - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync( - Stream, - StreamState.NoStream, - CreateTestEvents(), - userCredentials: TestCredentials.Root - ); - - await Client.CreateToStreamAsync( - Stream, - Group, - new(), - userCredentials: TestCredentials.Root - ); - } - - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/update_non_existent.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/update_non_existent.cs deleted file mode 100644 index 9e1f37e86..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/update_non_existent.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class update_non_existent - : IClassFixture { - const string Stream = nameof(update_non_existent); - const string Group = "nonexistent"; - readonly Fixture _fixture; - - public update_non_existent(Fixture fixture) => _fixture = fixture; - - [Regression.Fact(21, "20.x returns the wrong exception")] - public async Task the_completion_fails_with_not_found() => - await Assert.ThrowsAsync( - () => _fixture.Client.UpdateToStreamAsync( - Stream, - Group, - new(), - userCredentials: TestCredentials.Root - ) - ); - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/when_writing_and_subscribing_to_normal_events_manual_nack.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/when_writing_and_subscribing_to_normal_events_manual_nack.cs deleted file mode 100644 index 267baa684..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/when_writing_and_subscribing_to_normal_events_manual_nack.cs +++ /dev/null @@ -1,54 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -[Obsolete] -public class when_writing_and_subscribing_to_normal_events_manual_nack - : IClassFixture { - private const string Stream = nameof(when_writing_and_subscribing_to_normal_events_manual_nack); - private const string Group = nameof(Group); - private const int BufferCount = 10; - private const int EventWriteCount = BufferCount * 2; - - private readonly Fixture _fixture; - - public when_writing_and_subscribing_to_normal_events_manual_nack(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task Test() { - await _fixture.Subscription!.Messages.OfType() - .Take(1) - .ForEachAwaitAsync(async message => - await _fixture.Subscription.Nack(PersistentSubscriptionNakEventAction.Park, "fail", - message.ResolvedEvent)) - .WithTimeout(); - } - - public class Fixture : EventStoreClientFixture { - private readonly EventData[] _events; - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - _events = CreateTestEvents(EventWriteCount).ToArray(); - } - - protected override async Task Given() { - await Client.CreateToStreamAsync(Stream, Group, new(startFrom: StreamPosition.Start, resolveLinkTos: true), - userCredentials: TestCredentials.Root); - - Subscription = Client.SubscribeToStream(Stream, Group, bufferSize: BufferCount, userCredentials: TestCredentials.Root); - } - - protected override async Task When() { - foreach (var e in _events) { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.Any, new[] { e }); - } - } - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/restart_subsystem.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/restart_subsystem.cs deleted file mode 100644 index cc6047e00..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/restart_subsystem.cs +++ /dev/null @@ -1,74 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests; - -public class restart_subsystem : IClassFixture { - readonly Fixture _fixture; - - public restart_subsystem(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task does_not_throw() => await _fixture.Client.RestartSubsystemAsync(userCredentials: TestCredentials.Root); - - [Fact] - public async Task throws_with_no_credentials() => - await Assert.ThrowsAsync( - async () => - await _fixture.Client.RestartSubsystemAsync() - ); - - [Fact(Skip = "Unable to produce same behavior with HTTP fallback!")] - public async Task throws_with_non_existing_user() => - await Assert.ThrowsAsync( - async () => await _fixture.Client.RestartSubsystemAsync(userCredentials: TestCredentials.TestBadUser) - ); - - [Fact] - public async Task throws_with_normal_user_credentials() => - await Assert.ThrowsAsync(async () => await _fixture.Client.RestartSubsystemAsync(userCredentials: TestCredentials.TestUser1)); - - public class Fixture : EventStoreClientFixture { - public Fixture() : base(noDefaultCredentials: true) { } - - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} - -// namespace EventStore.Client.PersistentSubscriptions.Tests; -// -// public class restart_subsystem : IClassFixture { -// readonly InsecureClientTestFixture _fixture; -// -// public restart_subsystem(InsecureClientTestFixture fixture) => _fixture = fixture; -// -// [Fact] -// public async Task does_not_throw() => -// await _fixture.PersistentSubscriptions.RestartSubsystemAsync(userCredentials: TestCredentials.Root); -// -// [Fact] -// public async Task throws_with_no_credentials() => -// await Assert.ThrowsAsync( -// async () => -// await _fixture.PersistentSubscriptions.RestartSubsystemAsync() -// ); -// -// [Fact(Skip = "Unable to produce same behavior with HTTP fallback!")] -// public async Task throws_with_non_existing_user() => -// await Assert.ThrowsAsync( -// async () => await _fixture.PersistentSubscriptions.RestartSubsystemAsync(userCredentials: TestCredentials.TestBadUser) -// ); -// -// [Fact] -// public async Task throws_with_normal_user_credentials() { -// await _fixture.Users.CreateUserWithRetry( -// TestCredentials.TestUser1.Username!, -// TestCredentials.TestUser1.Username!, -// Array.Empty(), -// TestCredentials.TestUser1.Password!, -// TestCredentials.Root -// ); -// -// await Assert.ThrowsAsync( -// async () => await _fixture.PersistentSubscriptions.RestartSubsystemAsync(userCredentials: TestCredentials.TestUser1) -// ); -// } -// } \ No newline at end of file diff --git a/test/EventStore.Client.Plugins.Tests/EventStore.Client.Plugins.Tests.csproj b/test/EventStore.Client.Plugins.Tests/EventStore.Client.Plugins.Tests.csproj deleted file mode 100644 index dac52c701..000000000 --- a/test/EventStore.Client.Plugins.Tests/EventStore.Client.Plugins.Tests.csproj +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/test/EventStore.Client.ProjectionManagement.Tests/AssemblyInfo.cs b/test/EventStore.Client.ProjectionManagement.Tests/AssemblyInfo.cs deleted file mode 100644 index b0b47aa73..000000000 --- a/test/EventStore.Client.ProjectionManagement.Tests/AssemblyInfo.cs +++ /dev/null @@ -1 +0,0 @@ -[assembly: CollectionBehavior(DisableTestParallelization = true)] \ No newline at end of file diff --git a/test/EventStore.Client.ProjectionManagement.Tests/EventStore.Client.ProjectionManagement.Tests.csproj b/test/EventStore.Client.ProjectionManagement.Tests/EventStore.Client.ProjectionManagement.Tests.csproj deleted file mode 100644 index dac52c701..000000000 --- a/test/EventStore.Client.ProjectionManagement.Tests/EventStore.Client.ProjectionManagement.Tests.csproj +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/test/EventStore.Client.ProjectionManagement.Tests/EventStoreClientFixture.cs b/test/EventStore.Client.ProjectionManagement.Tests/EventStoreClientFixture.cs deleted file mode 100644 index 62d9ba053..000000000 --- a/test/EventStore.Client.ProjectionManagement.Tests/EventStoreClientFixture.cs +++ /dev/null @@ -1,50 +0,0 @@ -namespace EventStore.Client.ProjectionManagement.Tests; - -public abstract class EventStoreClientFixture : EventStoreClientFixtureBase { - protected EventStoreClientFixture(EventStoreClientSettings? settings = null, bool noDefaultCredentials = false) : - base( - settings, - new Dictionary { - ["EVENTSTORE_RUN_PROJECTIONS"] = "ALL", - ["EVENTSTORE_START_STANDARD_PROJECTIONS"] = "True" - }, - noDefaultCredentials - ) { - Client = new(Settings); - UserManagementClient = new(Settings); - StreamsClient = new(Settings); - } - - public EventStoreUserManagementClient UserManagementClient { get; } - public EventStoreClient StreamsClient { get; } - public EventStoreProjectionManagementClient Client { get; } - - protected virtual bool RunStandardProjections => true; - - protected override async Task OnServerUpAsync() { - await StreamsClient.WarmUp(); - await UserManagementClient.WarmUp(); - await Client.WarmUp(); - await UserManagementClient.CreateUserWithRetry( - TestCredentials.TestUser1.Username!, - TestCredentials.TestUser1.Username!, - Array.Empty(), - TestCredentials.TestUser1.Password!, - TestCredentials.Root - ).WithTimeout(); - - await StandardProjections.Created(Client).WithTimeout(TimeSpan.FromMinutes(2)); - - if (RunStandardProjections) - await Task - .WhenAll(StandardProjections.Names.Select(name => Client.EnableAsync(name, userCredentials: TestCredentials.Root))) - .WithTimeout(TimeSpan.FromMinutes(2)); - } - - public override async Task DisposeAsync() { - await StreamsClient.DisposeAsync(); - await UserManagementClient.DisposeAsync(); - await Client.DisposeAsync(); - await base.DisposeAsync(); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.ProjectionManagement.Tests/StandardProjections.cs b/test/EventStore.Client.ProjectionManagement.Tests/StandardProjections.cs deleted file mode 100644 index 4f57a0ae2..000000000 --- a/test/EventStore.Client.ProjectionManagement.Tests/StandardProjections.cs +++ /dev/null @@ -1,30 +0,0 @@ -namespace EventStore.Client.ProjectionManagement.Tests; - -static class StandardProjections { - public static readonly string[] Names = { - "$streams", - "$stream_by_category", - "$by_category", - "$by_event_type", - "$by_correlation_id" - }; - - public static Task Created(EventStoreProjectionManagementClient client) { - var systemProjectionsReady = Names.Select( - async name => { - var ready = false; - - while (!ready) { - var result = await client.GetStatusAsync(name, userCredentials: TestCredentials.Root); - - if (result?.Status.Contains("Running") ?? false) - ready = true; - else - await Task.Delay(100); - } - } - ); - - return Task.WhenAll(systemProjectionsReady); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.ProjectionManagement.Tests/abort.cs b/test/EventStore.Client.ProjectionManagement.Tests/abort.cs deleted file mode 100644 index 1983a79b6..000000000 --- a/test/EventStore.Client.ProjectionManagement.Tests/abort.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace EventStore.Client.ProjectionManagement.Tests; - -public class @abort : IClassFixture { - readonly Fixture _fixture; - - public abort(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task status_is_aborted() { - var name = StandardProjections.Names.First(); - await _fixture.Client.AbortAsync(name, userCredentials: TestCredentials.Root); - var result = await _fixture.Client.GetStatusAsync(name, userCredentials: TestCredentials.Root); - Assert.NotNull(result); - Assert.Contains(new[] { "Aborted/Stopped", "Stopped" }, x => x == result!.Status); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.ProjectionManagement.Tests/create.cs b/test/EventStore.Client.ProjectionManagement.Tests/create.cs deleted file mode 100644 index e8f9c21d2..000000000 --- a/test/EventStore.Client.ProjectionManagement.Tests/create.cs +++ /dev/null @@ -1,35 +0,0 @@ -namespace EventStore.Client.ProjectionManagement.Tests; - -public class @create : IClassFixture { - readonly Fixture _fixture; - - public create(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task one_time() => - await _fixture.Client.CreateOneTimeAsync("fromAll().when({$init: function (state, ev) {return {};}});", userCredentials: TestCredentials.Root); - - [Theory] - [InlineData(true)] - [InlineData(false)] - public async Task continuous(bool trackEmittedStreams) => - await _fixture.Client.CreateContinuousAsync( - $"{nameof(continuous)}_{trackEmittedStreams}", - "fromAll().when({$init: function (state, ev) {return {};}});", - trackEmittedStreams, - userCredentials: TestCredentials.Root - ); - - [Fact] - public async Task transient() => - await _fixture.Client.CreateTransientAsync( - nameof(transient), - "fromAll().when({$init: function (state, ev) {return {};}});", - userCredentials: TestCredentials.Root - ); - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.ProjectionManagement.Tests/disable.cs b/test/EventStore.Client.ProjectionManagement.Tests/disable.cs deleted file mode 100644 index bd03a2847..000000000 --- a/test/EventStore.Client.ProjectionManagement.Tests/disable.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace EventStore.Client.ProjectionManagement.Tests; - -public class @disable : IClassFixture { - readonly Fixture _fixture; - - public disable(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task status_is_stopped() { - var name = StandardProjections.Names.First(); - await _fixture.Client.DisableAsync(name, userCredentials: TestCredentials.Root); - var result = await _fixture.Client.GetStatusAsync(name, userCredentials: TestCredentials.Root); - Assert.NotNull(result); - Assert.Contains(new[] { "Aborted/Stopped", "Stopped" }, x => x == result!.Status); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.ProjectionManagement.Tests/enable.cs b/test/EventStore.Client.ProjectionManagement.Tests/enable.cs deleted file mode 100644 index 0afecaaa7..000000000 --- a/test/EventStore.Client.ProjectionManagement.Tests/enable.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace EventStore.Client.ProjectionManagement.Tests; - -public class @enable : IClassFixture { - readonly Fixture _fixture; - - public enable(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task status_is_running() { - var name = StandardProjections.Names.First(); - await _fixture.Client.EnableAsync(name, userCredentials: TestCredentials.Root); - var result = await _fixture.Client.GetStatusAsync(name, userCredentials: TestCredentials.Root); - Assert.NotNull(result); - Assert.Equal("Running", result!.Status); - } - - public class Fixture : EventStoreClientFixture { - protected override bool RunStandardProjections => false; - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.ProjectionManagement.Tests/get_result.cs b/test/EventStore.Client.ProjectionManagement.Tests/get_result.cs deleted file mode 100644 index d664862b5..000000000 --- a/test/EventStore.Client.ProjectionManagement.Tests/get_result.cs +++ /dev/null @@ -1,51 +0,0 @@ -namespace EventStore.Client.ProjectionManagement.Tests; - -public class get_result : IClassFixture { - readonly Fixture _fixture; - - public get_result(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task returns_expected_result() { - Result? result = null; - - await AssertEx.IsOrBecomesTrue( - async () => { - result = await _fixture.Client - .GetResultAsync(nameof(get_result), userCredentials: TestCredentials.TestUser1); - - return result.Count > 0; - } - ); - - Assert.NotNull(result); - Assert.Equal(1, result!.Count); - } - - class Result { - public int Count { get; set; } - } - - public class Fixture : EventStoreClientFixture { - static readonly string Projection = $@" -fromStream('{nameof(get_result)}').when({{ - ""$init"": function() {{ return {{ Count: 0 }}; }}, - ""$any"": function(s, e) {{ s.Count++; return s; }} -}}); -"; - - protected override Task Given() => - Client.CreateContinuousAsync( - nameof(get_result), - Projection, - userCredentials: TestCredentials.Root - ); - - protected override async Task When() => - await StreamsClient.AppendToStreamAsync( - nameof(get_result), - StreamState.NoStream, - CreateTestEvents() - ); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.ProjectionManagement.Tests/get_state.cs b/test/EventStore.Client.ProjectionManagement.Tests/get_state.cs deleted file mode 100644 index 2295ed722..000000000 --- a/test/EventStore.Client.ProjectionManagement.Tests/get_state.cs +++ /dev/null @@ -1,51 +0,0 @@ -namespace EventStore.Client.ProjectionManagement.Tests; - -public class get_state : IClassFixture { - readonly Fixture _fixture; - - public get_state(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task returns_expected_result() { - Result? result = null; - - await AssertEx.IsOrBecomesTrue( - async () => { - result = await _fixture.Client - .GetStateAsync(nameof(get_state), userCredentials: TestCredentials.TestUser1); - - return result.Count > 0; - } - ); - - Assert.NotNull(result); - Assert.Equal(1, result!.Count); - } - - class Result { - public int Count { get; set; } - } - - public class Fixture : EventStoreClientFixture { - static readonly string Projection = $@" -fromStream('{nameof(get_state)}').when({{ - ""$init"": function() {{ return {{ Count: 0 }}; }}, - ""$any"": function(s, e) {{ s.Count++; return s; }} -}}); -"; - - protected override Task Given() => - Client.CreateContinuousAsync( - nameof(get_state), - Projection, - userCredentials: TestCredentials.Root - ); - - protected override Task When() => - StreamsClient.AppendToStreamAsync( - nameof(get_state), - StreamState.NoStream, - CreateTestEvents() - ); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.ProjectionManagement.Tests/get_status.cs b/test/EventStore.Client.ProjectionManagement.Tests/get_status.cs deleted file mode 100644 index 7382a758b..000000000 --- a/test/EventStore.Client.ProjectionManagement.Tests/get_status.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace EventStore.Client.ProjectionManagement.Tests; - -public class get_status : IClassFixture { - readonly Fixture _fixture; - - public get_status(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task returns_expected_result() { - var name = StandardProjections.Names.First(); - var result = await _fixture.Client.GetStatusAsync(name, userCredentials: TestCredentials.TestUser1); - - Assert.NotNull(result); - Assert.Equal(name, result!.Name); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.ProjectionManagement.Tests/list_all_projections.cs b/test/EventStore.Client.ProjectionManagement.Tests/list_all_projections.cs deleted file mode 100644 index cac2e85da..000000000 --- a/test/EventStore.Client.ProjectionManagement.Tests/list_all_projections.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace EventStore.Client.ProjectionManagement.Tests; - -public class list_all_projections : IClassFixture { - readonly Fixture _fixture; - - public list_all_projections(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task returns_expected_result() { - var result = await _fixture.Client.ListAllAsync(userCredentials: TestCredentials.Root) - .ToArrayAsync(); - - Assert.Equal(result.Select(x => x.Name).OrderBy(x => x), StandardProjections.Names.OrderBy(x => x)); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.ProjectionManagement.Tests/list_continuous_projections.cs b/test/EventStore.Client.ProjectionManagement.Tests/list_continuous_projections.cs deleted file mode 100644 index c96ed825f..000000000 --- a/test/EventStore.Client.ProjectionManagement.Tests/list_continuous_projections.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace EventStore.Client.ProjectionManagement.Tests; - -public class list_continuous_projections : IClassFixture { - readonly Fixture _fixture; - - public list_continuous_projections(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task returns_expected_result() { - var result = await _fixture.Client.ListContinuousAsync(userCredentials: TestCredentials.Root) - .ToArrayAsync(); - - Assert.Equal( - result.Select(x => x.Name).OrderBy(x => x), - StandardProjections.Names.Concat(new[] { nameof(list_continuous_projections) }).OrderBy(x => x) - ); - - Assert.True(result.All(x => x.Mode == "Continuous")); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => - Client.CreateContinuousAsync( - nameof(list_continuous_projections), - "fromAll().when({$init: function (state, ev) {return {};}});", - userCredentials: TestCredentials.Root - ); - - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.ProjectionManagement.Tests/list_one_time_projections.cs b/test/EventStore.Client.ProjectionManagement.Tests/list_one_time_projections.cs deleted file mode 100644 index d88d68b5c..000000000 --- a/test/EventStore.Client.ProjectionManagement.Tests/list_one_time_projections.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace EventStore.Client.ProjectionManagement.Tests; - -public class list_one_time_projections : IClassFixture { - readonly Fixture _fixture; - - public list_one_time_projections(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task returns_expected_result() { - var result = await _fixture.Client.ListOneTimeAsync(userCredentials: TestCredentials.Root) - .ToArrayAsync(); - - var details = Assert.Single(result); - Assert.Equal("OneTime", details.Mode); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => - Client.CreateOneTimeAsync("fromAll().when({$init: function (state, ev) {return {};}});", userCredentials: TestCredentials.Root); - - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.ProjectionManagement.Tests/reset.cs b/test/EventStore.Client.ProjectionManagement.Tests/reset.cs deleted file mode 100644 index 3dbfc15a5..000000000 --- a/test/EventStore.Client.ProjectionManagement.Tests/reset.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace EventStore.Client.ProjectionManagement.Tests; - -public class @reset : IClassFixture { - readonly Fixture _fixture; - - public reset(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task status_is_running() { - var name = StandardProjections.Names.First(); - await _fixture.Client.ResetAsync(name, userCredentials: TestCredentials.Root); - var result = await _fixture.Client.GetStatusAsync(name, userCredentials: TestCredentials.Root); - - Assert.NotNull(result); - Assert.Equal("Running", result!.Status); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.ProjectionManagement.Tests/restart_subsystem.cs b/test/EventStore.Client.ProjectionManagement.Tests/restart_subsystem.cs deleted file mode 100644 index d10ba1545..000000000 --- a/test/EventStore.Client.ProjectionManagement.Tests/restart_subsystem.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace EventStore.Client.ProjectionManagement.Tests; - -public class restart_subsystem : IClassFixture { - readonly Fixture _fixture; - - public restart_subsystem(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task does_not_throw() => await _fixture.Client.RestartSubsystemAsync(userCredentials: TestCredentials.Root); - - [Fact] - public async Task throws_when_given_no_credentials() => await Assert.ThrowsAsync(() => _fixture.Client.RestartSubsystemAsync()); - - public class Fixture : EventStoreClientFixture { - public Fixture() : base(noDefaultCredentials: true) { } - - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.ProjectionManagement.Tests/update.cs b/test/EventStore.Client.ProjectionManagement.Tests/update.cs deleted file mode 100644 index ba8b682ad..000000000 --- a/test/EventStore.Client.ProjectionManagement.Tests/update.cs +++ /dev/null @@ -1,30 +0,0 @@ -namespace EventStore.Client.ProjectionManagement.Tests; - -public class @update : IClassFixture { - readonly Fixture _fixture; - - public update(Fixture fixture) => _fixture = fixture; - - [Theory] - [InlineData(true)] - [InlineData(false)] - [InlineData(null)] - public async Task returns_expected_result(bool? emitEnabled) => - await _fixture.Client.UpdateAsync( - nameof(update), - "fromAll().when({$init: function (s, e) {return {};}});", - emitEnabled, - userCredentials: TestCredentials.Root - ); - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => - Client.CreateContinuousAsync( - nameof(update), - "fromAll().when({$init: function (state, ev) {return {};}});", - userCredentials: TestCredentials.Root - ); - - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/Append/append_to_stream_limits.cs b/test/EventStore.Client.Streams.Tests/Append/append_to_stream_limits.cs deleted file mode 100644 index 6bdd3fbb8..000000000 --- a/test/EventStore.Client.Streams.Tests/Append/append_to_stream_limits.cs +++ /dev/null @@ -1,54 +0,0 @@ -namespace EventStore.Client.Streams.Tests.Append; - -[Trait("Category", "Target:Stream")] -[Trait("Category", "Operation:Append")] -public class append_to_stream_limits(ITestOutputHelper output, StreamLimitsFixture fixture) : EventStoreTests(output, fixture) { - [Fact] - public async Task succeeds_when_size_is_less_than_max_append_size() { - var stream = Fixture.GetStreamName(); - - var (events, size) = Fixture.CreateTestEventsUpToMaxSize(StreamLimitsFixture.MaxAppendSize - 1); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - } - - [Fact] - public async Task fails_when_size_exceeds_max_append_size() { - var stream = Fixture.GetStreamName(); - - var eventsAppendSize = StreamLimitsFixture.MaxAppendSize * 2; - - // beware of the size of the events... - var (events, size) = Fixture.CreateTestEventsUpToMaxSize(eventsAppendSize); - - size.ShouldBeGreaterThan(StreamLimitsFixture.MaxAppendSize); - - var ex = await Fixture.Streams - .AppendToStreamAsync(stream, StreamState.NoStream, events) - .ShouldThrowAsync(); - - ex.MaxAppendSize.ShouldBe(StreamLimitsFixture.MaxAppendSize); - } -} - -public class StreamLimitsFixture() : EventStoreFixture(x => x.WithMaxAppendSize(MaxAppendSize)) { - public const uint MaxAppendSize = 64; - - public (IEnumerable Events, uint size) CreateTestEventsUpToMaxSize(uint maxSize) { - var size = 0; - var events = new List(); - - foreach (var evt in CreateTestEvents(int.MaxValue)) { - size += evt.Data.Length; - - if (size >= maxSize) { - size -= evt.Data.Length; - break; - } - - events.Add(evt); - } - - return (events, (uint)size); - } -} diff --git a/test/EventStore.Client.Streams.Tests/Append/append_to_stream_retry.cs b/test/EventStore.Client.Streams.Tests/Append/append_to_stream_retry.cs deleted file mode 100644 index d67240c49..000000000 --- a/test/EventStore.Client.Streams.Tests/Append/append_to_stream_retry.cs +++ /dev/null @@ -1,37 +0,0 @@ -using Polly; -using Polly.Contrib.WaitAndRetry; - -namespace EventStore.Client.Streams.Tests.Append; - -[Trait("Category", "Target:Stream")] -[Trait("Category", "Operation:Append")] -public class append_to_stream_retry(ITestOutputHelper output, StreamRetryFixture fixture) : EventStoreTests(output, fixture) { - [Fact] - public async Task can_retry() { - var stream = Fixture.GetStreamName(); - - // can definitely write without throwing - var result = await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents()); - - result.NextExpectedStreamRevision.ShouldBe(new(0)); - - await Fixture.Service.Restart(); - - // write can be retried - var writeResult = await Policy - .Handle() - .WaitAndRetryAsync( - Backoff.LinearBackoff(TimeSpan.FromMilliseconds(250), 10), - (ex, ts) => Fixture.Log.Debug("Error writing events to stream. Retrying. Reason: {Message}.", ex.Message) - ) - .ExecuteAsync(() => Fixture.Streams.AppendToStreamAsync(stream, result.NextExpectedStreamRevision, Fixture.CreateTestEvents())); - - Fixture.Log.Information("Successfully wrote events to stream {Stream}.", stream); - - writeResult.NextExpectedStreamRevision.ShouldBe(new(1)); - } -} - -public class StreamRetryFixture() : EventStoreFixture( - x => x.RunInMemory(false).With(o => o.ClientSettings.ConnectivitySettings.MaxDiscoverAttempts = 2) -); \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/Append/append_to_stream_with_tls_ca_file.cs b/test/EventStore.Client.Streams.Tests/Append/append_to_stream_with_tls_ca_file.cs deleted file mode 100644 index 2fdc983ba..000000000 --- a/test/EventStore.Client.Streams.Tests/Append/append_to_stream_with_tls_ca_file.cs +++ /dev/null @@ -1,35 +0,0 @@ -namespace EventStore.Client.Streams.Tests.Append; - -[Trait("Category", "Target:Stream")] -[Trait("Category", "Operation:Append")] -public class append_to_stream_with_tls_ca_file(ITestOutputHelper output, EventStoreFixture fixture) - : EventStoreTests(output, fixture) { - public static IEnumerable CertPaths => - new List { - new object[] { Path.Combine("certs", "ca", "ca.crt") }, - new object[] { Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "certs", "ca", "ca.crt") }, - }; - - [Theory] - [MemberData(nameof(CertPaths))] - private async Task TestAppendWithCaFile(string certificateFilePath) { - Fixture.Log.Information($"Using certificate: {certificateFilePath}"); - - var connectionString = - $"esdb://admin:changeit@localhost:2113/?tls=true&tlsVerifyCert=true&tlsCAFile={certificateFilePath}"; - - var settings = EventStoreClientSettings.Create(connectionString); - - var client = new EventStoreClient(settings); - - var appendResult = await client.AppendToStreamAsync( - "some-stream", - StreamState.Any, - new[] { new EventData(Uuid.NewUuid(), "some-event", default) } - ); - - appendResult.ShouldNotBeNull(); - - await client.DisposeAsync(); - } -} diff --git a/test/EventStore.Client.Streams.Tests/Append/appending_to_implicitly_created_stream.cs b/test/EventStore.Client.Streams.Tests/Append/appending_to_implicitly_created_stream.cs deleted file mode 100644 index 59ab89df0..000000000 --- a/test/EventStore.Client.Streams.Tests/Append/appending_to_implicitly_created_stream.cs +++ /dev/null @@ -1,266 +0,0 @@ -namespace EventStore.Client.Streams.Tests.Append; - -[Trait("Category", "Target:Stream")] -[Trait("Category", "Operation:Append")] -public class appending_to_implicitly_created_stream(ITestOutputHelper output, EventStoreFixture fixture) : EventStoreTests(output, fixture) { - [Fact] - public async Task sequence_0em1_1e0_2e1_3e2_4e3_5e4_0em1_idempotent() { - var stream = Fixture.GetStreamName(); - - var events = Fixture.CreateTestEvents(6).ToArray(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(1)); - - var count = await Fixture.Streams - .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); - - Assert.Equal(events.Length, count); - } - - [Fact] - public async Task sequence_0em1_1e0_2e1_3e2_4e3_4e4_0any_idempotent() { - var stream = Fixture.GetStreamName(); - - var events = Fixture.CreateTestEvents(6).ToArray(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, events.Take(1)); - - var count = await Fixture.Streams - .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); - - Assert.Equal(events.Length, count); - } - - [Fact] - public async Task sequence_0em1_1e0_2e1_3e2_4e3_5e4_0e5_non_idempotent() { - var stream = Fixture.GetStreamName(); - - var events = Fixture.CreateTestEvents(6).ToArray(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - await Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(5), events.Take(1)); - - var count = await Fixture.Streams - .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 2).CountAsync(); - - Assert.Equal(events.Length + 1, count); - } - - [Fact] - public async Task sequence_0em1_1e0_2e1_3e2_4e3_5e4_0e6_throws_wev() { - var stream = Fixture.GetStreamName(); - - var events = Fixture.CreateTestEvents(6).ToArray(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - - await Assert.ThrowsAsync(() => Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(6), events.Take(1))); - } - - [Fact] - public async Task sequence_0em1_1e0_2e1_3e2_4e3_5e4_0e6_returns_wev() { - var stream = Fixture.GetStreamName(); - - var events = Fixture.CreateTestEvents(6).ToArray(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - - var writeResult = await Fixture.Streams.AppendToStreamAsync( - stream, - new StreamRevision(6), - events.Take(1), - options => options.ThrowOnAppendFailure = false - ); - - Assert.IsType(writeResult); - } - - [Fact] - public async Task sequence_0em1_1e0_2e1_3e2_4e3_5e4_0e4_throws_wev() { - var stream = Fixture.GetStreamName(); - - var events = Fixture.CreateTestEvents(6).ToArray(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - - await Assert.ThrowsAsync(() => Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(4), events.Take(1))); - } - - [Fact] - public async Task sequence_0em1_1e0_2e1_3e2_4e3_5e4_0e4_returns_wev() { - var stream = Fixture.GetStreamName(); - - var events = Fixture.CreateTestEvents(6).ToArray(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - - var writeResult = await Fixture.Streams.AppendToStreamAsync( - stream, - new StreamRevision(4), - events.Take(1), - options => options.ThrowOnAppendFailure = false - ); - - Assert.IsType(writeResult); - } - - [Fact] - public async Task sequence_0em1_0e0_non_idempotent() { - var stream = Fixture.GetStreamName(); - - var events = Fixture.CreateTestEvents().ToArray(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - await Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(0), events.Take(1)); - - var count = await Fixture.Streams - .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 2).CountAsync(); - - Assert.Equal(events.Length + 1, count); - } - - [Fact] - public async Task sequence_0em1_0any_idempotent() { - var stream = Fixture.GetStreamName(); - - var events = Fixture.CreateTestEvents().ToArray(); - - await Task.Delay(TimeSpan.FromSeconds(30)); - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, events.Take(1)); - - var count = await Fixture.Streams - .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); - - Assert.Equal(events.Length, count); - } - - [Fact] - public async Task sequence_0em1_0em1_idempotent() { - var stream = Fixture.GetStreamName(); - - var events = Fixture.CreateTestEvents().ToArray(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(1)); - - var count = await Fixture.Streams - .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); - - Assert.Equal(events.Length, count); - } - - [Fact] - public async Task sequence_0em1_1e0_2e1_1any_1any_idempotent() { - var stream = Fixture.GetStreamName(); - - var events = Fixture.CreateTestEvents(3).ToArray(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, events.Skip(1).Take(1)); - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, events.Skip(1).Take(1)); - - var count = await Fixture.Streams - .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); - - Assert.Equal(events.Length, count); - } - - [Fact] - public async Task sequence_S_0em1_1em1_E_S_0em1_E_idempotent() { - var stream = Fixture.GetStreamName(); - - var events = Fixture.CreateTestEvents(2).ToArray(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(1)); - - var count = await Fixture.Streams - .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); - - Assert.Equal(events.Length, count); - } - - [Fact] - public async Task sequence_S_0em1_1em1_E_S_0any_E_idempotent() { - var stream = Fixture.GetStreamName(); - - var events = Fixture.CreateTestEvents(2).ToArray(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, events.Take(1)); - - var count = await Fixture.Streams - .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); - - Assert.Equal(events.Length, count); - } - - [Fact] - public async Task sequence_S_0em1_1em1_E_S_1e0_E_idempotent() { - var stream = Fixture.GetStreamName(); - - var events = Fixture.CreateTestEvents(2).ToArray(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - - await Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(0), events.Skip(1)); - - var count = await Fixture.Streams - .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); - - Assert.Equal(events.Length, count); - } - - [Fact] - public async Task sequence_S_0em1_1em1_E_S_1any_E_idempotent() { - var stream = Fixture.GetStreamName(); - - var events = Fixture.CreateTestEvents(2).ToArray(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, events.Skip(1).Take(1)); - - var count = await Fixture.Streams - .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); - - Assert.Equal(events.Length, count); - } - - [Fact] - public async Task sequence_S_0em1_1em1_E_S_0em1_1em1_2em1_E_idempotancy_fail_throws() { - var stream = Fixture.GetStreamName(); - - var events = Fixture.CreateTestEvents(3).ToArray(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(2)); - - await Assert.ThrowsAsync( - () => Fixture.Streams.AppendToStreamAsync( - stream, - StreamState.NoStream, - events - ) - ); - } - - [Fact] - public async Task sequence_S_0em1_1em1_E_S_0em1_1em1_2em1_E_idempotancy_fail_returns() { - var stream = Fixture.GetStreamName(); - - var events = Fixture.CreateTestEvents(3).ToArray(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(2)); - - var writeResult = await Fixture.Streams.AppendToStreamAsync( - stream, - StreamState.NoStream, - events, - options => options.ThrowOnAppendFailure = false - ); - - Assert.IsType(writeResult); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/Append/sending_and_receiving_large_messages.cs b/test/EventStore.Client.Streams.Tests/Append/sending_and_receiving_large_messages.cs deleted file mode 100644 index 099ece45c..000000000 --- a/test/EventStore.Client.Streams.Tests/Append/sending_and_receiving_large_messages.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Grpc.Core; - -namespace EventStore.Client.Streams.Tests.Append; - -[Trait("Category", "Target:Stream")] -[Trait("Category", "Operation:Append")] -public class sending_and_receiving_large_messages(ITestOutputHelper output, sending_and_receiving_large_messages.CustomFixture fixture) - : EventStoreTests(output, fixture) { - [Fact] - public async Task over_the_hard_limit() { - var streamName = Fixture.GetStreamName(); - var largeEvent = Fixture.CreateTestEvents() - .Select(e => new EventData(e.EventId, "-", new byte[CustomFixture.MaximumSize + 1])); - - var ex = await Assert.ThrowsAsync( - () => Fixture.Streams.AppendToStreamAsync( - streamName, - StreamState.NoStream, - largeEvent - ) - ); - - Assert.Equal(StatusCode.ResourceExhausted, ex.StatusCode); - } - - public class CustomFixture() : EventStoreFixture(x => x.WithMaxAppendSize(MaximumSize)) { - public const int MaximumSize = 16 * 1024 * 1024 - 10000; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/AssemblyInfo.cs b/test/EventStore.Client.Streams.Tests/AssemblyInfo.cs deleted file mode 100644 index b0b47aa73..000000000 --- a/test/EventStore.Client.Streams.Tests/AssemblyInfo.cs +++ /dev/null @@ -1 +0,0 @@ -[assembly: CollectionBehavior(DisableTestParallelization = true)] \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/DependencyInjectionTests.cs b/test/EventStore.Client.Streams.Tests/DependencyInjectionTests.cs deleted file mode 100644 index 96512557b..000000000 --- a/test/EventStore.Client.Streams.Tests/DependencyInjectionTests.cs +++ /dev/null @@ -1,75 +0,0 @@ -using Grpc.Core.Interceptors; -using Microsoft.Extensions.DependencyInjection; - -namespace EventStore.Client.Streams.Tests; - -[Trait("Category", "UnitTest")] -public class DependencyInjectionTests { - [Fact] - public void Register() => - new ServiceCollection() - .AddEventStoreClient() - .BuildServiceProvider() - .GetRequiredService(); - - [Fact] - public void RegisterWithConnectionString() => - new ServiceCollection() - .AddEventStoreClient("esdb://localhost:2113?tls=false") - .BuildServiceProvider() - .GetRequiredService(); - - [Fact] - public void RegisterWithConnectionStringFactory() => - new ServiceCollection() - .AddEventStoreClient(provider => "esdb://localhost:2113?tls=false") - .BuildServiceProvider() - .GetRequiredService(); - - [Fact] - public void RegisterWithUri() => - new ServiceCollection() - .AddEventStoreClient(new Uri("https://localhost:1234")) - .BuildServiceProvider() - .GetRequiredService(); - - [Fact] - public void RegisterWithUriFactory() => - new ServiceCollection() - .AddEventStoreClient(provider => new Uri("https://localhost:1234")) - .BuildServiceProvider() - .GetRequiredService(); - - [Fact] - public void RegisterWithSettings() => - new ServiceCollection() - .AddEventStoreClient(settings => { }) - .BuildServiceProvider() - .GetRequiredService(); - - [Fact] - public void RegisterWithSettingsFactory() => - new ServiceCollection() - .AddEventStoreClient(provider => settings => { }) - .BuildServiceProvider() - .GetRequiredService(); - - [Fact] - public void RegisterInterceptors() { - var interceptorResolved = false; - new ServiceCollection() - .AddEventStoreClient() - .AddSingleton(() => interceptorResolved = true) - .AddSingleton() - .BuildServiceProvider() - .GetRequiredService(); - - Assert.True(interceptorResolved); - } - - delegate void ConstructorInvoked(); - - class TestInterceptor : Interceptor { - public TestInterceptor(ConstructorInvoked invoked) => invoked.Invoke(); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/Diagnostics/StreamsTracingInstrumentationTests.cs b/test/EventStore.Client.Streams.Tests/Diagnostics/StreamsTracingInstrumentationTests.cs deleted file mode 100644 index 5a19c6b0d..000000000 --- a/test/EventStore.Client.Streams.Tests/Diagnostics/StreamsTracingInstrumentationTests.cs +++ /dev/null @@ -1,221 +0,0 @@ -// ReSharper disable ConditionalAccessQualifierIsNonNullableAccordingToAPIContract - -using EventStore.Client.Diagnostics; -using EventStore.Diagnostics.Tracing; - -namespace EventStore.Client.Streams.Tests.Diagnostics; - -[Trait("Category", "Diagnostics:Tracing")] -public class StreamsTracingInstrumentationTests(ITestOutputHelper output, DiagnosticsFixture fixture) - : EventStoreTests(output, fixture) { - [Fact] - public async Task AppendIsInstrumentedWithTracingAsExpected() { - var stream = Fixture.GetStreamName(); - - await Fixture.Streams.AppendToStreamAsync( - stream, - StreamState.NoStream, - Fixture.CreateTestEvents() - ); - - var activity = Fixture - .GetActivitiesForOperation(TracingConstants.Operations.Append, stream) - .SingleOrDefault() - .ShouldNotBeNull(); - - Fixture.AssertAppendActivityHasExpectedTags(activity, stream); - } - - [Fact] - public async Task AppendTraceIsTaggedWithErrorStatusOnException() { - var stream = Fixture.GetStreamName(); - - var actualException = await Fixture.Streams.AppendToStreamAsync( - stream, - StreamState.NoStream, - Fixture.CreateTestEventsThatThrowsException() - ).ShouldThrowAsync(); - - var activity = Fixture - .GetActivitiesForOperation(TracingConstants.Operations.Append, stream) - .SingleOrDefault() - .ShouldNotBeNull(); - - Fixture.AssertErroneousAppendActivityHasExpectedTags(activity, actualException); - } - - [Fact] - public async Task TracingContextIsInjectedWhenUserMetadataIsValidJsonObject() { - var stream = Fixture.GetStreamName(); - - await Fixture.Streams.AppendToStreamAsync( - stream, - StreamState.NoStream, - Fixture.CreateTestEvents(1, metadata: Fixture.CreateTestJsonMetadata()) - ); - - var activity = Fixture - .GetActivitiesForOperation(TracingConstants.Operations.Append, stream) - .SingleOrDefault() - .ShouldNotBeNull(); - - var readResult = await Fixture.Streams - .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start) - .ToListAsync(); - - var tracingMetadata = readResult[0].OriginalEvent.Metadata.ExtractTracingMetadata(); - - tracingMetadata.ShouldNotBe(TracingMetadata.None); - tracingMetadata.TraceId.ShouldBe(activity.TraceId.ToString()); - tracingMetadata.SpanId.ShouldBe(activity.SpanId.ToString()); - } - - [Fact] - public async Task TracingContextIsNotInjectedWhenUserMetadataIsNotValidJsonObject() { - var stream = Fixture.GetStreamName(); - - var inputMetadata = "clearlynotavalidjsonobject"u8.ToArray(); - await Fixture.Streams.AppendToStreamAsync( - stream, - StreamState.NoStream, - Fixture.CreateTestEvents(1, metadata: inputMetadata) - ); - - var readResult = await Fixture.Streams - .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start) - .ToListAsync(); - - var outputMetadata = readResult[0].OriginalEvent.Metadata.ToArray(); - outputMetadata.ShouldBe(inputMetadata); - } - - [Fact] - public async Task TracingContextIsInjectedWhenEventIsNotJsonButHasJsonMetadata() { - var stream = Fixture.GetStreamName(); - - var inputMetadata = Fixture.CreateTestJsonMetadata().ToArray(); - await Fixture.Streams.AppendToStreamAsync( - stream, - StreamState.NoStream, - Fixture.CreateTestEvents( - metadata: inputMetadata, - contentType: Constants.Metadata.ContentTypes.ApplicationOctetStream - ) - ); - - var readResult = await Fixture.Streams - .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start) - .ToListAsync(); - - var outputMetadata = readResult[0].OriginalEvent.Metadata.ToArray(); - outputMetadata.ShouldNotBe(inputMetadata); - - var appendActivities = Fixture.GetActivitiesForOperation(TracingConstants.Operations.Append, stream); - - appendActivities.ShouldNotBeEmpty(); - } - - [Fact] - public async Task json_metadata_event_is_traced_and_non_json_metadata_event_is_not_traced() { - var streamName = Fixture.GetStreamName(); - - var seedEvents = new[] { - Fixture.CreateTestEvent(metadata: Fixture.CreateTestJsonMetadata()), - Fixture.CreateTestEvent(metadata: Fixture.CreateTestNonJsonMetadata()) - }; - - var availableEvents = new HashSet(seedEvents.Select(x => x.EventId)); - - await Fixture.Streams.AppendToStreamAsync(streamName, StreamState.NoStream, seedEvents); - - await using var subscription = Fixture.Streams.SubscribeToStream(streamName, FromStream.Start); - await using var enumerator = subscription.Messages.GetAsyncEnumerator(); - - var appendActivities = Fixture - .GetActivitiesForOperation(TracingConstants.Operations.Append, streamName) - .ShouldNotBeNull(); - - Assert.True(await enumerator.MoveNextAsync()); - - Assert.IsType(enumerator.Current); - - await Subscribe(enumerator).WithTimeout(); - - var subscribeActivities = Fixture - .GetActivitiesForOperation(TracingConstants.Operations.Subscribe, streamName) - .ToArray(); - - appendActivities.ShouldHaveSingleItem(); - - subscribeActivities.ShouldHaveSingleItem(); - - subscribeActivities.First().ParentId.ShouldBe(appendActivities.First().Id); - - var jsonMetadataEvent = seedEvents.First(); - - Fixture.AssertSubscriptionActivityHasExpectedTags( - subscribeActivities.First(), - streamName, - jsonMetadataEvent.EventId.ToString() - ); - - return; - - async Task Subscribe(IAsyncEnumerator internalEnumerator) { - while (await internalEnumerator.MoveNextAsync()) { - if (internalEnumerator.Current is not StreamMessage.Event(var resolvedEvent)) - continue; - - availableEvents.Remove(resolvedEvent.Event.EventId); - - if (availableEvents.Count == 0) - return; - } - } - } - - [Fact] - [Trait("Category", "Special cases")] - public async Task should_not_trace_when_event_is_null() { - var category = Guid.NewGuid().ToString("N"); - var streamName = category + "-123"; - - var seedEvents = Fixture.CreateTestEvents(type: $"{category}-{Fixture.GetStreamName()}").ToArray(); - await Fixture.Streams.AppendToStreamAsync(streamName, StreamState.NoStream, seedEvents); - - await Fixture.Streams.DeleteAsync(streamName, StreamState.StreamExists); - - await using var subscription = Fixture.Streams.SubscribeToStream("$ce-" + category, FromStream.Start, resolveLinkTos: true); - - await using var enumerator = subscription.Messages.GetAsyncEnumerator(); - - Assert.True(await enumerator.MoveNextAsync()); - - Assert.IsType(enumerator.Current); - - await Subscribe().WithTimeout(); - - var appendActivities = Fixture - .GetActivitiesForOperation(TracingConstants.Operations.Append, streamName) - .ShouldNotBeNull(); - - var subscribeActivities = Fixture - .GetActivitiesForOperation(TracingConstants.Operations.Subscribe, "$ce-" + category) - .ToArray(); - - appendActivities.ShouldHaveSingleItem(); - subscribeActivities.ShouldBeEmpty(); - - return; - - async Task Subscribe() { - while (await enumerator.MoveNextAsync()) { - if (enumerator.Current is not StreamMessage.Event(var resolvedEvent)) - continue; - - if (resolvedEvent.Event?.EventType is "$metadata") - return; - } - } - } -} diff --git a/test/EventStore.Client.Streams.Tests/EventDataTests.cs b/test/EventStore.Client.Streams.Tests/EventDataTests.cs deleted file mode 100644 index 87ed00191..000000000 --- a/test/EventStore.Client.Streams.Tests/EventDataTests.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace EventStore.Client.Streams.Tests; - -[Trait("Category", "UnitTest")] -public class EventDataTests { - [Fact] - public void EmptyEventIdThrows() { - var ex = Assert.Throws( - () => new EventData(Uuid.Empty, "-", Array.Empty()) - ); - - Assert.Equal("eventId", ex.ParamName); - } - - [Fact] - public void MalformedContentTypeThrows() => - Assert.Throws(() => new EventData(Uuid.NewUuid(), "-", Array.Empty(), contentType: "application")); - - [Fact] - public void InvalidContentTypeThrows() { - var ex = Assert.Throws(() => new EventData(Uuid.NewUuid(), "-", Array.Empty(), contentType: "application/xml")); - Assert.Equal("contentType", ex.ParamName); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/EventStore.Client.Streams.Tests.csproj b/test/EventStore.Client.Streams.Tests/EventStore.Client.Streams.Tests.csproj deleted file mode 100644 index 3e9700e08..000000000 --- a/test/EventStore.Client.Streams.Tests/EventStore.Client.Streams.Tests.csproj +++ /dev/null @@ -1,9 +0,0 @@ - - - - CS0612;xUnit1031 - - - - - \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/EventStore.Client.Streams.Tests.csproj.DotSettings b/test/EventStore.Client.Streams.Tests/EventStore.Client.Streams.Tests.csproj.DotSettings deleted file mode 100644 index 9176e378d..000000000 --- a/test/EventStore.Client.Streams.Tests/EventStore.Client.Streams.Tests.csproj.DotSettings +++ /dev/null @@ -1,12 +0,0 @@ - - False - True - False - False - True - False - True - True - True - True - False \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/Security/Obsolete/SecurityFixture_obsolete.cs b/test/EventStore.Client.Streams.Tests/Security/Obsolete/SecurityFixture_obsolete.cs deleted file mode 100644 index 18b52be82..000000000 --- a/test/EventStore.Client.Streams.Tests/Security/Obsolete/SecurityFixture_obsolete.cs +++ /dev/null @@ -1,321 +0,0 @@ -using System.Runtime.CompilerServices; - -namespace EventStore.Client.Streams.Tests.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class SecurityFixture_obsolete : EventStoreFixture { - public const string NoAclStream = nameof(NoAclStream); - public const string ReadStream = nameof(ReadStream); - public const string WriteStream = nameof(WriteStream); - public const string MetaReadStream = nameof(MetaReadStream); - public const string MetaWriteStream = nameof(MetaWriteStream); - public const string AllStream = SystemStreams.AllStream; - public const string NormalAllStream = nameof(NormalAllStream); - public const string SystemAllStream = $"${nameof(SystemAllStream)}"; - public const string SystemAdminStream = $"${nameof(SystemAdminStream)}"; - public const string SystemAclStream = $"${nameof(SystemAclStream)}"; - - const int TimeoutMs = 1000; - - public SecurityFixture_obsolete() : base(x => x.WithoutDefaultCredentials()) { - OnSetup = async () => { - await Users.CreateUserWithRetry( - TestCredentials.TestUser1.Username!, - nameof(TestCredentials.TestUser1), - Array.Empty(), - TestCredentials.TestUser1.Password!, - TestCredentials.Root - ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - await Users.CreateUserWithRetry( - TestCredentials.TestUser2.Username!, - nameof(TestCredentials.TestUser2), - Array.Empty(), - TestCredentials.TestUser2.Password!, - TestCredentials.Root - ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - await Users.CreateUserWithRetry( - TestCredentials.TestAdmin.Username!, - nameof(TestCredentials.TestAdmin), - new[] { SystemRoles.Admins }, - TestCredentials.TestAdmin.Password!, - TestCredentials.Root - ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - await Given(); - await When(); - }; - } - - protected virtual async Task Given() { - await Streams.SetStreamMetadataAsync( - NoAclStream, - StreamState.NoStream, - new(), - userCredentials: TestCredentials.TestAdmin - ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - await Streams.SetStreamMetadataAsync( - ReadStream, - StreamState.NoStream, - new(acl: new(TestCredentials.TestUser1.Username)), - userCredentials: TestCredentials.TestAdmin - ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - await Streams.SetStreamMetadataAsync( - WriteStream, - StreamState.NoStream, - new(acl: new(writeRole: TestCredentials.TestUser1.Username)), - userCredentials: TestCredentials.TestAdmin - ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - await Streams.SetStreamMetadataAsync( - MetaReadStream, - StreamState.NoStream, - new(acl: new(metaReadRole: TestCredentials.TestUser1.Username)), - userCredentials: TestCredentials.TestAdmin - ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - await Streams.SetStreamMetadataAsync( - MetaWriteStream, - StreamState.NoStream, - new(acl: new(metaWriteRole: TestCredentials.TestUser1.Username)), - userCredentials: TestCredentials.TestAdmin - ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - await Streams.SetStreamMetadataAsync( - AllStream, - StreamState.Any, - new(acl: new(TestCredentials.TestUser1.Username)), - userCredentials: TestCredentials.TestAdmin - ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - await Streams.SetStreamMetadataAsync( - SystemAclStream, - StreamState.NoStream, - new( - acl: new( - writeRole: TestCredentials.TestUser1.Username, - readRole: TestCredentials.TestUser1.Username, - metaWriteRole: TestCredentials.TestUser1.Username, - metaReadRole: TestCredentials.TestUser1.Username - ) - ), - userCredentials: TestCredentials.TestAdmin - ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - await Streams.SetStreamMetadataAsync( - SystemAdminStream, - StreamState.NoStream, - new( - acl: new( - writeRole: SystemRoles.Admins, - readRole: SystemRoles.Admins, - metaWriteRole: SystemRoles.Admins, - metaReadRole: SystemRoles.Admins - ) - ), - userCredentials: TestCredentials.TestAdmin - ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - await Streams.SetStreamMetadataAsync( - NormalAllStream, - StreamState.NoStream, - new( - acl: new( - writeRole: SystemRoles.All, - readRole: SystemRoles.All, - metaWriteRole: SystemRoles.All, - metaReadRole: SystemRoles.All - ) - ), - userCredentials: TestCredentials.TestAdmin - ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - await Streams.SetStreamMetadataAsync( - SystemAllStream, - StreamState.NoStream, - new( - acl: new( - writeRole: SystemRoles.All, - readRole: SystemRoles.All, - metaWriteRole: SystemRoles.All, - metaReadRole: SystemRoles.All - ) - ), - userCredentials: TestCredentials.TestAdmin - ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - } - - protected virtual Task When() => Task.CompletedTask; - - public Task ReadEvent(string streamId, UserCredentials? userCredentials = default) => - Streams.ReadStreamAsync( - Direction.Forwards, - streamId, - StreamPosition.Start, - 1, - false, - userCredentials: userCredentials - ) - .ToArrayAsync() - .AsTask() - .WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - public Task ReadStreamForward(string streamId, UserCredentials? userCredentials = default) => - Streams.ReadStreamAsync( - Direction.Forwards, - streamId, - StreamPosition.Start, - 1, - false, - userCredentials: userCredentials - ) - .ToArrayAsync() - .AsTask() - .WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - public Task ReadStreamBackward(string streamId, UserCredentials? userCredentials = default) => - Streams.ReadStreamAsync( - Direction.Backwards, - streamId, - StreamPosition.Start, - 1, - false, - userCredentials: userCredentials - ) - .ToArrayAsync() - .AsTask() - .WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - public Task AppendStream(string streamId, UserCredentials? userCredentials = default) => - Streams.AppendToStreamAsync( - streamId, - StreamState.Any, - CreateTestEvents(3), - userCredentials: userCredentials - ) - .WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - public Task ReadAllForward(UserCredentials? userCredentials = default) => - Streams.ReadAllAsync( - Direction.Forwards, - Position.Start, - 1, - false, - userCredentials: userCredentials - ) - .ToArrayAsync() - .AsTask() - .WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - public Task ReadAllBackward(UserCredentials? userCredentials = default) => - Streams - .ReadAllAsync( - Direction.Backwards, - Position.End, - 1, - false, - userCredentials: userCredentials - ) - .ToArrayAsync() - .AsTask() - .WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - public Task ReadMeta(string streamId, UserCredentials? userCredentials = default) => - Streams.GetStreamMetadataAsync(streamId, userCredentials: userCredentials) - .WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - public Task WriteMeta(string streamId, UserCredentials? userCredentials = default, string? role = default) => - Streams.SetStreamMetadataAsync( - streamId, - StreamState.Any, - new( - acl: new( - writeRole: role, - readRole: role, - metaWriteRole: role, - metaReadRole: role - ) - ), - userCredentials: userCredentials - ) - .WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - [Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client", false)] - public async Task SubscribeToStreamObsolete(string streamId, UserCredentials? userCredentials = default) { - var source = new TaskCompletionSource(); - using (await Streams.SubscribeToStreamAsync( - streamId, - FromStream.Start, - (_, _, _) => { - source.TrySetResult(true); - return Task.CompletedTask; - }, - subscriptionDropped: (_, _, ex) => { - if (ex == null) - source.TrySetResult(true); - else - source.TrySetException(ex); - }, - userCredentials: userCredentials - ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs))) { - await source.Task.WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - } - } - - public async Task SubscribeToStream(string streamId, UserCredentials? userCredentials = default) { - await using var subscription = - Streams.SubscribeToStream(streamId, FromStream.Start, userCredentials: userCredentials); - await subscription - .Messages.OfType().AnyAsync().AsTask() - .WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - } - - [Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client", false)] - public async Task SubscribeToAllObsolete(UserCredentials? userCredentials = default) { - var source = new TaskCompletionSource(); - using (await Streams.SubscribeToAllAsync( - FromAll.Start, - (_, _, _) => { - source.TrySetResult(true); - return Task.CompletedTask; - }, - false, - (_, _, ex) => { - if (ex == null) - source.TrySetResult(true); - else - source.TrySetException(ex); - }, - userCredentials: userCredentials - ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs))) { - await source.Task.WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - } - } - - public async Task SubscribeToAll(UserCredentials? userCredentials = default) { - await using var subscription = - Streams.SubscribeToAll(FromAll.Start, userCredentials: userCredentials); - await subscription - .Messages.OfType().AnyAsync().AsTask() - .WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - } - - public async Task CreateStreamWithMeta(StreamMetadata metadata, [CallerMemberName] string streamId = "") { - await Streams.SetStreamMetadataAsync( - streamId, - StreamState.NoStream, - metadata, - userCredentials: TestCredentials.TestAdmin - ) - .WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - return streamId; - } - - public Task DeleteStream(string streamId, UserCredentials? userCredentials = default) => - Streams.TombstoneAsync(streamId, StreamState.Any, userCredentials: userCredentials) - .WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); -} diff --git a/test/EventStore.Client.Streams.Tests/Security/Obsolete/all_stream_with_no_acl_security_obsolete.cs b/test/EventStore.Client.Streams.Tests/Security/Obsolete/all_stream_with_no_acl_security_obsolete.cs deleted file mode 100644 index 40cdd81ef..000000000 --- a/test/EventStore.Client.Streams.Tests/Security/Obsolete/all_stream_with_no_acl_security_obsolete.cs +++ /dev/null @@ -1,37 +0,0 @@ -namespace EventStore.Client.Streams.Tests.Obsolete; - -[Trait("Category", "Security")] -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class all_stream_with_no_acl_security_obsolete(ITestOutputHelper output, all_stream_with_no_acl_security_obsolete.CustomFixture fixture) : EventStoreTests(output, fixture) { - [Fact] - public async Task reading_and_subscribing_is_not_allowed_when_no_credentials_are_passed() { - await Assert.ThrowsAsync(() => Fixture.ReadAllForward()); - await Assert.ThrowsAsync(() => Fixture.ReadAllBackward()); - await Assert.ThrowsAsync(() => Fixture.ReadMeta(SecurityFixture_obsolete.AllStream)); - await Assert.ThrowsAsync(() => Fixture.SubscribeToAllObsolete()); - } - - [Fact] - public async Task reading_and_subscribing_is_not_allowed_for_usual_user() { - await Assert.ThrowsAsync(() => Fixture.ReadAllForward(TestCredentials.TestUser1)); - await Assert.ThrowsAsync(() => Fixture.ReadAllBackward(TestCredentials.TestUser1)); - await Assert.ThrowsAsync(() => Fixture.ReadMeta(SecurityFixture_obsolete.AllStream, TestCredentials.TestUser1)); - await Assert.ThrowsAsync(() => Fixture.SubscribeToAllObsolete(TestCredentials.TestUser1)); - } - - [Fact] - public async Task reading_and_subscribing_is_allowed_for_admin_user() { - await Fixture.ReadAllForward(TestCredentials.TestAdmin); - await Fixture.ReadAllBackward(TestCredentials.TestAdmin); - await Fixture.ReadMeta(SecurityFixture_obsolete.AllStream, TestCredentials.TestAdmin); - await Fixture.SubscribeToAllObsolete(TestCredentials.TestAdmin); - } - - public class CustomFixture : SecurityFixture_obsolete { - protected override async Task Given() { - await base.Given(); - - await Streams.SetStreamMetadataAsync(AllStream, StreamState.Any, new(), userCredentials: TestCredentials.Root); - } - } -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/Security/Obsolete/overriden_system_stream_security_for_all_obsolete.cs b/test/EventStore.Client.Streams.Tests/Security/Obsolete/overriden_system_stream_security_for_all_obsolete.cs deleted file mode 100644 index 4593e39e0..000000000 --- a/test/EventStore.Client.Streams.Tests/Security/Obsolete/overriden_system_stream_security_for_all_obsolete.cs +++ /dev/null @@ -1,70 +0,0 @@ -namespace EventStore.Client.Streams.Tests.Obsolete; - -[Trait("Category", "Security")] -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class overriden_system_stream_security_for_all_obsolete(ITestOutputHelper output, overriden_system_stream_security_for_all_obsolete.CustomFixture fixture) : EventStoreTests(output, fixture) { - [Fact] - public async Task operations_on_system_stream_succeeds_for_user() { - var stream = $"${Fixture.GetStreamName()}"; - await Fixture.AppendStream(stream, TestCredentials.TestUser1); - await Fixture.ReadEvent(stream, TestCredentials.TestUser1); - await Fixture.ReadStreamForward(stream, TestCredentials.TestUser1); - await Fixture.ReadStreamBackward(stream, TestCredentials.TestUser1); - - await Fixture.ReadMeta(stream, TestCredentials.TestUser1); - await Fixture.WriteMeta(stream, TestCredentials.TestUser1); - - await Fixture.SubscribeToStreamObsolete(stream, TestCredentials.TestUser1); - - await Fixture.DeleteStream(stream, TestCredentials.TestUser1); - } - - [AnonymousAccess.Fact] - public async Task operations_on_system_stream_fail_for_anonymous_user() { - var stream = $"${Fixture.GetStreamName()}"; - await Fixture.AppendStream(stream); - await Fixture.ReadEvent(stream); - await Fixture.ReadStreamForward(stream); - await Fixture.ReadStreamBackward(stream); - - await Fixture.ReadMeta(stream); - await Fixture.WriteMeta(stream); - - await Fixture.SubscribeToStreamObsolete(stream); - - await Fixture.DeleteStream(stream); - } - - [Fact] - public async Task operations_on_system_stream_succeed_for_admin() { - var stream = $"${Fixture.GetStreamName()}"; - await Fixture.AppendStream(stream, TestCredentials.TestAdmin); - - await Fixture.ReadEvent(stream, TestCredentials.TestAdmin); - await Fixture.ReadStreamForward(stream, TestCredentials.TestAdmin); - await Fixture.ReadStreamBackward(stream, TestCredentials.TestAdmin); - - await Fixture.ReadMeta(stream, TestCredentials.TestAdmin); - await Fixture.WriteMeta(stream, TestCredentials.TestAdmin); - - await Fixture.SubscribeToStreamObsolete(stream, TestCredentials.TestAdmin); - - await Fixture.DeleteStream(stream, TestCredentials.TestAdmin); - } - - public class CustomFixture : SecurityFixture_obsolete { - protected override Task When() { - var settings = new SystemSettings( - systemStreamAcl: new( - SystemRoles.All, - SystemRoles.All, - SystemRoles.All, - SystemRoles.All, - SystemRoles.All - ) - ); - - return Streams.SetSystemSettingsAsync(settings, userCredentials: TestCredentials.TestAdmin); - } - } -} diff --git a/test/EventStore.Client.Streams.Tests/Security/Obsolete/overriden_system_stream_security_obsolete.cs b/test/EventStore.Client.Streams.Tests/Security/Obsolete/overriden_system_stream_security_obsolete.cs deleted file mode 100644 index f36646be1..000000000 --- a/test/EventStore.Client.Streams.Tests/Security/Obsolete/overriden_system_stream_security_obsolete.cs +++ /dev/null @@ -1,87 +0,0 @@ -namespace EventStore.Client.Streams.Tests.Obsolete; - -[Trait("Category", "Security")] -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class overriden_system_stream_security_obsolete(ITestOutputHelper output, overriden_system_stream_security_obsolete.CustomFixture fixture) : EventStoreTests(output, fixture) { - [Fact] - public async Task operations_on_system_stream_succeed_for_authorized_user() { - var stream = $"${Fixture.GetStreamName()}"; - await Fixture.AppendStream(stream, TestCredentials.TestUser1); - - await Fixture.ReadEvent(stream, TestCredentials.TestUser1); - await Fixture.ReadStreamForward(stream, TestCredentials.TestUser1); - await Fixture.ReadStreamBackward(stream, TestCredentials.TestUser1); - - await Fixture.ReadMeta(stream, TestCredentials.TestUser1); - await Fixture.WriteMeta(stream, TestCredentials.TestUser1); - - await Fixture.SubscribeToStreamObsolete(stream, TestCredentials.TestUser1); - - await Fixture.DeleteStream(stream, TestCredentials.TestUser1); - } - - [Fact] - public async Task operations_on_system_stream_fail_for_not_authorized_user() { - var stream = $"${Fixture.GetStreamName()}"; - await Assert.ThrowsAsync(() => Fixture.ReadEvent(stream, TestCredentials.TestUser2)); - await Assert.ThrowsAsync(() => Fixture.ReadStreamForward(stream, TestCredentials.TestUser2)); - await Assert.ThrowsAsync( - () => - Fixture.ReadStreamBackward(stream, TestCredentials.TestUser2) - ); - - await Assert.ThrowsAsync(() => Fixture.AppendStream(stream, TestCredentials.TestUser2)); - - await Assert.ThrowsAsync(() => Fixture.ReadMeta(stream, TestCredentials.TestUser2)); - await Assert.ThrowsAsync(() => Fixture.WriteMeta(stream, TestCredentials.TestUser2)); - - await Assert.ThrowsAsync(() => Fixture.SubscribeToStreamObsolete(stream, TestCredentials.TestUser2)); - - await Assert.ThrowsAsync(() => Fixture.DeleteStream(stream, TestCredentials.TestUser2)); - } - - [Fact] - public async Task operations_on_system_stream_fail_for_anonymous_user() { - var stream = $"${Fixture.GetStreamName()}"; - await Assert.ThrowsAsync(() => Fixture.ReadEvent(stream)); - await Assert.ThrowsAsync(() => Fixture.ReadStreamForward(stream)); - await Assert.ThrowsAsync(() => Fixture.ReadStreamBackward(stream)); - - await Assert.ThrowsAsync(() => Fixture.AppendStream(stream)); - - await Assert.ThrowsAsync(() => Fixture.ReadMeta(stream)); - await Assert.ThrowsAsync(() => Fixture.WriteMeta(stream)); - - await Assert.ThrowsAsync(() => Fixture.SubscribeToStreamObsolete(stream)); - - await Assert.ThrowsAsync(() => Fixture.DeleteStream(stream)); - } - - [Fact] - public async Task operations_on_system_stream_succeed_for_admin() { - var stream = $"${Fixture.GetStreamName()}"; - await Fixture.AppendStream(stream, TestCredentials.TestAdmin); - - await Fixture.ReadEvent(stream, TestCredentials.TestAdmin); - await Fixture.ReadStreamForward(stream, TestCredentials.TestAdmin); - await Fixture.ReadStreamBackward(stream, TestCredentials.TestAdmin); - - await Fixture.ReadMeta(stream, TestCredentials.TestAdmin); - await Fixture.WriteMeta(stream, TestCredentials.TestAdmin); - - await Fixture.SubscribeToStreamObsolete(stream, TestCredentials.TestAdmin); - - await Fixture.DeleteStream(stream, TestCredentials.TestAdmin); - } - - public class CustomFixture : SecurityFixture_obsolete { - protected override Task When() { - var settings = new SystemSettings( - systemStreamAcl: new("user1", "user1", "user1", "user1", "user1"), - userStreamAcl: default - ); - - return Streams.SetSystemSettingsAsync(settings, userCredentials: TestCredentials.TestAdmin); - } - } -} diff --git a/test/EventStore.Client.Streams.Tests/Security/Obsolete/overriden_user_stream_security_obsolete.cs b/test/EventStore.Client.Streams.Tests/Security/Obsolete/overriden_user_stream_security_obsolete.cs deleted file mode 100644 index dcbd88fa1..000000000 --- a/test/EventStore.Client.Streams.Tests/Security/Obsolete/overriden_user_stream_security_obsolete.cs +++ /dev/null @@ -1,78 +0,0 @@ -namespace EventStore.Client.Streams.Tests.Obsolete; - -[Trait("Category", "Security")] -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class overriden_user_stream_security_obsolete(ITestOutputHelper output, overriden_user_stream_security_obsolete.CustomFixture fixture) : EventStoreTests(output, fixture) { - [Fact] - public async Task operations_on_user_stream_succeeds_for_authorized_user() { - var stream = Fixture.GetStreamName(); - await Fixture.AppendStream(stream, TestCredentials.TestUser1); - - await Fixture.ReadEvent(stream, TestCredentials.TestUser1); - await Fixture.ReadStreamForward(stream, TestCredentials.TestUser1); - await Fixture.ReadStreamBackward(stream, TestCredentials.TestUser1); - - await Fixture.ReadMeta(stream, TestCredentials.TestUser1); - await Fixture.WriteMeta(stream, TestCredentials.TestUser1); - - await Fixture.SubscribeToStreamObsolete(stream, TestCredentials.TestUser1); - - await Fixture.DeleteStream(stream, TestCredentials.TestUser1); - } - - [Fact] - public async Task operations_on_user_stream_fail_for_not_authorized_user() { - var stream = Fixture.GetStreamName(); - await Assert.ThrowsAsync(() => Fixture.ReadEvent(stream, TestCredentials.TestUser2)); - await Assert.ThrowsAsync(() => Fixture.ReadStreamForward(stream, TestCredentials.TestUser2)); - await Assert.ThrowsAsync(() => Fixture.ReadStreamBackward(stream, TestCredentials.TestUser2)); - - await Assert.ThrowsAsync(() => Fixture.AppendStream(stream, TestCredentials.TestUser2)); - await Assert.ThrowsAsync(() => Fixture.ReadMeta(stream, TestCredentials.TestUser2)); - await Assert.ThrowsAsync(() => Fixture.WriteMeta(stream, TestCredentials.TestUser2)); - - await Assert.ThrowsAsync(() => Fixture.SubscribeToStreamObsolete(stream, TestCredentials.TestUser2)); - - await Assert.ThrowsAsync(() => Fixture.DeleteStream(stream, TestCredentials.TestUser2)); - } - - [Fact] - public async Task operations_on_user_stream_fail_for_anonymous_user() { - var stream = Fixture.GetStreamName(); - await Assert.ThrowsAsync(() => Fixture.ReadEvent(stream)); - await Assert.ThrowsAsync(() => Fixture.ReadStreamForward(stream)); - await Assert.ThrowsAsync(() => Fixture.ReadStreamBackward(stream)); - - await Assert.ThrowsAsync(() => Fixture.AppendStream(stream)); - await Assert.ThrowsAsync(() => Fixture.ReadMeta(stream)); - await Assert.ThrowsAsync(() => Fixture.WriteMeta(stream)); - - await Assert.ThrowsAsync(() => Fixture.SubscribeToStreamObsolete(stream)); - - await Assert.ThrowsAsync(() => Fixture.DeleteStream(stream)); - } - - [Fact] - public async Task operations_on_user_stream_succeed_for_admin() { - var stream = Fixture.GetStreamName(); - await Fixture.AppendStream(stream, TestCredentials.TestAdmin); - - await Fixture.ReadEvent(stream, TestCredentials.TestAdmin); - await Fixture.ReadStreamForward(stream, TestCredentials.TestAdmin); - await Fixture.ReadStreamBackward(stream, TestCredentials.TestAdmin); - - await Fixture.ReadMeta(stream, TestCredentials.TestAdmin); - await Fixture.WriteMeta(stream, TestCredentials.TestAdmin); - - await Fixture.SubscribeToStreamObsolete(stream, TestCredentials.TestAdmin); - - await Fixture.DeleteStream(stream, TestCredentials.TestAdmin); - } - - public class CustomFixture : SecurityFixture_obsolete { - protected override Task When() { - var settings = new SystemSettings(new("user1", "user1", "user1", "user1", "user1")); - return Streams.SetSystemSettingsAsync(settings, userCredentials: TestCredentials.TestAdmin); - } - } -} diff --git a/test/EventStore.Client.Streams.Tests/Security/Obsolete/subscribe_to_all_security_obsolete.cs b/test/EventStore.Client.Streams.Tests/Security/Obsolete/subscribe_to_all_security_obsolete.cs deleted file mode 100644 index b21cf66c6..000000000 --- a/test/EventStore.Client.Streams.Tests/Security/Obsolete/subscribe_to_all_security_obsolete.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace EventStore.Client.Streams.Tests.Obsolete; - -[Trait("Category", "Security")] -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class subscribe_to_all_security_obsolete(ITestOutputHelper output, SecurityFixture_obsolete fixture) : EventStoreTests(output, fixture) { - [Fact] - public async Task subscribing_to_all_with_not_existing_credentials_is_not_authenticated() => - await Assert.ThrowsAsync(() => Fixture.SubscribeToAllObsolete(TestCredentials.TestBadUser)); - - [Fact] - public async Task subscribing_to_all_with_no_credentials_is_denied() => await Assert.ThrowsAsync(() => Fixture.SubscribeToAllObsolete()); - - [Fact] - public async Task subscribing_to_all_with_not_authorized_user_credentials_is_denied() => - await Assert.ThrowsAsync(() => Fixture.SubscribeToAllObsolete(TestCredentials.TestUser2)); - - [Fact] - public async Task subscribing_to_all_with_authorized_user_credentials_succeeds() => await Fixture.SubscribeToAllObsolete(TestCredentials.TestUser1); - - [Fact] - public async Task subscribing_to_all_with_admin_user_credentials_succeeds() => await Fixture.SubscribeToAllObsolete(TestCredentials.TestAdmin); -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/Security/Obsolete/subscribe_to_stream_security_obsolete.cs b/test/EventStore.Client.Streams.Tests/Security/Obsolete/subscribe_to_stream_security_obsolete.cs deleted file mode 100644 index 409256650..000000000 --- a/test/EventStore.Client.Streams.Tests/Security/Obsolete/subscribe_to_stream_security_obsolete.cs +++ /dev/null @@ -1,75 +0,0 @@ -namespace EventStore.Client.Streams.Tests.Obsolete; - -[Trait("Category", "Security")] -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class subscribe_to_stream_security_obsolete(ITestOutputHelper output, SecurityFixture_obsolete fixture) : EventStoreTests(output, fixture) { - [Fact] - public async Task subscribing_to_stream_with_not_existing_credentials_is_not_authenticated() => - await Assert.ThrowsAsync(() => Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.ReadStream, TestCredentials.TestBadUser)); - - [Fact] - public async Task subscribing_to_stream_with_no_credentials_is_denied() => - await Assert.ThrowsAsync(() => Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.ReadStream)); - - [Fact] - public async Task subscribing_to_stream_with_not_authorized_user_credentials_is_denied() => - await Assert.ThrowsAsync(() => Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.ReadStream, TestCredentials.TestUser2)); - - [Fact] - public async Task reading_stream_with_authorized_user_credentials_succeeds() { - await Fixture.AppendStream(SecurityFixture_obsolete.ReadStream, TestCredentials.TestUser1); - await Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.ReadStream, TestCredentials.TestUser1); - } - - [Fact] - public async Task reading_stream_with_admin_user_credentials_succeeds() { - await Fixture.AppendStream(SecurityFixture_obsolete.ReadStream, TestCredentials.TestAdmin); - await Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.ReadStream, TestCredentials.TestAdmin); - } - - [AnonymousAccess.Fact] - public async Task subscribing_to_no_acl_stream_succeeds_when_no_credentials_are_passed() { - await Fixture.AppendStream(SecurityFixture_obsolete.NoAclStream); - await Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.NoAclStream); - } - - [Fact] - public async Task subscribing_to_no_acl_stream_is_not_authenticated_when_not_existing_credentials_are_passed() => - await Assert.ThrowsAsync(() => Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.NoAclStream, TestCredentials.TestBadUser)); - - [Fact] - public async Task subscribing_to_no_acl_stream_succeeds_when_any_existing_user_credentials_are_passed() { - await Fixture.AppendStream(SecurityFixture_obsolete.NoAclStream, TestCredentials.TestUser1); - await Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.NoAclStream, TestCredentials.TestUser1); - await Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.NoAclStream, TestCredentials.TestUser2); - } - - [Fact] - public async Task subscribing_to_no_acl_stream_succeeds_when_admin_user_credentials_are_passed() { - await Fixture.AppendStream(SecurityFixture_obsolete.NoAclStream, TestCredentials.TestAdmin); - await Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.NoAclStream, TestCredentials.TestAdmin); - } - - [AnonymousAccess.Fact] - public async Task subscribing_to_all_access_normal_stream_succeeds_when_no_credentials_are_passed() { - await Fixture.AppendStream(SecurityFixture_obsolete.NormalAllStream); - await Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.NormalAllStream); - } - - [Fact] - public async Task subscribing_to_all_access_normal_stream_is_not_authenticated_when_not_existing_credentials_are_passed() => - await Assert.ThrowsAsync(() => Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.NormalAllStream, TestCredentials.TestBadUser)); - - [Fact] - public async Task subscribing_to_all_access_normal_stream_succeeds_when_any_existing_user_credentials_are_passed() { - await Fixture.AppendStream(SecurityFixture_obsolete.NormalAllStream, TestCredentials.TestUser1); - await Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.NormalAllStream, TestCredentials.TestUser1); - await Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.NormalAllStream, TestCredentials.TestUser2); - } - - [Fact] - public async Task subscribing_to_all_access_normal_streamm_succeeds_when_admin_user_credentials_are_passed() { - await Fixture.AppendStream(SecurityFixture_obsolete.NormalAllStream, TestCredentials.TestAdmin); - await Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.NormalAllStream, TestCredentials.TestAdmin); - } -} diff --git a/test/EventStore.Client.Streams.Tests/Security/Obsolete/system_stream_security_obsolete.cs b/test/EventStore.Client.Streams.Tests/Security/Obsolete/system_stream_security_obsolete.cs deleted file mode 100644 index 462696ff2..000000000 --- a/test/EventStore.Client.Streams.Tests/Security/Obsolete/system_stream_security_obsolete.cs +++ /dev/null @@ -1,146 +0,0 @@ -namespace EventStore.Client.Streams.Tests.Obsolete; - -[Trait("Category", "Security")] -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class system_stream_security_obsolete(ITestOutputHelper output, SecurityFixture_obsolete fixture) : EventStoreTests(output, fixture) { - [Fact] - public async Task operations_on_system_stream_with_no_acl_set_fail_for_non_admin() { - await Assert.ThrowsAsync(() => Fixture.ReadEvent("$system-no-acl", TestCredentials.TestUser1)); - await Assert.ThrowsAsync(() => Fixture.ReadStreamForward("$system-no-acl", TestCredentials.TestUser1)); - - await Assert.ThrowsAsync(() => Fixture.ReadStreamBackward("$system-no-acl", TestCredentials.TestUser1)); - - await Assert.ThrowsAsync(() => Fixture.AppendStream("$system-no-acl", TestCredentials.TestUser1)); - - await Assert.ThrowsAsync(() => Fixture.ReadMeta("$system-no-acl", TestCredentials.TestUser1)); - await Assert.ThrowsAsync(() => Fixture.WriteMeta("$system-no-acl", TestCredentials.TestUser1)); - - await Assert.ThrowsAsync(() => Fixture.SubscribeToStreamObsolete("$system-no-acl", TestCredentials.TestUser1)); - } - - [Fact] - public async Task operations_on_system_stream_with_no_acl_set_succeed_for_admin() { - await Fixture.AppendStream("$system-no-acl", TestCredentials.TestAdmin); - - await Fixture.ReadEvent("$system-no-acl", TestCredentials.TestAdmin); - await Fixture.ReadStreamForward("$system-no-acl", TestCredentials.TestAdmin); - await Fixture.ReadStreamBackward("$system-no-acl", TestCredentials.TestAdmin); - - await Fixture.ReadMeta("$system-no-acl", TestCredentials.TestAdmin); - await Fixture.WriteMeta("$system-no-acl", TestCredentials.TestAdmin); - - await Fixture.SubscribeToStreamObsolete("$system-no-acl", TestCredentials.TestAdmin); - } - - [Fact] - public async Task operations_on_system_stream_with_acl_set_to_usual_user_fail_for_not_authorized_user() { - await Assert.ThrowsAsync(() => Fixture.ReadEvent(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestUser2)); - await Assert.ThrowsAsync(() => Fixture.ReadStreamForward(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestUser2)); - await Assert.ThrowsAsync(() => Fixture.ReadStreamBackward(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestUser2)); - - await Assert.ThrowsAsync(() => Fixture.AppendStream(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestUser2)); - - await Assert.ThrowsAsync(() => Fixture.ReadMeta(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestUser2)); - await Assert.ThrowsAsync(() => Fixture.WriteMeta(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestUser2, TestCredentials.TestUser1.Username)); - - await Assert.ThrowsAsync(() => Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestUser2)); - } - - [Fact] - public async Task operations_on_system_stream_with_acl_set_to_usual_user_succeed_for_that_user() { - await Fixture.AppendStream(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestUser1); - await Fixture.ReadEvent(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestUser1); - await Fixture.ReadStreamForward(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestUser1); - await Fixture.ReadStreamBackward(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestUser1); - - await Fixture.ReadMeta(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestUser1); - await Fixture.WriteMeta(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestUser1, TestCredentials.TestUser1.Username); - - await Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestUser1); - } - - [Fact] - public async Task operations_on_system_stream_with_acl_set_to_usual_user_succeed_for_admin() { - await Fixture.AppendStream(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestAdmin); - await Fixture.ReadEvent(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestAdmin); - await Fixture.ReadStreamForward(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestAdmin); - await Fixture.ReadStreamBackward(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestAdmin); - - await Fixture.ReadMeta(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestAdmin); - await Fixture.WriteMeta(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestAdmin, TestCredentials.TestUser1.Username); - - await Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestAdmin); - } - - [Fact] - public async Task operations_on_system_stream_with_acl_set_to_admins_fail_for_usual_user() { - await Assert.ThrowsAsync(() => Fixture.ReadEvent(SecurityFixture_obsolete.SystemAdminStream, TestCredentials.TestUser1)); - await Assert.ThrowsAsync(() => Fixture.ReadStreamForward(SecurityFixture_obsolete.SystemAdminStream, TestCredentials.TestUser1)); - await Assert.ThrowsAsync( - () => - Fixture.ReadStreamBackward(SecurityFixture_obsolete.SystemAdminStream, TestCredentials.TestUser1) - ); - - await Assert.ThrowsAsync(() => Fixture.AppendStream(SecurityFixture_obsolete.SystemAdminStream, TestCredentials.TestUser1)); - - await Assert.ThrowsAsync(() => Fixture.ReadMeta(SecurityFixture_obsolete.SystemAdminStream, TestCredentials.TestUser1)); - await Assert.ThrowsAsync( - () => - Fixture.WriteMeta(SecurityFixture_obsolete.SystemAdminStream, TestCredentials.TestUser1, SystemRoles.Admins) - ); - - await Assert.ThrowsAsync(() => Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.SystemAdminStream, TestCredentials.TestUser1)); - } - - [Fact] - public async Task operations_on_system_stream_with_acl_set_to_admins_succeed_for_admin() { - await Fixture.AppendStream(SecurityFixture_obsolete.SystemAdminStream, TestCredentials.TestAdmin); - await Fixture.ReadEvent(SecurityFixture_obsolete.SystemAdminStream, TestCredentials.TestAdmin); - await Fixture.ReadStreamForward(SecurityFixture_obsolete.SystemAdminStream, TestCredentials.TestAdmin); - await Fixture.ReadStreamBackward(SecurityFixture_obsolete.SystemAdminStream, TestCredentials.TestAdmin); - - await Fixture.ReadMeta(SecurityFixture_obsolete.SystemAdminStream, TestCredentials.TestAdmin); - await Fixture.WriteMeta(SecurityFixture_obsolete.SystemAdminStream, TestCredentials.TestAdmin, SystemRoles.Admins); - - await Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.SystemAdminStream, TestCredentials.TestAdmin); - } - - [AnonymousAccess.Fact] - public async Task operations_on_system_stream_with_acl_set_to_all_succeed_for_not_authenticated_user() { - await Fixture.AppendStream(SecurityFixture_obsolete.SystemAllStream); - await Fixture.ReadEvent(SecurityFixture_obsolete.SystemAllStream); - await Fixture.ReadStreamForward(SecurityFixture_obsolete.SystemAllStream); - await Fixture.ReadStreamBackward(SecurityFixture_obsolete.SystemAllStream); - - await Fixture.ReadMeta(SecurityFixture_obsolete.SystemAllStream); - await Fixture.WriteMeta(SecurityFixture_obsolete.SystemAllStream, role: SystemRoles.All); - - await Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.SystemAllStream); - } - - [Fact] - public async Task operations_on_system_stream_with_acl_set_to_all_succeed_for_usual_user() { - await Fixture.AppendStream(SecurityFixture_obsolete.SystemAllStream, TestCredentials.TestUser1); - await Fixture.ReadEvent(SecurityFixture_obsolete.SystemAllStream, TestCredentials.TestUser1); - await Fixture.ReadStreamForward(SecurityFixture_obsolete.SystemAllStream, TestCredentials.TestUser1); - await Fixture.ReadStreamBackward(SecurityFixture_obsolete.SystemAllStream, TestCredentials.TestUser1); - - await Fixture.ReadMeta(SecurityFixture_obsolete.SystemAllStream, TestCredentials.TestUser1); - await Fixture.WriteMeta(SecurityFixture_obsolete.SystemAllStream, TestCredentials.TestUser1, SystemRoles.All); - - await Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.SystemAllStream, TestCredentials.TestUser1); - } - - [Fact] - public async Task operations_on_system_stream_with_acl_set_to_all_succeed_for_admin() { - await Fixture.AppendStream(SecurityFixture_obsolete.SystemAllStream, TestCredentials.TestAdmin); - await Fixture.ReadEvent(SecurityFixture_obsolete.SystemAllStream, TestCredentials.TestAdmin); - await Fixture.ReadStreamForward(SecurityFixture_obsolete.SystemAllStream, TestCredentials.TestAdmin); - await Fixture.ReadStreamBackward(SecurityFixture_obsolete.SystemAllStream, TestCredentials.TestAdmin); - - await Fixture.ReadMeta(SecurityFixture_obsolete.SystemAllStream, TestCredentials.TestAdmin); - await Fixture.WriteMeta(SecurityFixture_obsolete.SystemAllStream, TestCredentials.TestAdmin, SystemRoles.All); - - await Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.SystemAllStream, TestCredentials.TestAdmin); - } -} diff --git a/test/EventStore.Client.Streams.Tests/Serialization/is_json.cs b/test/EventStore.Client.Streams.Tests/Serialization/is_json.cs deleted file mode 100644 index d2b44a918..000000000 --- a/test/EventStore.Client.Streams.Tests/Serialization/is_json.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System.Runtime.CompilerServices; -using System.Text; - -namespace EventStore.Client.Streams.Tests.Serialization; - -[Trait("Category", "Serialization")] -public class is_json(ITestOutputHelper output, EventStoreFixture fixture) : EventStoreTests(output, fixture) { - public static IEnumerable TestCases() { - var json = @"{""some"":""json""}"; - - yield return new object?[] { true, json, string.Empty }; - yield return new object?[] { true, string.Empty, json }; - yield return new object?[] { true, json, json }; - yield return new object?[] { false, json, string.Empty }; - yield return new object?[] { false, string.Empty, json }; - yield return new object?[] { false, json, json }; - } - - [Theory] - [MemberData(nameof(TestCases))] - public async Task is_preserved(bool isJson, string data, string metadata) { - var stream = GetStreamName(isJson, data, metadata); - var encoding = Encoding.UTF8; - var eventData = new EventData( - Uuid.NewUuid(), - "-", - encoding.GetBytes(data), - encoding.GetBytes(metadata), - isJson - ? Constants.Metadata.ContentTypes.ApplicationJson - : Constants.Metadata.ContentTypes.ApplicationOctetStream - ); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, new[] { eventData }); - - var @event = await Fixture.Streams - .ReadStreamAsync( - Direction.Forwards, - stream, - StreamPosition.Start, - 1, - true - ) - .FirstOrDefaultAsync(); - - Assert.Equal( - isJson - ? Constants.Metadata.ContentTypes.ApplicationJson - : Constants.Metadata.ContentTypes.ApplicationOctetStream, - @event.Event.ContentType - ); - - Assert.Equal(data, encoding.GetString(@event.Event.Data.ToArray())); - Assert.Equal(metadata, encoding.GetString(@event.Event.Metadata.ToArray())); - } - - string GetStreamName(bool isJson, string data, string metadata, [CallerMemberName] string? testMethod = default) => - $"{Fixture.GetStreamName(testMethod)}_{isJson}_{(data == string.Empty ? "no_data" : "data")}_{(metadata == string.Empty ? "no_metadata" : "metadata")}"; -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/Obsolete/subscribe_to_all_obsolete.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/Obsolete/subscribe_to_all_obsolete.cs deleted file mode 100644 index af4b5ac43..000000000 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/Obsolete/subscribe_to_all_obsolete.cs +++ /dev/null @@ -1,592 +0,0 @@ -namespace EventStore.Client.Streams.Tests.Subscriptions.Obsolete; - -[Trait("Category", "Subscriptions")] -[Trait("Category", "Target:All")] -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class subscribe_to_all_obsolete(ITestOutputHelper output, SubscriptionsFixture fixture) : EventStoreTests(output, fixture) { - [Fact] - public async Task receives_all_events_from_start() { - var receivedAllEvents = new TaskCompletionSource(); - var subscriptionDropped = new TaskCompletionSource(); - - var seedEvents = Fixture.CreateTestEvents(10).ToArray(); - var pageSize = seedEvents.Length / 2; - - var availableEvents = new HashSet(seedEvents.Select(x => x.EventId)); - - foreach (var evt in seedEvents.Take(pageSize)) - await Fixture.Streams.AppendToStreamAsync($"stream-{evt.EventId.ToGuid():N}", StreamState.NoStream, new[] { evt }); - - using var subscription = await Fixture.Streams - .SubscribeToAllAsync(FromAll.Start, OnReceived, false, OnDropped) - .WithTimeout(); - - foreach (var evt in seedEvents.Skip(pageSize)) - await Fixture.Streams.AppendToStreamAsync($"stream-{evt.EventId.ToGuid():N}", StreamState.NoStream, new[] { evt }); - - await receivedAllEvents.Task.WithTimeout(); - - // if the subscription dropped before time, raise the reason why - if (subscriptionDropped.Task.IsCompleted) - subscriptionDropped.Task.IsCompleted.ShouldBe(false, subscriptionDropped.Task.Result.ToString()); - - // stop the subscription - subscription.Dispose(); - var result = await subscriptionDropped.Task.WithTimeout(); - result.ShouldBe(SubscriptionDroppedResult.Disposed()); - - return; - - Task OnReceived(StreamSubscription sub, ResolvedEvent re, CancellationToken ct) { - availableEvents.RemoveWhere(x => x == re.OriginalEvent.EventId); - - if (availableEvents.Count == 0) { - receivedAllEvents.TrySetResult(true); - Fixture.Log.Information("Received all {TotalEventsCount} expected events", seedEvents.Length); - } - - return Task.CompletedTask; - } - - void OnDropped(StreamSubscription sub, SubscriptionDroppedReason reason, Exception? ex) => - subscriptionDropped.SetResult(new(reason, ex)); - } - - [Fact] - public async Task receives_all_events_from_end() { - var receivedAllEvents = new TaskCompletionSource(); - var subscriptionDropped = new TaskCompletionSource(); - - var seedEvents = Fixture.CreateTestEvents(10).ToArray(); - - var availableEvents = new HashSet(seedEvents.Select(x => x.EventId)); - - using var subscription = await Fixture.Streams - .SubscribeToAllAsync(FromAll.End, OnReceived, false, OnDropped) - .WithTimeout(); - - // add the events we want to receive after we start the subscription - foreach (var evt in seedEvents) - await Fixture.Streams.AppendToStreamAsync($"stream-{evt.EventId.ToGuid():N}", StreamState.NoStream, new[] { evt }); - - await receivedAllEvents.Task.WithTimeout(); - - // if the subscription dropped before time, raise the reason why - if (subscriptionDropped.Task.IsCompleted) - subscriptionDropped.Task.IsCompleted.ShouldBe(false, subscriptionDropped.Task.Result.ToString()); - - // stop the subscription - subscription.Dispose(); - var result = await subscriptionDropped.Task.WithTimeout(); - result.ShouldBe(SubscriptionDroppedResult.Disposed()); - - return; - - Task OnReceived(StreamSubscription sub, ResolvedEvent re, CancellationToken ct) { - availableEvents.RemoveWhere(x => x == re.OriginalEvent.EventId); - - if (availableEvents.Count == 0) { - receivedAllEvents.TrySetResult(true); - Fixture.Log.Information("Received all {TotalEventsCount} expected events", seedEvents.Length); - } - - return Task.CompletedTask; - } - - void OnDropped(StreamSubscription sub, SubscriptionDroppedReason reason, Exception? ex) => - subscriptionDropped.SetResult(new(reason, ex)); - } - - [Fact] - public async Task receives_all_events_from_position() { - var receivedAllEvents = new TaskCompletionSource(); - var subscriptionDropped = new TaskCompletionSource(); - - var seedEvents = Fixture.CreateTestEvents(10).ToArray(); - var pageSize = seedEvents.Length / 2; - - // only the second half of the events will be received - var availableEvents = new HashSet(seedEvents.Skip(pageSize).Select(x => x.EventId)); - - IWriteResult writeResult = new SuccessResult(); - foreach (var evt in seedEvents.Take(pageSize)) - writeResult = await Fixture.Streams.AppendToStreamAsync($"stream-{evt.EventId.ToGuid():N}", StreamState.NoStream, new[] { evt }); - - var position = FromAll.After(writeResult.LogPosition); - - using var subscription = await Fixture.Streams - .SubscribeToAllAsync(position, OnReceived, false, OnDropped) - .WithTimeout(); - - foreach (var evt in seedEvents.Skip(pageSize)) - await Fixture.Streams.AppendToStreamAsync($"stream-{evt.EventId.ToGuid():N}", StreamState.NoStream, new[] { evt }); - - await receivedAllEvents.Task.WithTimeout(); - - // if the subscription dropped before time, raise the reason why - if (subscriptionDropped.Task.IsCompleted) - subscriptionDropped.Task.IsCompleted.ShouldBe(false, subscriptionDropped.Task.Result.ToString()); - - // stop the subscription - subscription.Dispose(); - var result = await subscriptionDropped.Task.WithTimeout(); - result.ShouldBe(SubscriptionDroppedResult.Disposed()); - - return; - - Task OnReceived(StreamSubscription sub, ResolvedEvent re, CancellationToken ct) { - availableEvents.RemoveWhere(x => x == re.OriginalEvent.EventId); - - if (availableEvents.Count == 0) { - receivedAllEvents.TrySetResult(true); - Fixture.Log.Information("Received all {TotalEventsCount} expected events", pageSize); - } - - return Task.CompletedTask; - } - - void OnDropped(StreamSubscription sub, SubscriptionDroppedReason reason, Exception? ex) => - subscriptionDropped.SetResult(new(reason, ex)); - } - - [Fact] - public async Task receives_all_events_with_resolved_links() { - var streamName = Fixture.GetStreamName(); - - var receivedAllEvents = new TaskCompletionSource(); - var subscriptionDropped = new TaskCompletionSource(); - - var seedEvents = Fixture.CreateTestEvents(3).ToArray(); - var availableEvents = new HashSet(seedEvents.Select(x => x.EventId)); - - await Fixture.Streams.AppendToStreamAsync(streamName, StreamState.NoStream, seedEvents); - - using var subscription = await Fixture.Streams - .SubscribeToAllAsync(FromAll.Start, OnReceived, true, OnDropped) - .WithTimeout(); - - await receivedAllEvents.Task.WithTimeout(); - - // if the subscription dropped before time, raise the reason why - if (subscriptionDropped.Task.IsCompleted) - subscriptionDropped.Task.IsCompleted.ShouldBe(false, subscriptionDropped.Task.Result.ToString()); - - // stop the subscription - subscription.Dispose(); - var result = await subscriptionDropped.Task.WithTimeout(); - result.ShouldBe(SubscriptionDroppedResult.Disposed()); - - return; - - Task OnReceived(StreamSubscription sub, ResolvedEvent re, CancellationToken ct) { - var hasResolvedLink = re.OriginalEvent.EventStreamId.StartsWith($"$et-{EventStoreFixture.TestEventType}"); - if (availableEvents.RemoveWhere(x => x == re.Event.EventId && hasResolvedLink) == 0) { - Fixture.Log.Debug("Received unexpected event {EventId} from stream {StreamId}", re.Event.EventId, re.OriginalEvent.EventStreamId); - return Task.CompletedTask; - } - - if (availableEvents.Count == 0) { - receivedAllEvents.TrySetResult(true); - Fixture.Log.Information("Received all {TotalEventsCount} expected events", seedEvents.Length); - } - - return Task.CompletedTask; - } - - void OnDropped(StreamSubscription sub, SubscriptionDroppedReason reason, Exception? ex) => - subscriptionDropped.SetResult(new(reason, ex)); - } - - [Theory] - [MemberData(nameof(SubscriptionFilter.TestCases), MemberType= typeof(SubscriptionFilter))] - public async Task receives_all_filtered_events_from_start(SubscriptionFilter filter) { - var streamPrefix = $"{nameof(receives_all_filtered_events_from_start)}-{filter.Name}-{Guid.NewGuid():N}"; - - Fixture.Log.Information("Using filter {FilterName} with prefix {StreamPrefix}", filter.Name, streamPrefix); - - var receivedAllEvents = new TaskCompletionSource(); - var subscriptionDropped = new TaskCompletionSource(); - var checkpointReached = new TaskCompletionSource(); - - var seedEvents = Fixture.CreateTestEvents(64) - .Select(evt => filter.PrepareEvent(streamPrefix, evt)) - .ToArray(); - - var pageSize = seedEvents.Length / 2; - - var availableEvents = new HashSet(seedEvents.Select(x => x.EventId)); - - // add noise - await Fixture.Streams.AppendToStreamAsync(Fixture.GetStreamName(), StreamState.NoStream, Fixture.CreateTestEvents(3)); - - var existingEventsCount = await Fixture.Streams.ReadAllAsync(Direction.Forwards, Position.Start).CountAsync(); - Fixture.Log.Debug("Existing events count: {ExistingEventsCount}", existingEventsCount); - - // Debugging: - // await foreach (var evt in Fixture.Streams.ReadAllAsync(Direction.Forwards, Position.Start)) - // Fixture.Log.Debug("Read event {EventId} from {StreamId}.", evt.OriginalEvent.EventId, evt.OriginalEvent.EventStreamId); - - // add some of the events we want to see before we start the subscription - foreach (var evt in seedEvents.Take(pageSize)) - await Fixture.Streams.AppendToStreamAsync($"{streamPrefix}-{evt.EventId.ToGuid():N}", StreamState.NoStream, new[] { evt }); - - var filterOptions = new SubscriptionFilterOptions(filter.Create(streamPrefix), 1, CheckpointReached); - - using var subscription = await Fixture.Streams - .SubscribeToAllAsync(FromAll.Start, OnReceived, false, OnDropped, filterOptions) - .WithTimeout(); - - // add some of the events we want to see after we start the subscription - foreach (var evt in seedEvents.Skip(pageSize)) - await Fixture.Streams.AppendToStreamAsync($"{streamPrefix}-{evt.EventId.ToGuid():N}", StreamState.NoStream, new[] { evt }); - - // wait until all events were received and at least one checkpoint was reached? - await receivedAllEvents.Task.WithTimeout(); - await checkpointReached.Task.WithTimeout(); - - // await Task.WhenAll(receivedAllEvents.Task, checkpointReached.Task).WithTimeout(); - - // if the subscription dropped before time, raise the reason why - if (subscriptionDropped.Task.IsCompleted) - subscriptionDropped.Task.IsCompleted.ShouldBe(false, subscriptionDropped.Task.Result.ToString()); - - // stop the subscription - subscription.Dispose(); - var result = await subscriptionDropped.Task.WithTimeout(); - result.ShouldBe(SubscriptionDroppedResult.Disposed()); - - Task OnReceived(StreamSubscription sub, ResolvedEvent re, CancellationToken ct) { - if (availableEvents.RemoveWhere(x => x == re.OriginalEvent.EventId) == 0) { - Fixture.Log.Error( - "Received unexpected event {EventId} from {StreamId}", - re.OriginalEvent.EventId, - re.OriginalEvent.EventStreamId - ); - - receivedAllEvents.TrySetException( - new InvalidOperationException($"Received unexpected event {re.OriginalEvent.EventId} from stream {re.OriginalEvent.EventStreamId}") - ); - } - else { - Fixture.Log.Verbose("Received expected event {EventId} from {StreamId}.", re.OriginalEvent.EventId, re.OriginalEvent.EventStreamId); - } - - if (availableEvents.Count == 0) { - receivedAllEvents.TrySetResult(true); - Fixture.Log.Information("Received all {TotalEventsCount} expected events.", seedEvents.Length); - } - - return Task.CompletedTask; - } - - void OnDropped(StreamSubscription sub, SubscriptionDroppedReason reason, Exception? ex) { - subscriptionDropped.SetResult(new(reason, ex)); - if (reason != SubscriptionDroppedReason.Disposed) { - receivedAllEvents.TrySetException(ex!); - checkpointReached.TrySetException(ex!); - } - } - - Task CheckpointReached(StreamSubscription sub, Position position, CancellationToken ct) { - Fixture.Log.Verbose( - "Checkpoint reached {Position}. Received {ReceivedEventsCount}/{TotalEventsCount} events", - position, seedEvents.Length - availableEvents.Count, seedEvents.Length - ); - checkpointReached.TrySetResult(true); - return Task.CompletedTask; - } - } - - [Theory] - [MemberData(nameof(SubscriptionFilter.TestCases), MemberType= typeof(SubscriptionFilter))] - public async Task receives_all_filtered_events_from_end(SubscriptionFilter filter) { - var streamPrefix = $"{nameof(receives_all_filtered_events_from_end)}-{filter.Name}-{Guid.NewGuid():N}"; - - Fixture.Log.Information("Using filter {FilterName} with prefix {StreamPrefix}", filter.Name, streamPrefix); - - var receivedAllEvents = new TaskCompletionSource(); - var subscriptionDropped = new TaskCompletionSource(); - var checkpointReached = new TaskCompletionSource(); - - var seedEvents = Fixture.CreateTestEvents(64) - .Select(evt => filter.PrepareEvent(streamPrefix, evt)) - .ToArray(); - - var pageSize = seedEvents.Length / 2; - - // only the second half of the events will be received - var availableEvents = new HashSet(seedEvents.Skip(pageSize).Select(x => x.EventId)); - - // add noise - await Fixture.Streams.AppendToStreamAsync(Fixture.GetStreamName(), StreamState.NoStream, Fixture.CreateTestEvents(3)); - - var existingEventsCount = await Fixture.Streams.ReadAllAsync(Direction.Forwards, Position.Start).CountAsync(); - Fixture.Log.Debug("Existing events count: {ExistingEventsCount}", existingEventsCount); - - // add some of the events that are a match to the filter but will not be received - foreach (var evt in seedEvents.Take(pageSize)) - await Fixture.Streams.AppendToStreamAsync($"{streamPrefix}-{evt.EventId.ToGuid():N}", StreamState.NoStream, new[] { evt }); - - var filterOptions = new SubscriptionFilterOptions(filter.Create(streamPrefix), 1, CheckpointReached); - - using var subscription = await Fixture.Streams - .SubscribeToAllAsync(FromAll.End, OnReceived, false, OnDropped, filterOptions) - .WithTimeout(); - - // add the events we want to receive after we start the subscription - foreach (var evt in seedEvents.Skip(pageSize)) - await Fixture.Streams.AppendToStreamAsync($"{streamPrefix}-{evt.EventId.ToGuid():N}", StreamState.NoStream, new[] { evt }); - - // wait until all events were received and at least one checkpoint was reached? - await receivedAllEvents.Task.WithTimeout(); - await checkpointReached.Task.WithTimeout(); - - // if the subscription dropped before time, raise the reason why - if (subscriptionDropped.Task.IsCompleted) - subscriptionDropped.Task.IsCompleted.ShouldBe(false, subscriptionDropped.Task.Result.ToString()); - - // stop the subscription - subscription.Dispose(); - var result = await subscriptionDropped.Task.WithTimeout(); - result.ShouldBe(SubscriptionDroppedResult.Disposed()); - - return; - - Task OnReceived(StreamSubscription sub, ResolvedEvent re, CancellationToken ct) { - if (availableEvents.RemoveWhere(x => x == re.OriginalEvent.EventId) == 0) { - Fixture.Log.Error( - "Received unexpected event {EventId} from {StreamId}", - re.OriginalEvent.EventId, - re.OriginalEvent.EventStreamId - ); - - receivedAllEvents.TrySetException( - new InvalidOperationException($"Received unexpected event {re.OriginalEvent.EventId} from stream {re.OriginalEvent.EventStreamId}") - ); - } - else { - Fixture.Log.Verbose("Received expected event {EventId} from {StreamId}", re.OriginalEvent.EventId, re.OriginalEvent.EventStreamId); - } - - if (availableEvents.Count == 0) { - receivedAllEvents.TrySetResult(true); - Fixture.Log.Information("Received all {TotalEventsCount} expected events", pageSize); - } - - return Task.CompletedTask; - } - - void OnDropped(StreamSubscription sub, SubscriptionDroppedReason reason, Exception? ex) { - subscriptionDropped.SetResult(new(reason, ex)); - if (reason != SubscriptionDroppedReason.Disposed) { - receivedAllEvents.TrySetException(ex!); - checkpointReached.TrySetException(ex!); - } - } - - Task CheckpointReached(StreamSubscription sub, Position position, CancellationToken ct) { - Fixture.Log.Verbose( - "Checkpoint reached {Position}. Received {ReceivedEventsCount}/{TotalEventsCount} events", - position, pageSize - availableEvents.Count, pageSize - ); - checkpointReached.TrySetResult(true); - return Task.CompletedTask; - } - } - - [Theory] - [MemberData(nameof(SubscriptionFilter.TestCases), MemberType= typeof(SubscriptionFilter))] - public async Task receives_all_filtered_events_from_position(SubscriptionFilter filter) { - var streamPrefix = $"{nameof(receives_all_filtered_events_from_position)}-{filter.Name}-{Guid.NewGuid():N}"; - - Fixture.Log.Information("Using filter {FilterName} with prefix {StreamPrefix}", filter.Name, streamPrefix); - - var receivedAllEvents = new TaskCompletionSource(); - var subscriptionDropped = new TaskCompletionSource(); - var checkpointReached = new TaskCompletionSource(); - - var seedEvents = Fixture.CreateTestEvents(64) - .Select(evt => filter.PrepareEvent(streamPrefix, evt)) - .ToArray(); - - var pageSize = seedEvents.Length / 2; - - // only the second half of the events will be received - var availableEvents = new HashSet(seedEvents.Skip(pageSize).Select(x => x.EventId)); - - // add noise - await Fixture.Streams.AppendToStreamAsync(Fixture.GetStreamName(), StreamState.NoStream, Fixture.CreateTestEvents(3)); - - var existingEventsCount = await Fixture.Streams.ReadAllAsync(Direction.Forwards, Position.Start).CountAsync(); - Fixture.Log.Debug("Existing events count: {ExistingEventsCount}", existingEventsCount); - - // add some of the events that are a match to the filter but will not be received - IWriteResult writeResult = new SuccessResult(); - foreach (var evt in seedEvents.Take(pageSize)) - writeResult = await Fixture.Streams.AppendToStreamAsync($"{streamPrefix}-{evt.EventId.ToGuid():N}", StreamState.NoStream, new[] { evt }); - - var position = FromAll.After(writeResult.LogPosition); - - var filterOptions = new SubscriptionFilterOptions(filter.Create(streamPrefix), 1, CheckpointReached); - - using var subscription = await Fixture.Streams - .SubscribeToAllAsync(position, OnReceived, false, OnDropped, filterOptions) - .WithTimeout(); - - // add the events we want to receive after we start the subscription - foreach (var evt in seedEvents.Skip(pageSize)) - await Fixture.Streams.AppendToStreamAsync($"{streamPrefix}-{evt.EventId.ToGuid():N}", StreamState.NoStream, new[] { evt }); - - // wait until all events were received and at least one checkpoint was reached? - await receivedAllEvents.Task.WithTimeout(); - await checkpointReached.Task.WithTimeout(); - - // if the subscription dropped before time, raise the reason why - if (subscriptionDropped.Task.IsCompleted) - subscriptionDropped.Task.IsCompleted.ShouldBe(false, subscriptionDropped.Task.Result.ToString()); - - // stop the subscription - subscription.Dispose(); - var result = await subscriptionDropped.Task.WithTimeout(); - result.ShouldBe(SubscriptionDroppedResult.Disposed()); - - return; - - Task OnReceived(StreamSubscription sub, ResolvedEvent re, CancellationToken ct) { - if (availableEvents.RemoveWhere(x => x == re.OriginalEvent.EventId) == 0) { - Fixture.Log.Error( - "Received unexpected event {EventId} from {StreamId}", - re.OriginalEvent.EventId, - re.OriginalEvent.EventStreamId - ); - - receivedAllEvents.TrySetException( - new InvalidOperationException($"Received unexpected event {re.OriginalEvent.EventId} from stream {re.OriginalEvent.EventStreamId}") - ); - } - else { - Fixture.Log.Verbose("Received expected event {EventId} from {StreamId}", re.OriginalEvent.EventId, re.OriginalEvent.EventStreamId); - } - - if (availableEvents.Count == 0) { - receivedAllEvents.TrySetResult(true); - Fixture.Log.Information("Received all {TotalEventsCount} expected events", pageSize); - } - - return Task.CompletedTask; - } - - void OnDropped(StreamSubscription sub, SubscriptionDroppedReason reason, Exception? ex) { - subscriptionDropped.SetResult(new(reason, ex)); - if (reason != SubscriptionDroppedReason.Disposed) { - receivedAllEvents.TrySetException(ex!); - checkpointReached.TrySetException(ex!); - } - } - - Task CheckpointReached(StreamSubscription sub, Position position, CancellationToken ct) { - Fixture.Log.Verbose( - "Checkpoint reached {Position}. Received {ReceivedEventsCount}/{TotalEventsCount} events", - position, pageSize - availableEvents.Count, pageSize - ); - checkpointReached.TrySetResult(true); - return Task.CompletedTask; - } - } - - [Fact] - public async Task receives_all_filtered_events_with_resolved_links() { - var streamName = Fixture.GetStreamName(); - - var receivedAllEvents = new TaskCompletionSource(); - var subscriptionDropped = new TaskCompletionSource(); - - var seedEvents = Fixture.CreateTestEvents(3).ToArray(); - var availableEvents = new HashSet(seedEvents.Select(x => x.EventId)); - - await Fixture.Streams.AppendToStreamAsync(streamName, StreamState.NoStream, seedEvents); - - var options = new SubscriptionFilterOptions( - StreamFilter.Prefix($"$et-{EventStoreFixture.TestEventType}") - ); - - using var subscription = await Fixture.Streams - .SubscribeToAllAsync(FromAll.Start, OnReceived, true, OnDropped, options) - .WithTimeout(); - - await receivedAllEvents.Task.WithTimeout(); - - // if the subscription dropped before time, raise the reason why - if (subscriptionDropped.Task.IsCompleted) - subscriptionDropped.Task.IsCompleted.ShouldBe(false, subscriptionDropped.Task.Result.ToString()); - - // stop the subscription - subscription.Dispose(); - var result = await subscriptionDropped.Task.WithTimeout(); - result.ShouldBe(SubscriptionDroppedResult.Disposed()); - - return; - - Task OnReceived(StreamSubscription sub, ResolvedEvent re, CancellationToken ct) { - var hasResolvedLink = re.OriginalEvent.EventStreamId.StartsWith($"$et-{EventStoreFixture.TestEventType}"); - if (availableEvents.RemoveWhere(x => x == re.Event.EventId && hasResolvedLink) == 0) { - Fixture.Log.Debug("Received unexpected event {EventId} from stream {StreamId}", re.Event.EventId, re.OriginalEvent.EventStreamId); - return Task.CompletedTask; - } - - if (availableEvents.Count == 0) { - receivedAllEvents.TrySetResult(true); - Fixture.Log.Information("Received all {TotalEventsCount} expected events", seedEvents.Length); - } - - return Task.CompletedTask; - } - - void OnDropped(StreamSubscription sub, SubscriptionDroppedReason reason, Exception? ex) => - subscriptionDropped.SetResult(new(reason, ex)); - } - - [Fact] - public async Task drops_when_disposed() { - var subscriptionDropped = new TaskCompletionSource(); - - using var subscription = await Fixture.Streams - .SubscribeToAllAsync( - FromAll.Start, - (sub, re, ct) => Task.CompletedTask, - false, - (sub, reason, ex) => subscriptionDropped.SetResult(new(reason, ex)) - ) - .WithTimeout(); - - // if the subscription dropped before time, raise the reason why - if (subscriptionDropped.Task.IsCompleted) - subscriptionDropped.Task.IsCompleted.ShouldBe(false, subscriptionDropped.Task.Result.ToString()); - - // stop the subscription - subscription.Dispose(); - var result = await subscriptionDropped.Task.WithTimeout(); - result.ShouldBe(SubscriptionDroppedResult.Disposed()); - } - - [Fact] - public async Task drops_when_subscriber_error() { - var expectedResult = SubscriptionDroppedResult.SubscriberError(); - - var subscriptionDropped = new TaskCompletionSource(); - - using var subscription = await Fixture.Streams - .SubscribeToAllAsync( - FromAll.Start, - (sub, re, ct) => expectedResult.Throw(), - false, - (sub, reason, ex) => subscriptionDropped.SetResult(new(reason, ex)) - ) - .WithTimeout(); - - await Fixture.Streams.AppendToStreamAsync(Fixture.GetStreamName(), StreamState.NoStream, Fixture.CreateTestEvents()); - - var result = await subscriptionDropped.Task.WithTimeout(); - result.ShouldBe(expectedResult); - } -} diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/Obsolete/subscribe_to_stream_obsolete.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/Obsolete/subscribe_to_stream_obsolete.cs deleted file mode 100644 index 4e05b293b..000000000 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/Obsolete/subscribe_to_stream_obsolete.cs +++ /dev/null @@ -1,303 +0,0 @@ -namespace EventStore.Client.Streams.Tests.Subscriptions.Obsolete; - -[Trait("Category", "Subscriptions")] -[Trait("Category", "Target:Stream")] -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class subscribe_to_stream_obsolete(ITestOutputHelper output, SubscriptionsFixture fixture) : EventStoreTests(output, fixture) { - [Fact] - public async Task receives_all_events_from_start() { - var streamName = Fixture.GetStreamName(); - - var receivedAllEvents = new TaskCompletionSource(); - var subscriptionDropped = new TaskCompletionSource(); - - var seedEvents = Fixture.CreateTestEvents(10).ToArray(); - var pageSize = seedEvents.Length / 2; - - var availableEvents = new HashSet(seedEvents.Select(x => x.EventId)); - - await Fixture.Streams.AppendToStreamAsync(streamName, StreamState.NoStream, seedEvents.Take(pageSize)); - - using var subscription = await Fixture.Streams - .SubscribeToStreamAsync(streamName, FromStream.Start, OnReceived, false, OnDropped) - .WithTimeout(); - - await Fixture.Streams.AppendToStreamAsync(streamName, StreamState.StreamExists, seedEvents.Skip(pageSize)); - - await receivedAllEvents.Task.WithTimeout(); - - // if the subscription dropped before time, raise the reason why - if (subscriptionDropped.Task.IsCompleted) - subscriptionDropped.Task.IsCompleted.ShouldBe(false, subscriptionDropped.Task.Result.ToString()); - - // stop the subscription - subscription.Dispose(); - var result = await subscriptionDropped.Task.WithTimeout(); - result.ShouldBe(SubscriptionDroppedResult.Disposed()); - - return; - - Task OnReceived(StreamSubscription sub, ResolvedEvent re, CancellationToken ct) { - availableEvents.RemoveWhere(x => x == re.OriginalEvent.EventId); - - if (availableEvents.Count == 0) { - receivedAllEvents.TrySetResult(true); - Fixture.Log.Information("Received all {TotalEventsCount} expected events", seedEvents.Length); - } - - return Task.CompletedTask; - } - - void OnDropped(StreamSubscription sub, SubscriptionDroppedReason reason, Exception? ex) => - subscriptionDropped.SetResult(new(reason, ex)); - } - - [Fact] - public async Task receives_all_events_from_position() { - var streamName = Fixture.GetStreamName(); - - var receivedAllEvents = new TaskCompletionSource(); - var subscriptionDropped = new TaskCompletionSource(); - - var seedEvents = Fixture.CreateTestEvents(10).ToArray(); - var pageSize = seedEvents.Length / 2; - - // only the second half of the events will be received - var availableEvents = new HashSet(seedEvents.Skip(pageSize).Select(x => x.EventId)); - - var writeResult = await Fixture.Streams.AppendToStreamAsync(streamName, StreamState.NoStream, seedEvents.Take(pageSize)); - var streamPosition = StreamPosition.FromStreamRevision(writeResult.NextExpectedStreamRevision); - var checkpoint = FromStream.After(streamPosition); - - using var subscription = await Fixture.Streams - .SubscribeToStreamAsync(streamName, checkpoint, OnReceived, false, OnDropped) - .WithTimeout(); - - await Fixture.Streams.AppendToStreamAsync(streamName, writeResult.NextExpectedStreamRevision, seedEvents.Skip(pageSize)); - - await receivedAllEvents.Task.WithTimeout(); - - // if the subscription dropped before time, raise the reason why - if (subscriptionDropped.Task.IsCompleted) - subscriptionDropped.Task.IsCompleted.ShouldBe(false, subscriptionDropped.Task.Result.ToString()); - - // stop the subscription - subscription.Dispose(); - var result = await subscriptionDropped.Task.WithTimeout(); - result.ShouldBe(SubscriptionDroppedResult.Disposed()); - - return; - - Task OnReceived(StreamSubscription sub, ResolvedEvent re, CancellationToken ct) { - availableEvents.RemoveWhere(x => x == re.OriginalEvent.EventId); - - if (availableEvents.Count == 0) { - receivedAllEvents.TrySetResult(true); - Fixture.Log.Information("Received all {TotalEventsCount} expected events", pageSize); - } - - return Task.CompletedTask; - } - - void OnDropped(StreamSubscription sub, SubscriptionDroppedReason reason, Exception? ex) => - subscriptionDropped.SetResult(new(reason, ex)); - } - - [Fact] - public async Task receives_all_events_from_non_existing_stream() { - var streamName = Fixture.GetStreamName(); - - var receivedAllEvents = new TaskCompletionSource(); - var subscriptionDropped = new TaskCompletionSource(); - - var seedEvents = Fixture.CreateTestEvents(10).ToArray(); - - var availableEvents = new HashSet(seedEvents.Select(x => x.EventId)); - - using var subscription = await Fixture.Streams - .SubscribeToStreamAsync(streamName, FromStream.Start, OnReceived, false, OnDropped) - .WithTimeout(); - - await Fixture.Streams.AppendToStreamAsync(streamName, StreamState.NoStream, seedEvents); - - await receivedAllEvents.Task.WithTimeout(); - - // if the subscription dropped before time, raise the reason why - if (subscriptionDropped.Task.IsCompleted) - subscriptionDropped.Task.IsCompleted.ShouldBe(false, subscriptionDropped.Task.Result.ToString()); - - // stop the subscription - subscription.Dispose(); - var result = await subscriptionDropped.Task.WithTimeout(); - result.ShouldBe(SubscriptionDroppedResult.Disposed()); - - return; - - Task OnReceived(StreamSubscription sub, ResolvedEvent re, CancellationToken ct) { - availableEvents.RemoveWhere(x => x == re.OriginalEvent.EventId); - - if (availableEvents.Count == 0) { - receivedAllEvents.TrySetResult(true); - Fixture.Log.Information("Received all {TotalEventsCount} expected events", seedEvents.Length); - } - - return Task.CompletedTask; - } - - void OnDropped(StreamSubscription sub, SubscriptionDroppedReason reason, Exception? ex) => - subscriptionDropped.SetResult(new(reason, ex)); - } - - [Fact] - public async Task allow_multiple_subscriptions_to_same_stream() { - var streamName = Fixture.GetStreamName(); - - var receivedAllEvents = new TaskCompletionSource(); - - var seedEvents = Fixture.CreateTestEvents(5).ToArray(); - - var targetEventsCount = seedEvents.Length * 2; - - await Fixture.Streams.AppendToStreamAsync(streamName, StreamState.NoStream, seedEvents); - - using var subscription1 = await Fixture.Streams - .SubscribeToStreamAsync(streamName, FromStream.Start, OnReceived) - .WithTimeout(); - - using var subscription2 = await Fixture.Streams - .SubscribeToStreamAsync(streamName, FromStream.Start, OnReceived) - .WithTimeout(); - - await receivedAllEvents.Task.WithTimeout(); - - Task OnReceived(StreamSubscription sub, ResolvedEvent re, CancellationToken ct) { - if (--targetEventsCount == 0) { - receivedAllEvents.TrySetResult(true); - Fixture.Log.Information("Received all {TotalEventsCount} expected events", seedEvents.Length); - } - - return Task.CompletedTask; - } - } - - [Fact] - public async Task drops_when_disposed() { - var streamName = Fixture.GetStreamName(); - - var subscriptionDropped = new TaskCompletionSource(); - - using var subscription = await Fixture.Streams - .SubscribeToStreamAsync( - streamName, - FromStream.Start, - (sub, re, ct) => Task.CompletedTask, - false, - (sub, reason, ex) => subscriptionDropped.SetResult(new(reason, ex)) - ) - .WithTimeout(); - - // if the subscription dropped before time, raise the reason why - if (subscriptionDropped.Task.IsCompleted) - subscriptionDropped.Task.IsCompleted.ShouldBe(false, subscriptionDropped.Task.Result.ToString()); - - // stop the subscription - subscription.Dispose(); - var result = await subscriptionDropped.Task.WithTimeout(); - result.ShouldBe(SubscriptionDroppedResult.Disposed()); - } - - [Fact] - public async Task drops_when_subscriber_error() { - var streamName = Fixture.GetStreamName(); - - var expectedResult = SubscriptionDroppedResult.SubscriberError(); - - var subscriptionDropped = new TaskCompletionSource(); - - using var subscription = await Fixture.Streams - .SubscribeToStreamAsync( - streamName, - FromStream.Start, - (sub, re, ct) => expectedResult.Throw(), - false, - (sub, reason, ex) => subscriptionDropped.SetResult(new(reason, ex)) - ) - .WithTimeout(); - - await Fixture.Streams.AppendToStreamAsync(streamName, StreamState.NoStream, Fixture.CreateTestEvents()); - - var result = await subscriptionDropped.Task.WithTimeout(); - result.ShouldBe(expectedResult); - } - - [Fact] - public async Task drops_when_stream_tombstoned() { - var streamName = Fixture.GetStreamName(); - - var subscriptionDropped = new TaskCompletionSource(); - - using var subscription = await Fixture.Streams - .SubscribeToStreamAsync( - streamName, - FromStream.Start, - (sub, re, ct) => Task.CompletedTask, - false, - (sub, reason, ex) => { subscriptionDropped.SetResult(new(reason, ex)); } - ) - .WithTimeout(); - - // rest in peace - await Fixture.Streams.TombstoneAsync(streamName, StreamState.NoStream); - - var result = await subscriptionDropped.Task.WithTimeout(); - result.Error.ShouldBeOfType().Stream.ShouldBe(streamName); - } - - [Fact] - public async Task receives_all_events_with_resolved_links() { - var streamName = Fixture.GetStreamName(); - - var receivedAllEvents = new TaskCompletionSource(); - var subscriptionDropped = new TaskCompletionSource(); - - var seedEvents = Fixture.CreateTestEvents(3).ToArray(); - var availableEvents = new HashSet(seedEvents.Select(x => x.EventId)); - - await Fixture.Streams.AppendToStreamAsync(streamName, StreamState.NoStream, seedEvents); - - using var subscription = await Fixture.Streams - .SubscribeToStreamAsync($"$et-{EventStoreFixture.TestEventType}", FromStream.Start, OnReceived, true, OnDropped) - .WithTimeout(); - - await receivedAllEvents.Task.WithTimeout(); - - // if the subscription dropped before time, raise the reason why - if (subscriptionDropped.Task.IsCompleted) - subscriptionDropped.Task.IsCompleted.ShouldBe(false, subscriptionDropped.Task.Result.ToString()); - - // stop the subscription - subscription.Dispose(); - var result = await subscriptionDropped.Task.WithTimeout(); - result.ShouldBe(SubscriptionDroppedResult.Disposed()); - - return; - - Task OnReceived(StreamSubscription sub, ResolvedEvent re, CancellationToken ct) { - var hasResolvedLink = re.OriginalEvent.EventStreamId.StartsWith($"$et-{EventStoreFixture.TestEventType}"); - if (availableEvents.RemoveWhere(x => x == re.Event.EventId && hasResolvedLink) == 0) { - Fixture.Log.Debug("Received unexpected event {EventId} from stream {StreamId}", re.Event.EventId, re.OriginalEvent.EventStreamId); - return Task.CompletedTask; - } - - if (availableEvents.Count == 0) { - receivedAllEvents.TrySetResult(true); - Fixture.Log.Information("Received all {TotalEventsCount} expected events", seedEvents.Length); - } - - return Task.CompletedTask; - } - - void OnDropped(StreamSubscription sub, SubscriptionDroppedReason reason, Exception? ex) => - subscriptionDropped.SetResult(new(reason, ex)); - } -} diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionDroppedResult.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionDroppedResult.cs deleted file mode 100644 index 40df3eb52..000000000 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionDroppedResult.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace EventStore.Client.Streams.Tests.Subscriptions; - -public record SubscriptionDroppedResult(SubscriptionDroppedReason Reason, Exception? Error) { - public Task Throw() => Task.FromException(Error!); - - public static SubscriptionDroppedResult ServerError(Exception? error = null) => - new(SubscriptionDroppedReason.ServerError, error ?? new Exception("Server error")); - - public static SubscriptionDroppedResult SubscriberError(Exception? error = null) => - new(SubscriptionDroppedReason.SubscriberError, error ?? new Exception("Subscriber error")); - - public static SubscriptionDroppedResult Disposed(Exception? error = null) => - new(SubscriptionDroppedReason.Disposed, error); - - public override string ToString() => $"{Reason} {Error?.Message ?? string.Empty}".Trim(); -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionsFixture.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionsFixture.cs deleted file mode 100644 index 582344f98..000000000 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionsFixture.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace EventStore.Client.Streams.Tests.Subscriptions; - - -[Trait("Category", "Subscriptions")] -public class SubscriptionsFixture : EventStoreFixture { - public SubscriptionsFixture(): base(x => x.RunProjections()) { - OnSetup = async () => { - await Streams.SetStreamMetadataAsync( - SystemStreams.AllStream, - StreamState.NoStream, - new(acl: new(SystemRoles.All)), - userCredentials: TestCredentials.Root - ); - - await Streams.AppendToStreamAsync($"SubscriptionsFixture-Noise-{Guid.NewGuid():N}", StreamState.NoStream, CreateTestEvents(10)); - }; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/reconnection.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/reconnection.cs deleted file mode 100644 index 2dc9912e5..000000000 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/reconnection.cs +++ /dev/null @@ -1,178 +0,0 @@ -using Grpc.Core; -using static System.TimeSpan; - -namespace EventStore.Client.Streams.Tests.Subscriptions; - -[Trait("Category", "Subscriptions")] -[Obsolete] -public class @reconnection(ITestOutputHelper output, ReconnectionFixture fixture) : EventStoreTests(output, fixture) { - [Theory] - [InlineData(4, 5000, 0, 30000)] - public async Task when_the_connection_is_lost(int expectedNumberOfEvents, int reconnectDelayMs, int serviceRestartDelayMs, int testTimeoutMs) { - using var cancellator = new CancellationTokenSource().With(x => x.CancelAfter(testTimeoutMs)); - - var streamName = Fixture.GetStreamName(); - - // create backpressure by producing half of the events - await Fixture.ProduceEvents(streamName, expectedNumberOfEvents / 2, cancellationToken: cancellator.Token); - - // create subscription that will actually receive the first event and - // then wait for the service to be restarted - // but we are evil and will force the drop of the subscription muah ah ah - var consumeEvents = Fixture.ConsumeEvents( - streamName, - expectedNumberOfEvents, - FromMilliseconds(reconnectDelayMs), - cancellator.Token - ); - - // create chaos by pausing the service - await Fixture.RestartService(FromMilliseconds(serviceRestartDelayMs)); - - // produce the rest of the events to make it more interesting - await Fixture.ProduceEvents(streamName, expectedNumberOfEvents / 2, cancellationToken: cancellator.Token); - - // wait for the subscription to receive all events or timeout - await consumeEvents.ShouldNotThrowAsync(); - } -} - -public class ReconnectionFixture() - : EventStoreFixture( - x => x.RunInMemory(false) - .With(o => o.ClientSettings.ConnectivitySettings.DiscoveryInterval = FromMilliseconds(100)) - .With(o => o.ClientSettings.ConnectivitySettings.GossipTimeout = FromMilliseconds(100)) - ) -{ - public async Task ProduceEvents(string streamName, int numberOfEvents, StreamState? streamState = null, CancellationToken cancellationToken = default) { - while (!cancellationToken.IsCancellationRequested) { - try { - var result = await Streams.AppendToStreamAsync( - streamName, - streamState.GetValueOrDefault(StreamState.Any), - CreateTestEvents(numberOfEvents), - cancellationToken: cancellationToken - ); - - if (result is SuccessResult success) { - Log.Information( - "{NumberOfEvents} events produced to {StreamName}.", numberOfEvents, streamName - ); - - return; - } - - Log.Error( - "Failed to produce {NumberOfEvents} events to {StreamName}.", numberOfEvents, streamName - ); - - await Task.Delay(250); - } - catch (Exception ex) when ( ex is not OperationCanceledException) { - Log.Error( - ex, "Failed to produce {NumberOfEvents} events to {StreamName}.", numberOfEvents, streamName - ); - - await Task.Delay(250); - } - } - } - - public Task ConsumeEvents( - string streamName, - int expectedNumberOfEvents, - TimeSpan reconnectDelay, - CancellationToken cancellationToken - ) { - var receivedAllEvents = new TaskCompletionSource(); - - var receivedEventsCount = 0; - - _ = SubscribeToStream( - streamName, - checkpoint: null, - OnReceive(), - OnDrop(), - cancellationToken - ); - - return receivedAllEvents.Task; - - Func OnReceive() { - return re => { - receivedEventsCount++; - Log.Debug("{ReceivedEventsCount}/{ExpectedNumberOfEvents} events received.", receivedEventsCount, expectedNumberOfEvents); - - if (receivedEventsCount == expectedNumberOfEvents) { - Log.Information("Test complete. {ReceivedEventsCount}/{ExpectedNumberOfEvents} events received.", receivedEventsCount, expectedNumberOfEvents); - receivedAllEvents.TrySetResult(); - } - - return Task.CompletedTask; - }; - } - - Func> OnDrop() { - return async (reason, ex) => { - if (ex is RpcException { StatusCode: StatusCode.Unavailable or StatusCode.DeadlineExceeded }) { - Log.Warning("Transitive exception detected. Retrying connection in {reconnectDelayMs}ms.", reconnectDelay.TotalMilliseconds); - await Task.Delay(reconnectDelay); - return true; - } - - if (reason == SubscriptionDroppedReason.Disposed || ex is OperationCanceledException || ex is TaskCanceledException || ex is null) { - if (receivedEventsCount != expectedNumberOfEvents) - receivedAllEvents.TrySetException(new TimeoutException($"Test timeout detected. {receivedEventsCount}/{expectedNumberOfEvents} events received.", ex)); - else { - Log.Information("Test cancellation requested. {ReceivedEventsCount}/{ExpectedNumberOfEvents} events received.", receivedEventsCount, expectedNumberOfEvents); - receivedAllEvents.TrySetCanceled(cancellationToken); - } - - return false; - } - - Log.Fatal(ex, "Fatal exception detected. This is the end..."); - receivedAllEvents.SetException(ex); - - return false; - }; - } - } - - [Obsolete] - async Task SubscribeToStream( - string stream, - StreamPosition? checkpoint, - Func onReceive, - Func> onDrop, - CancellationToken cancellationToken - ) { - var start = checkpoint == null ? FromStream.Start : FromStream.After(checkpoint.Value); - - Log.Verbose("Attempting to start from checkpoint: {Checkpoint}.", checkpoint); - - try { - var sub = await Streams.SubscribeToStreamAsync( - streamName: stream, - start: start, - eventAppeared: async (s, re, ct) => { - await onReceive(re); - checkpoint = re.OriginalEventNumber; - Log.Verbose("Checkpoint Set: {Checkpoint}.", checkpoint); - }, - subscriptionDropped: async (s, reason, ex) => { - var resubscribe = await onDrop(reason, ex); - if (resubscribe) _ = SubscribeToStream(stream, checkpoint, onReceive, onDrop, cancellationToken); - }, - cancellationToken: cancellationToken - ); - } catch (Exception ex) { - var reason = ex is OperationCanceledException or TaskCanceledException - ? SubscriptionDroppedReason.Disposed - : SubscriptionDroppedReason.SubscriberError; - - var resubscribe = await onDrop(reason, ex); - if (resubscribe) _ = SubscribeToStream(stream, checkpoint, onReceive, onDrop, cancellationToken); - } - } -} diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all.cs deleted file mode 100644 index 2e9879a4a..000000000 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all.cs +++ /dev/null @@ -1,480 +0,0 @@ -namespace EventStore.Client.Streams.Tests.Subscriptions; - -[Trait("Category", "Subscriptions")] -[Trait("Category", "Target:All")] -public class subscribe_to_all(ITestOutputHelper output, SubscriptionsFixture fixture) - : EventStoreTests(output, fixture) { - [Fact] - public async Task receives_all_events_from_start() { - var seedEvents = Fixture.CreateTestEvents(10).ToArray(); - var pageSize = seedEvents.Length / 2; - - var availableEvents = new HashSet(seedEvents.Select(x => x.EventId)); - - foreach (var evt in seedEvents.Take(pageSize)) - await Fixture.Streams.AppendToStreamAsync( - $"stream-{evt.EventId.ToGuid():N}", - StreamState.NoStream, - new[] { evt } - ); - - await using var subscription = Fixture.Streams.SubscribeToAll(FromAll.Start); - await using var enumerator = subscription.Messages.GetAsyncEnumerator(); - - Assert.True(await enumerator.MoveNextAsync()); - - Assert.IsType(enumerator.Current); - - foreach (var evt in seedEvents.Skip(pageSize)) - await Fixture.Streams.AppendToStreamAsync( - $"stream-{evt.EventId.ToGuid():N}", - StreamState.NoStream, - new[] { evt } - ); - - await Subscribe().WithTimeout(); - - return; - - async Task Subscribe() { - while (await enumerator.MoveNextAsync()) { - if (enumerator.Current is not StreamMessage.Event(var resolvedEvent)) { - continue; - } - - availableEvents.Remove(resolvedEvent.Event.EventId); - - if (availableEvents.Count == 0) { - return; - } - } - } - } - - [Fact] - public async Task receives_all_events_from_end() { - var seedEvents = Fixture.CreateTestEvents(10).ToArray(); - - var availableEvents = new HashSet(seedEvents.Select(x => x.EventId)); - - await using var subscription = Fixture.Streams.SubscribeToAll(FromAll.End); - await using var enumerator = subscription.Messages.GetAsyncEnumerator(); - - Assert.True(await enumerator.MoveNextAsync()); - - Assert.IsType(enumerator.Current); - - // add the events we want to receive after we start the subscription - foreach (var evt in seedEvents) - await Fixture.Streams.AppendToStreamAsync( - $"stream-{evt.EventId.ToGuid():N}", - StreamState.NoStream, - new[] { evt } - ); - - await Subscribe().WithTimeout(); - - return; - - async Task Subscribe() { - while (await enumerator.MoveNextAsync()) { - if (enumerator.Current is not StreamMessage.Event(var resolvedEvent)) { - continue; - } - - availableEvents.Remove(resolvedEvent.OriginalEvent.EventId); - - if (availableEvents.Count == 0) { - return; - } - } - } - } - - [Fact] - public async Task receives_all_events_from_position() { - var seedEvents = Fixture.CreateTestEvents(10).ToArray(); - var pageSize = seedEvents.Length / 2; - - // only the second half of the events will be received - var availableEvents = new HashSet(seedEvents.Skip(pageSize).Select(x => x.EventId)); - - IWriteResult writeResult = new SuccessResult(); - foreach (var evt in seedEvents.Take(pageSize)) - writeResult = await Fixture.Streams.AppendToStreamAsync( - $"stream-{evt.EventId.ToGuid():N}", - StreamState.NoStream, - new[] { evt } - ); - - var position = FromAll.After(writeResult.LogPosition); - - await using var subscription = Fixture.Streams.SubscribeToAll(position); - await using var enumerator = subscription.Messages.GetAsyncEnumerator(); - - Assert.True(await enumerator.MoveNextAsync()); - - Assert.IsType(enumerator.Current); - - foreach (var evt in seedEvents.Skip(pageSize)) - await Fixture.Streams.AppendToStreamAsync( - $"stream-{evt.EventId.ToGuid():N}", - StreamState.NoStream, - new[] { evt } - ); - - await Subscribe().WithTimeout(); - - return; - - async Task Subscribe() { - while (await enumerator.MoveNextAsync()) { - if (enumerator.Current is not StreamMessage.Event(var resolvedEvent)) { - continue; - } - - availableEvents.Remove(resolvedEvent.Event.EventId); - - if (availableEvents.Count == 0) { - return; - } - } - } - } - - [Fact] - public async Task receives_all_events_with_resolved_links() { - var streamName = Fixture.GetStreamName(); - - var seedEvents = Fixture.CreateTestEvents(3).ToArray(); - var availableEvents = new HashSet(seedEvents.Select(x => x.EventId)); - - await Fixture.Streams.AppendToStreamAsync(streamName, StreamState.NoStream, seedEvents); - - await using var subscription = Fixture.Streams.SubscribeToAll(FromAll.Start, true); - await using var enumerator = subscription.Messages.GetAsyncEnumerator(); - - Assert.True(await enumerator.MoveNextAsync()); - - Assert.IsType(enumerator.Current); - - await Subscribe().WithTimeout(); - - return; - - async Task Subscribe() { - while (await enumerator.MoveNextAsync()) { - if (enumerator.Current is not StreamMessage.Event(var resolvedEvent)) { - continue; - } - - availableEvents.Remove(resolvedEvent.Event.EventId); - - if (availableEvents.Count == 0) { - return; - } - } - } - } - - [Theory] - [MemberData(nameof(SubscriptionFilter.TestCases), MemberType = typeof(SubscriptionFilter))] - public async Task receives_all_filtered_events_from_start(SubscriptionFilter filter) { - var streamPrefix = $"{nameof(receives_all_filtered_events_from_start)}-{filter.Name}-{Guid.NewGuid():N}"; - - Fixture.Log.Information("Using filter {FilterName} with prefix {StreamPrefix}", filter.Name, streamPrefix); - - var seedEvents = Fixture.CreateTestEvents(64) - .Select(evt => filter.PrepareEvent(streamPrefix, evt)) - .ToArray(); - - var pageSize = seedEvents.Length / 2; - - var availableEvents = new HashSet(seedEvents.Select(x => x.EventId)); - - // add noise - await Fixture.Streams.AppendToStreamAsync( - Fixture.GetStreamName(), - StreamState.NoStream, - Fixture.CreateTestEvents(3) - ); - - var existingEventsCount = await Fixture.Streams.ReadAllAsync(Direction.Forwards, Position.Start) - .Messages.CountAsync(); - - Fixture.Log.Debug("Existing events count: {ExistingEventsCount}", existingEventsCount); - - // Debugging: - // await foreach (var evt in Fixture.Streams.ReadAllAsync(Direction.Forwards, Position.Start)) - // Fixture.Log.Debug("Read event {EventId} from {StreamId}.", evt.OriginalEvent.EventId, evt.OriginalEvent.EventStreamId); - - // add some of the events we want to see before we start the subscription - foreach (var evt in seedEvents.Take(pageSize)) - await Fixture.Streams.AppendToStreamAsync( - $"{streamPrefix}-{evt.EventId.ToGuid():N}", - StreamState.NoStream, - new[] { evt } - ); - - var filterOptions = new SubscriptionFilterOptions(filter.Create(streamPrefix), 1); - - await using var subscription = Fixture.Streams.SubscribeToAll(FromAll.Start, filterOptions: filterOptions); - await using var enumerator = subscription.Messages.GetAsyncEnumerator(); - - Assert.True(await enumerator.MoveNextAsync()); - - Assert.IsType(enumerator.Current); - - // add some of the events we want to see after we start the subscription - foreach (var evt in seedEvents.Skip(pageSize)) - await Fixture.Streams.AppendToStreamAsync( - $"{streamPrefix}-{evt.EventId.ToGuid():N}", - StreamState.NoStream, - new[] { evt } - ); - - bool checkpointReached = false; - - await Subscribe().WithTimeout(); - - Assert.True(checkpointReached); - - return; - - async Task Subscribe() { - while (await enumerator.MoveNextAsync()) { - switch (enumerator.Current) { - case StreamMessage.AllStreamCheckpointReached: - checkpointReached = true; - - break; - - case StreamMessage.Event(var resolvedEvent): { - availableEvents.Remove(resolvedEvent.Event.EventId); - - if (availableEvents.Count == 0) { - return; - } - - break; - } - } - } - } - } - - [Theory] - [MemberData(nameof(SubscriptionFilter.TestCases), MemberType = typeof(SubscriptionFilter))] - public async Task receives_all_filtered_events_from_end(SubscriptionFilter filter) { - var streamPrefix = $"{nameof(receives_all_filtered_events_from_end)}-{filter.Name}-{Guid.NewGuid():N}"; - - Fixture.Log.Information("Using filter {FilterName} with prefix {StreamPrefix}", filter.Name, streamPrefix); - - var seedEvents = Fixture.CreateTestEvents(64) - .Select(evt => filter.PrepareEvent(streamPrefix, evt)) - .ToArray(); - - var pageSize = seedEvents.Length / 2; - - // only the second half of the events will be received - var availableEvents = new HashSet(seedEvents.Skip(pageSize).Select(x => x.EventId)); - - // add noise - await Fixture.Streams.AppendToStreamAsync( - Fixture.GetStreamName(), - StreamState.NoStream, - Fixture.CreateTestEvents(3) - ); - - var existingEventsCount = await Fixture.Streams.ReadAllAsync(Direction.Forwards, Position.Start) - .Messages.CountAsync(); - - Fixture.Log.Debug("Existing events count: {ExistingEventsCount}", existingEventsCount); - - // Debugging: - // await foreach (var evt in Fixture.Streams.ReadAllAsync(Direction.Forwards, Position.Start)) - // Fixture.Log.Debug("Read event {EventId} from {StreamId}.", evt.OriginalEvent.EventId, evt.OriginalEvent.EventStreamId); - - // add some of the events we want to see before we start the subscription - foreach (var evt in seedEvents.Take(pageSize)) - await Fixture.Streams.AppendToStreamAsync( - $"{streamPrefix}-{evt.EventId.ToGuid():N}", - StreamState.NoStream, - new[] { evt } - ); - - var filterOptions = new SubscriptionFilterOptions(filter.Create(streamPrefix), 1); - - await using var subscription = Fixture.Streams.SubscribeToAll(FromAll.End, filterOptions: filterOptions); - await using var enumerator = subscription.Messages.GetAsyncEnumerator(); - - Assert.True(await enumerator.MoveNextAsync()); - - Assert.IsType(enumerator.Current); - - // add some of the events we want to see after we start the subscription - foreach (var evt in seedEvents.Skip(pageSize)) - await Fixture.Streams.AppendToStreamAsync( - $"{streamPrefix}-{evt.EventId.ToGuid():N}", - StreamState.NoStream, - new[] { evt } - ); - - bool checkpointReached = false; - - await Subscribe().WithTimeout(); - - Assert.True(checkpointReached); - - return; - - async Task Subscribe() { - while (await enumerator.MoveNextAsync()) { - switch (enumerator.Current) { - case StreamMessage.AllStreamCheckpointReached: - checkpointReached = true; - - break; - - case StreamMessage.Event(var resolvedEvent): { - availableEvents.Remove(resolvedEvent.Event.EventId); - - if (availableEvents.Count == 0) { - return; - } - - break; - } - } - } - } - } - - [Theory] - [MemberData(nameof(SubscriptionFilter.TestCases), MemberType = typeof(SubscriptionFilter))] - public async Task receives_all_filtered_events_from_position(SubscriptionFilter filter) { - var streamPrefix = $"{nameof(receives_all_filtered_events_from_position)}-{filter.Name}-{Guid.NewGuid():N}"; - - Fixture.Log.Information("Using filter {FilterName} with prefix {StreamPrefix}", filter.Name, streamPrefix); - - var seedEvents = Fixture.CreateTestEvents(64) - .Select(evt => filter.PrepareEvent(streamPrefix, evt)) - .ToArray(); - - var pageSize = seedEvents.Length / 2; - - // only the second half of the events will be received - var availableEvents = new HashSet(seedEvents.Skip(pageSize).Select(x => x.EventId)); - - // add noise - await Fixture.Streams.AppendToStreamAsync( - Fixture.GetStreamName(), - StreamState.NoStream, - Fixture.CreateTestEvents(3) - ); - - var existingEventsCount = await Fixture.Streams.ReadAllAsync(Direction.Forwards, Position.Start) - .Messages.CountAsync(); - - Fixture.Log.Debug("Existing events count: {ExistingEventsCount}", existingEventsCount); - - // add some of the events that are a match to the filter but will not be received - IWriteResult writeResult = new SuccessResult(); - foreach (var evt in seedEvents.Take(pageSize)) - writeResult = await Fixture.Streams.AppendToStreamAsync( - $"{streamPrefix}-{evt.EventId.ToGuid():N}", - StreamState.NoStream, - new[] { evt } - ); - - var position = FromAll.After(writeResult.LogPosition); - - var filterOptions = new SubscriptionFilterOptions(filter.Create(streamPrefix), 1); - - await using var subscription = Fixture.Streams.SubscribeToAll(position, filterOptions: filterOptions); - await using var enumerator = subscription.Messages.GetAsyncEnumerator(); - - Assert.True(await enumerator.MoveNextAsync()); - - Assert.IsType(enumerator.Current); - - // add the events we want to receive after we start the subscription - foreach (var evt in seedEvents.Skip(pageSize)) - await Fixture.Streams.AppendToStreamAsync( - $"{streamPrefix}-{evt.EventId.ToGuid():N}", - StreamState.NoStream, - new[] { evt } - ); - - bool checkpointReached = false; - - await Subscribe().WithTimeout(); - - Assert.True(checkpointReached); - - return; - - async Task Subscribe() { - while (await enumerator.MoveNextAsync()) { - switch (enumerator.Current) { - case StreamMessage.AllStreamCheckpointReached: - checkpointReached = true; - - break; - - case StreamMessage.Event(var resolvedEvent): { - availableEvents.Remove(resolvedEvent.Event.EventId); - - if (availableEvents.Count == 0) { - return; - } - - break; - } - } - } - } - } - - [Fact] - public async Task receives_all_filtered_events_with_resolved_links() { - var streamName = Fixture.GetStreamName(); - - var seedEvents = Fixture.CreateTestEvents(3).ToArray(); - var availableEvents = new HashSet(seedEvents.Select(x => x.EventId)); - - await Fixture.Streams.AppendToStreamAsync(streamName, StreamState.NoStream, seedEvents); - - var filterOptions = new SubscriptionFilterOptions( - StreamFilter.Prefix($"$et-{EventStoreFixture.TestEventType}") - ); - - await using var subscription = - Fixture.Streams.SubscribeToAll(FromAll.Start, true, filterOptions: filterOptions); - - await using var enumerator = subscription.Messages.GetAsyncEnumerator(); - - Assert.True(await enumerator.MoveNextAsync()); - - Assert.IsType(enumerator.Current); - - await Subscribe().WithTimeout(); - - return; - - async Task Subscribe() { - while (await enumerator.MoveNextAsync()) { - if (enumerator.Current is not StreamMessage.Event(var resolvedEvent) || - !resolvedEvent.OriginalEvent.EventStreamId.StartsWith($"$et-{EventStoreFixture.TestEventType}")) { - continue; - } - - availableEvents.Remove(resolvedEvent.Event.EventId); - - if (availableEvents.Count == 0) { - return; - } - } - } - } -} diff --git a/test/EventStore.Client.ProjectionManagement.Tests/AssertEx.cs b/test/EventStore.Client.Tests.Common/AssertEx.cs similarity index 97% rename from test/EventStore.Client.ProjectionManagement.Tests/AssertEx.cs rename to test/EventStore.Client.Tests.Common/AssertEx.cs index f7d846294..db2386374 100644 --- a/test/EventStore.Client.ProjectionManagement.Tests/AssertEx.cs +++ b/test/EventStore.Client.Tests.Common/AssertEx.cs @@ -1,7 +1,7 @@ using System.Runtime.CompilerServices; using Xunit.Sdk; -namespace EventStore.Client.ProjectionManagement.Tests; +namespace EventStore.Client.Tests; public static class AssertEx { /// @@ -53,4 +53,4 @@ static async Task IsOrBecomesTrueImpl(Func> func, TimeSpan? tim return false; } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests.Common/EventStore.Client.Tests.Common.csproj b/test/EventStore.Client.Tests.Common/EventStore.Client.Tests.Common.csproj index 9826714b3..6ebee89cb 100644 --- a/test/EventStore.Client.Tests.Common/EventStore.Client.Tests.Common.csproj +++ b/test/EventStore.Client.Tests.Common/EventStore.Client.Tests.Common.csproj @@ -1,66 +1,68 @@ - - EventStore.Client.Tests - + + EventStore.Client.Tests + - - - + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + - - - certs\%(RecursiveDir)/%(FileName)%(Extension) - Always - - + + + certs\%(RecursiveDir)/%(FileName)%(Extension) + Always + + - - - Always - - - Always - - - Always - - - PreserveNewest - - - Always - - - Always - - + + + Always + + + Always + + + Always + + + PreserveNewest + + + Always + + + Always + + - - - + + + diff --git a/test/EventStore.Client.Tests.Common/Extensions/ConfigurationExtensions.cs b/test/EventStore.Client.Tests.Common/Extensions/ConfigurationExtensions.cs index 3e975fc23..621758f36 100644 --- a/test/EventStore.Client.Tests.Common/Extensions/ConfigurationExtensions.cs +++ b/test/EventStore.Client.Tests.Common/Extensions/ConfigurationExtensions.cs @@ -9,4 +9,4 @@ public static void EnsureValue(this IConfiguration configuration, string key, st if (string.IsNullOrEmpty(value)) configuration[key] = defaultValue; } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests.Common/Extensions/EventStoreClientExtensions.cs b/test/EventStore.Client.Tests.Common/Extensions/EventStoreClientExtensions.cs index e1475bc16..cd7b808bd 100644 --- a/test/EventStore.Client.Tests.Common/Extensions/EventStoreClientExtensions.cs +++ b/test/EventStore.Client.Tests.Common/Extensions/EventStoreClientExtensions.cs @@ -21,4 +21,4 @@ public static Task CreateUserWithRetry( ), cancellationToken ); -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests.Common/Extensions/EventStoreClientWarmupExtensions.cs b/test/EventStore.Client.Tests.Common/Extensions/EventStoreClientWarmupExtensions.cs index dea2f4ef9..aff15195c 100644 --- a/test/EventStore.Client.Tests.Common/Extensions/EventStoreClientWarmupExtensions.cs +++ b/test/EventStore.Client.Tests.Common/Extensions/EventStoreClientWarmupExtensions.cs @@ -129,4 +129,4 @@ public static Task WarmUp(this EventStoreUserMan }, cancellationToken ); -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests.Common/Extensions/OperatingSystemExtensions.cs b/test/EventStore.Client.Tests.Common/Extensions/OperatingSystemExtensions.cs index 1889b084d..5899f625c 100644 --- a/test/EventStore.Client.Tests.Common/Extensions/OperatingSystemExtensions.cs +++ b/test/EventStore.Client.Tests.Common/Extensions/OperatingSystemExtensions.cs @@ -4,4 +4,4 @@ public static class OperatingSystemExtensions { public static bool IsWindows(this OperatingSystem operatingSystem) => operatingSystem.Platform != PlatformID.Unix && operatingSystem.Platform != PlatformID.MacOSX; -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests.Common/Extensions/ReadOnlyMemoryExtensions.cs b/test/EventStore.Client.Tests.Common/Extensions/ReadOnlyMemoryExtensions.cs index 49ffd1cd9..63b6694a3 100644 --- a/test/EventStore.Client.Tests.Common/Extensions/ReadOnlyMemoryExtensions.cs +++ b/test/EventStore.Client.Tests.Common/Extensions/ReadOnlyMemoryExtensions.cs @@ -25,4 +25,4 @@ public static StreamPosition ParseStreamPosition(this ReadOnlyMemory json) return StreamPosition.FromInt64(int.Parse(checkPoint)); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Streams.Tests/Append/ShouldThrowAsyncExtensions.cs b/test/EventStore.Client.Tests.Common/Extensions/ShouldThrowAsyncExtensions.cs similarity index 90% rename from test/EventStore.Client.Streams.Tests/Append/ShouldThrowAsyncExtensions.cs rename to test/EventStore.Client.Tests.Common/Extensions/ShouldThrowAsyncExtensions.cs index 80f983ce0..edba53a25 100644 --- a/test/EventStore.Client.Streams.Tests/Append/ShouldThrowAsyncExtensions.cs +++ b/test/EventStore.Client.Tests.Common/Extensions/ShouldThrowAsyncExtensions.cs @@ -1,4 +1,4 @@ -namespace EventStore.Client.Streams.Tests.Append; +namespace EventStore.Client.Tests; public static class ShouldThrowAsyncExtensions { public static Task ShouldThrowAsync(this EventStoreClient.ReadStreamResult source) where TException : Exception => @@ -11,4 +11,4 @@ public static async Task ShouldThrowAsync(this EventStoreClient.Read var ex = await source.ShouldThrowAsync(); handler(ex); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests/TypeExtensions.cs b/test/EventStore.Client.Tests.Common/Extensions/TypeExtensions.cs similarity index 98% rename from test/EventStore.Client.Tests/TypeExtensions.cs rename to test/EventStore.Client.Tests.Common/Extensions/TypeExtensions.cs index 268109da8..465b04f92 100644 --- a/test/EventStore.Client.Tests/TypeExtensions.cs +++ b/test/EventStore.Client.Tests.Common/Extensions/TypeExtensions.cs @@ -2,7 +2,7 @@ namespace EventStore.Client.Tests; -static class TypeExtensions { +public static class TypeExtensions { public static bool InvokeEqualityOperator(this Type type, object? left, object? right) => type.InvokeOperator("Equality", left, right); public static bool InvokeInequalityOperator(this Type type, object? left, object? right) => type.InvokeOperator("Inequality", left, right); @@ -36,4 +36,4 @@ static bool InvokeOperator(this Type type, string name, object? left, object? ri return (bool)op.Invoke(null, new[] { left, right })!; } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests.Common/Extensions/WithExtension.cs b/test/EventStore.Client.Tests.Common/Extensions/WithExtension.cs index b2ea3dbac..35f731de3 100644 --- a/test/EventStore.Client.Tests.Common/Extensions/WithExtension.cs +++ b/test/EventStore.Client.Tests.Common/Extensions/WithExtension.cs @@ -59,4 +59,4 @@ public static T With(this T instance, Func action, Func when) { return when() ? action(instance) : instance; } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests.Common/Facts/AnonymousAccess.cs b/test/EventStore.Client.Tests.Common/Facts/AnonymousAccess.cs index 575093085..0e8a3c248 100644 --- a/test/EventStore.Client.Tests.Common/Facts/AnonymousAccess.cs +++ b/test/EventStore.Client.Tests.Common/Facts/AnonymousAccess.cs @@ -8,4 +8,4 @@ public class AnonymousAccess { public class FactAttribute() : Deprecation.FactAttribute(LegacySince, SkipMessage); public class TheoryAttribute() : Deprecation.TheoryAttribute(LegacySince, SkipMessage); -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests.Common/Facts/Deprecation.cs b/test/EventStore.Client.Tests.Common/Facts/Deprecation.cs index 01adee242..98e9fe671 100644 --- a/test/EventStore.Client.Tests.Common/Facts/Deprecation.cs +++ b/test/EventStore.Client.Tests.Common/Facts/Deprecation.cs @@ -4,7 +4,7 @@ public class Deprecation { public class FactAttribute(Version since, string skipMessage) : Xunit.FactAttribute { public override string? Skip { - get => EventStoreTestServer.Version >= since ? skipMessage : null; + get => KurrentPermanentTestNode.Version >= since ? skipMessage : null; set => throw new NotSupportedException(); } } @@ -19,8 +19,8 @@ public TheoryAttribute(Version since, string skipMessage) { } public override string? Skip { - get => EventStoreTestServer.Version >= _legacySince ? _skipMessage : null; + get => KurrentPermanentTestNode.Version >= _legacySince ? _skipMessage : null; set => throw new NotSupportedException(); } } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests.Common/Facts/Regression.cs b/test/EventStore.Client.Tests.Common/Facts/Regression.cs index 3c6a92f0c..5abdfbff6 100644 --- a/test/EventStore.Client.Tests.Common/Facts/Regression.cs +++ b/test/EventStore.Client.Tests.Common/Facts/Regression.cs @@ -4,15 +4,15 @@ namespace EventStore.Client.Tests; public class Regression { public class FactAttribute(int major, string skipMessage) : Xunit.FactAttribute { public override string? Skip { - get => (EventStoreTestServer.Version?.Major ?? int.MaxValue) < major ? skipMessage : null; + get => (KurrentPermanentTestNode.Version?.Major ?? int.MaxValue) < major ? skipMessage : null; set => throw new NotSupportedException(); } } public class TheoryAttribute(int major, string skipMessage) : Xunit.TheoryAttribute { public override string? Skip { - get => (EventStoreTestServer.Version?.Major ?? int.MaxValue) < major ? skipMessage : null; + get => (KurrentPermanentTestNode.Version?.Major ?? int.MaxValue) < major ? skipMessage : null; set => throw new NotSupportedException(); } } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests.Common/Facts/SupportsPSToAllFact.cs b/test/EventStore.Client.Tests.Common/Facts/SupportsPSToAllFact.cs deleted file mode 100644 index 3f5d993fe..000000000 --- a/test/EventStore.Client.Tests.Common/Facts/SupportsPSToAllFact.cs +++ /dev/null @@ -1,18 +0,0 @@ -// ReSharper disable InconsistentNaming - -namespace EventStore.Client.Tests; - -[PublicAPI] -public class SupportsPSToAll { - const int SupportedFromMajorVersion = 21; - - static readonly string SkipMessage = $"Persistent Subscriptions to $all are not supported on" - + $" {EventStoreTestServer.Version?.ToString(3) ?? "unknown"}"; - - public static bool No => !Yes; - public static bool Yes => (EventStoreTestServer.Version?.Major ?? int.MaxValue) >= SupportedFromMajorVersion; - - public class FactAttribute() : Regression.FactAttribute(SupportedFromMajorVersion, SkipMessage); - - public class TheoryAttribute() : Regression.TheoryAttribute(SupportedFromMajorVersion, SkipMessage); -} \ No newline at end of file diff --git a/test/EventStore.Client.Tests.Common/Fakers/TestUserFaker.cs b/test/EventStore.Client.Tests.Common/Fakers/TestUserFaker.cs index 1aca4aac1..9cb3c3fbb 100644 --- a/test/EventStore.Client.Tests.Common/Fakers/TestUserFaker.cs +++ b/test/EventStore.Client.Tests.Common/Fakers/TestUserFaker.cs @@ -50,4 +50,4 @@ public TestUser WithNonAsciiPassword() => public static partial class Fakers { public static TestUserFaker Users => TestUserFaker.Instance; -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests.Common/Fixtures/Base/EventStoreClientFixtureBase.cs b/test/EventStore.Client.Tests.Common/Fixtures/Base/EventStoreClientFixtureBase.cs deleted file mode 100644 index 141a2a8da..000000000 --- a/test/EventStore.Client.Tests.Common/Fixtures/Base/EventStoreClientFixtureBase.cs +++ /dev/null @@ -1,147 +0,0 @@ -using System.Diagnostics; -using System.Net; -using System.Reactive.Linq; -using System.Reactive.Subjects; -using System.Runtime.CompilerServices; -using System.Text; -using Serilog; -using Serilog.Events; -using Serilog.Extensions.Logging; -using Serilog.Formatting.Display; - -namespace EventStore.Client; - -public abstract class EventStoreClientFixtureBase : IAsyncLifetime { - public const string TestEventType = "-"; - - const string ConnectionStringSingle = "esdb://admin:changeit@localhost:2113/?tls=true&tlsVerifyCert=false"; - const string ConnectionStringCluster = "esdb://admin:changeit@localhost:2113,localhost:2112,localhost:2111?tls=true&tlsVerifyCert=false"; - - static readonly Subject LogEventSubject = new(); - - readonly IList _disposables; - - static EventStoreClientFixtureBase() => ConfigureLogging(); - - protected EventStoreClientFixtureBase( - EventStoreClientSettings? clientSettings, - IDictionary? env = null, bool noDefaultCredentials = false - ) { - _disposables = new List(); - - ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; - - var connectionString = GlobalEnvironment.UseCluster ? ConnectionStringCluster : ConnectionStringSingle; - Settings = clientSettings ?? EventStoreClientSettings.Create(connectionString); - - if (noDefaultCredentials) - Settings.DefaultCredentials = null; - - Settings.DefaultDeadline = Debugger.IsAttached - ? new TimeSpan?() - : TimeSpan.FromSeconds(30); - - var hostCertificatePath = Path.Combine( - Environment.CurrentDirectory, - GlobalEnvironment.UseCluster ? "certs-cluster" : "certs" - ); - - Settings.LoggerFactory ??= new SerilogLoggerFactory(); - - Settings.ConnectivitySettings.MaxDiscoverAttempts = 20; - Settings.ConnectivitySettings.DiscoveryInterval = TimeSpan.FromSeconds(1); - - if (GlobalEnvironment.UseExternalServer) - TestServer = new EventStoreTestServerExternal(); - else - TestServer = GlobalEnvironment.UseCluster - ? new EventStoreTestServerCluster(hostCertificatePath, Settings.ConnectivitySettings.ResolvedAddressOrDefault, env) - : new EventStoreTestServer(hostCertificatePath, Settings.ConnectivitySettings.ResolvedAddressOrDefault, env); - } - - public IEventStoreTestServer TestServer { get; } - protected EventStoreClientSettings Settings { get; } - - public Faker Faker { get; } = new(); - - public virtual async Task InitializeAsync() { - await TestServer.StartAsync().WithTimeout(TimeSpan.FromMinutes(5)); - await OnServerUpAsync().WithTimeout(TimeSpan.FromMinutes(5)); - await Given().WithTimeout(TimeSpan.FromMinutes(5)); - await When().WithTimeout(TimeSpan.FromMinutes(5)); - } - - public virtual Task DisposeAsync() { - foreach (var disposable in _disposables) - disposable.Dispose(); - - return TestServer.DisposeAsync().AsTask().WithTimeout(TimeSpan.FromMinutes(5)); - } - - static void ConfigureLogging() { - var loggerConfiguration = new LoggerConfiguration() - .Enrich.FromLogContext() - .MinimumLevel.Is(LogEventLevel.Verbose) - .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) - .MinimumLevel.Override("Grpc", LogEventLevel.Verbose) - .WriteTo.Observers(observable => observable.Subscribe(LogEventSubject.OnNext)) - .WriteTo.Seq("http://localhost:5341/", period: TimeSpan.FromMilliseconds(1)); - - Log.Logger = loggerConfiguration.CreateLogger(); - AppDomain.CurrentDomain.DomainUnload += (_, e) => Log.CloseAndFlush(); - } - - protected abstract Task OnServerUpAsync(); - protected abstract Task Given(); - protected abstract Task When(); - - public IEnumerable CreateTestEvents(int count = 1, string? type = null, int metadataSize = 1) => - Enumerable.Range(0, count).Select(index => CreateTestEvent(index, type ?? TestEventType, metadataSize)); - - protected static EventData CreateTestEvent(int index) => CreateTestEvent(index, TestEventType, 1); - - protected static EventData CreateTestEvent(int index, string type, int metadataSize) => - new( - Uuid.NewUuid(), - type, - Encoding.UTF8.GetBytes($@"{{""x"":{index}}}"), - Encoding.UTF8.GetBytes("\"" + new string('$', metadataSize) + "\"") - ); - - public string GetStreamName([CallerMemberName] string? testMethod = null) { - var type = GetType(); - - return $"{type.DeclaringType?.Name}.{testMethod ?? "unknown"}"; - } - - public void CaptureLogs(ITestOutputHelper testOutputHelper) { - const string captureCorrelationId = nameof(captureCorrelationId); - - var captureId = Guid.NewGuid(); - - var callContextData = new AsyncLocal<(string, Guid)> { - Value = (captureCorrelationId, captureId) - }; - - bool Filter(LogEvent logEvent) => callContextData.Value.Item2.Equals(captureId); - - var formatter = new MessageTemplateTextFormatter("{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level:u3}] [{SourceContext}] {Message}"); - - var formatterWithException = - new MessageTemplateTextFormatter("{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level:u3}] [{SourceContext}] {Message}{NewLine}{Exception}"); - - var subscription = LogEventSubject.Where(Filter).Subscribe( - logEvent => { - using var writer = new StringWriter(); - if (logEvent.Exception != null) - formatterWithException.Format(logEvent, writer); - else - formatter.Format(logEvent, writer); - - testOutputHelper.WriteLine(writer.ToString()); - } - ); - - _disposables.Add(subscription); - } -} diff --git a/test/EventStore.Client.Tests.Common/Fixtures/Base/EventStoreTestServer.cs b/test/EventStore.Client.Tests.Common/Fixtures/Base/EventStoreTestServer.cs deleted file mode 100644 index 20c8c0c93..000000000 --- a/test/EventStore.Client.Tests.Common/Fixtures/Base/EventStoreTestServer.cs +++ /dev/null @@ -1,143 +0,0 @@ -using System.Net; -using System.Net.Http; -using Ductus.FluentDocker.Builders; -using Ductus.FluentDocker.Extensions; -using Ductus.FluentDocker.Model.Builders; -using Ductus.FluentDocker.Services; -using Ductus.FluentDocker.Services.Extensions; -using Polly; - -namespace EventStore.Client.Tests; - -public class EventStoreTestServer : IEventStoreTestServer { - static readonly string ContainerName = "es-client-dotnet-test"; - - static Version? _version; - readonly IContainerService _eventStore; - readonly string _hostCertificatePath; - readonly HttpClient _httpClient; - - public EventStoreTestServer( - string hostCertificatePath, - Uri address, - IDictionary? envOverrides - ) { - _hostCertificatePath = hostCertificatePath; - VerifyCertificatesExist(); - -#if NET - _httpClient = new HttpClient(new SocketsHttpHandler { - SslOptions = {RemoteCertificateValidationCallback = delegate { return true; }} - }) { - BaseAddress = address, - }; -#else - _httpClient = new HttpClient(new WinHttpHandler { - ServerCertificateValidationCallback = delegate { return true; } - }) { - BaseAddress = address, - }; -#endif - - var env = new Dictionary { - ["EVENTSTORE_DB_LOG_FORMAT"] = "V2", - ["EVENTSTORE_MEM_DB"] = "true", - ["EVENTSTORE_CHUNK_SIZE"] = (1024 * 1024 * 1024).ToString(), - ["EVENTSTORE_CERTIFICATE_FILE"] = "/etc/eventstore/certs/node/node.crt", - ["EVENTSTORE_CERTIFICATE_PRIVATE_KEY_FILE"] = "/etc/eventstore/certs/node/node.key", - ["EVENTSTORE_TRUSTED_ROOT_CERTIFICATES_PATH"] = "/etc/eventstore/certs/ca", - ["EVENTSTORE_LOG_LEVEL"] = "Verbose", - ["EVENTSTORE_STREAM_EXISTENCE_FILTER_SIZE"] = "10000", - ["EVENTSTORE_STREAM_INFO_CACHE_CAPACITY"] = "10000", - ["EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP"] = "false", - ["EVENTSTORE_DISABLE_LOG_FILE"] = "true" - }; - - foreach (var val in envOverrides ?? Enumerable.Empty>()) - env[val.Key] = val.Value; - - _eventStore = new Builder() - .UseContainer() - .UseImage(GlobalEnvironment.DockerImage) - .WithEnvironment(env.Select(pair => $"{pair.Key}={pair.Value}").ToArray()) - .WithName(ContainerName) - .MountVolume(_hostCertificatePath, "/etc/eventstore/certs", MountType.ReadOnly) - .ExposePort(2113, 2113) - //.WaitForHealthy(TimeSpan.FromSeconds(120)) - //.KeepContainer() - //.KeepRunning() - .Build(); - } - - public static Version Version => _version ??= GetVersion(); - - public async Task StartAsync(CancellationToken cancellationToken = default) { - _eventStore.Start(); - try { - await Policy.Handle() - .WaitAndRetryAsync(200, retryCount => TimeSpan.FromMilliseconds(100)) - .ExecuteAsync( - async () => { - using var response = await _httpClient.GetAsync("/health/live", cancellationToken); - if (response.StatusCode >= HttpStatusCode.BadRequest) - throw new($"Health check failed with status code: {response.StatusCode}."); - } - ); - } - catch (Exception) { - _eventStore.Dispose(); - throw; - } - } - - public void Stop() => _eventStore.Stop(); - - public ValueTask DisposeAsync() { - _httpClient?.Dispose(); - _eventStore?.Dispose(); - - return new ValueTask(Task.CompletedTask); - } - - static Version GetVersion() { - const string versionPrefix = "EventStoreDB version"; - - using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30)); - using var eventstore = new Builder().UseContainer() - .UseImage(GlobalEnvironment.DockerImage) - .Command("--version") - .Build() - .Start(); - - using var log = eventstore.Logs(true, cts.Token); - foreach (var line in log.ReadToEnd()) { - if (line.StartsWith(versionPrefix) && - Version.TryParse(new string(ReadVersion(line[(versionPrefix.Length + 1)..]).ToArray()), out var version)) { - return version; - } - } - - throw new InvalidOperationException("Could not determine server version."); - - IEnumerable ReadVersion(string s) { - foreach (var c in s.TakeWhile(c => c == '.' || char.IsDigit(c))) { - yield return c; - } - } - } - - void VerifyCertificatesExist() { - var certificateFiles = new[] { - Path.Combine("ca", "ca.crt"), - Path.Combine("ca", "ca.key"), - Path.Combine("node", "node.crt"), - Path.Combine("node", "node.key") - }.Select(path => Path.Combine(_hostCertificatePath, path)); - - foreach (var file in certificateFiles) - if (!File.Exists(file)) - throw new InvalidOperationException( - $"Could not locate the certificates file {file} needed to run EventStoreDB. Please run the 'gencert' tool at the root of the repository." - ); - } -} diff --git a/test/EventStore.Client.Tests.Common/Fixtures/Base/EventStoreTestServerCluster.cs b/test/EventStore.Client.Tests.Common/Fixtures/Base/EventStoreTestServerCluster.cs deleted file mode 100644 index ceb263e15..000000000 --- a/test/EventStore.Client.Tests.Common/Fixtures/Base/EventStoreTestServerCluster.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System.Net; -using System.Net.Http; -using Ductus.FluentDocker.Builders; -using Ductus.FluentDocker.Common; -using Ductus.FluentDocker.Services; -using Polly; - -namespace EventStore.Client; - -// [Obsolete("Use EventStoreTestCluster instead.", false)] -public class EventStoreTestServerCluster : IEventStoreTestServer { - readonly ICompositeService _eventStoreCluster; - readonly HttpClient _httpClient; - - public EventStoreTestServerCluster( - string hostCertificatePath, - Uri address, - IDictionary? envOverrides - ) { - envOverrides ??= new Dictionary(); - envOverrides["ES_CERTS_CLUSTER"] = hostCertificatePath; - - _eventStoreCluster = BuildCluster(envOverrides); - -#if NET - _httpClient = new HttpClient(new SocketsHttpHandler { - SslOptions = {RemoteCertificateValidationCallback = delegate { return true; }} - }) { - BaseAddress = address, - }; -#else - _httpClient = new HttpClient(new WinHttpHandler { - ServerCertificateValidationCallback = delegate { return true; } - }) { - BaseAddress = address, - }; -#endif - } - - public async Task StartAsync(CancellationToken cancellationToken = default) { - try { - // don't know why, sometimes the default network (e.g. net50_default) remains - // from previous cluster and prevents docker-compose up from executing successfully - Policy.Handle() - .WaitAndRetry( - 10, - retryCount => TimeSpan.FromSeconds(2), - (ex, _) => { - BuildCluster().Dispose(); - _eventStoreCluster.Start(); - } - ) - .Execute(() => { _eventStoreCluster.Start(); }); - - await Policy.Handle() - .WaitAndRetryAsync(200, retryCount => TimeSpan.FromMilliseconds(100)) - .ExecuteAsync( - async () => { - using var response = await _httpClient.GetAsync("/health/live", cancellationToken); - if (response.StatusCode >= HttpStatusCode.BadRequest) - throw new($"Health check failed with status code: {response.StatusCode}."); - } - ); - } - catch (Exception) { - _eventStoreCluster.Dispose(); - throw; - } - } - - public void Stop() => _eventStoreCluster.Stop(); - - public ValueTask DisposeAsync() { - _eventStoreCluster.Dispose(); - return new(Task.CompletedTask); - } - - ICompositeService BuildCluster(IDictionary? envOverrides = null) { - var env = GlobalEnvironment - .GetEnvironmentVariables(envOverrides) - .Select(pair => $"{pair.Key}={pair.Value}") - .ToArray(); - - return new Builder() - .UseContainer() - .UseCompose() - .WithEnvironment(env) - .FromFile("docker-compose.yml") - .ForceRecreate() - .RemoveOrphans() - .Build(); - } -} diff --git a/test/EventStore.Client.Tests.Common/Fixtures/Base/EventStoreTestServerExternal.cs b/test/EventStore.Client.Tests.Common/Fixtures/Base/EventStoreTestServerExternal.cs deleted file mode 100644 index 19b866a63..000000000 --- a/test/EventStore.Client.Tests.Common/Fixtures/Base/EventStoreTestServerExternal.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace EventStore.Client; - -public class EventStoreTestServerExternal : IEventStoreTestServer { - public Task StartAsync(CancellationToken cancellationToken = default) => Task.CompletedTask; - public void Stop() { } - - public ValueTask DisposeAsync() => new ValueTask(Task.CompletedTask); -} diff --git a/test/EventStore.Client.Tests.Common/Fixtures/Base/IEventStoreTestServer.cs b/test/EventStore.Client.Tests.Common/Fixtures/Base/IEventStoreTestServer.cs deleted file mode 100644 index 2d467835d..000000000 --- a/test/EventStore.Client.Tests.Common/Fixtures/Base/IEventStoreTestServer.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace EventStore.Client; - -public interface IEventStoreTestServer : IAsyncDisposable { - Task StartAsync(CancellationToken cancellationToken = default); - void Stop(); -} \ No newline at end of file diff --git a/test/EventStore.Client.Tests.Common/Fixtures/BaseTestNode.cs b/test/EventStore.Client.Tests.Common/Fixtures/BaseTestNode.cs new file mode 100644 index 000000000..789384e9d --- /dev/null +++ b/test/EventStore.Client.Tests.Common/Fixtures/BaseTestNode.cs @@ -0,0 +1,162 @@ +// // ReSharper disable InconsistentNaming +// +// using System.Globalization; +// using System.Net; +// using System.Net.Sockets; +// using Ductus.FluentDocker.Builders; +// using Ductus.FluentDocker.Extensions; +// using Ductus.FluentDocker.Services.Extensions; +// using EventStore.Client.Tests.FluentDocker; +// using Humanizer; +// using Serilog; +// using Serilog.Extensions.Logging; +// using static System.TimeSpan; +// +// namespace EventStore.Client.Tests; +// +// public abstract class BaseTestNode(EventStoreFixtureOptions? options = null) : TestContainerService { +// static readonly NetworkPortProvider NetworkPortProvider = new(NetworkPortProvider.DefaultEsdbPort); +// +// public EventStoreFixtureOptions Options { get; } = options ?? DefaultOptions(); +// +// static Version? _version; +// +// public static Version Version => _version ??= GetVersion(); +// +// public static EventStoreFixtureOptions DefaultOptions() { +// const string connString = "esdb://admin:changeit@localhost:{port}/?tlsVerifyCert=false"; +// +// var port = NetworkPortProvider.NextAvailablePort; +// +// var defaultSettings = EventStoreClientSettings +// .Create(connString.Replace("{port}", $"{port}")) +// .With(x => x.LoggerFactory = new SerilogLoggerFactory(Log.Logger)) +// .With(x => x.DefaultDeadline = Application.DebuggerIsAttached ? new TimeSpan?() : FromSeconds(30)) +// .With(x => x.ConnectivitySettings.MaxDiscoverAttempts = 20) +// .With(x => x.ConnectivitySettings.DiscoveryInterval = FromSeconds(1)); +// +// var defaultEnvironment = new Dictionary(GlobalEnvironment.Variables) { +// // ["EVENTSTORE_MEM_DB"] = "true", +// // ["EVENTSTORE_CERTIFICATE_FILE"] = "/etc/eventstore/certs/node/node.crt", +// // ["EVENTSTORE_CERTIFICATE_PRIVATE_KEY_FILE"] = "/etc/eventstore/certs/node/node.key", +// // ["EVENTSTORE_STREAM_EXISTENCE_FILTER_SIZE"] = "10000", +// // ["EVENTSTORE_STREAM_INFO_CACHE_CAPACITY"] = "10000", +// // ["EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP"] = "true", +// // ["EVENTSTORE_LOG_LEVEL"] = "Default", // required to use serilog settings +// // ["EVENTSTORE_DISABLE_LOG_FILE"] = "true", +// // ["EVENTSTORE_START_STANDARD_PROJECTIONS"] = "true", +// // ["EVENTSTORE_RUN_PROJECTIONS"] = "All", +// // ["EVENTSTORE_CHUNK_SIZE"] = (1024 * 1024 * 1024).ToString(), +// // ["EVENTSTORE_MAX_APPEND_SIZE"] = 100.Kilobytes().Bytes.ToString(CultureInfo.InvariantCulture), +// // ["EVENTSTORE_ADVERTISE_HTTP_PORT_TO_CLIENT_AS"] = $"{NetworkPortProvider.DefaultEsdbPort}" +// +// ["EVENTSTORE_MEM_DB"] = "true", +// ["EVENTSTORE_CERTIFICATE_FILE"] = "/etc/eventstore/certs/node/node.crt", +// ["EVENTSTORE_CERTIFICATE_PRIVATE_KEY_FILE"] = "/etc/eventstore/certs/node/node.key", +// ["EVENTSTORE_STREAM_EXISTENCE_FILTER_SIZE"] = "10000", +// ["EVENTSTORE_STREAM_INFO_CACHE_CAPACITY"] = "10000", +// ["EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP"] = "true", +// ["EVENTSTORE_LOG_LEVEL"] = "Default", // required to use serilog settings +// ["EVENTSTORE_DISABLE_LOG_FILE"] = "true", +// ["EVENTSTORE_CHUNK_SIZE"] = (1024 * 1024 * 1024).ToString(), +// ["EVENTSTORE_MAX_APPEND_SIZE"] = 100.Kilobytes().Bytes.ToString(CultureInfo.InvariantCulture), +// ["EVENTSTORE_ADVERTISE_HTTP_PORT_TO_CLIENT_AS"] = $"{NetworkPortProvider.DefaultEsdbPort}" +// }; +// +// if (port != NetworkPortProvider.DefaultEsdbPort) { +// if (GlobalEnvironment.Variables.TryGetValue("ES_DOCKER_TAG", out var tag) && tag == "ci") +// defaultEnvironment["EVENTSTORE_ADVERTISE_NODE_PORT_TO_CLIENT_AS"] = $"{port}"; +// else +// defaultEnvironment["EVENTSTORE_ADVERTISE_HTTP_PORT_TO_CLIENT_AS"] = $"{port}"; +// } +// +// return new(defaultSettings, defaultEnvironment); +// } +// +// static Version GetVersion() { +// const string versionPrefix = "EventStoreDB version"; +// +// using var cts = new CancellationTokenSource(FromSeconds(30)); +// using var eventstore = new Builder().UseContainer() +// .UseImage(GlobalEnvironment.DockerImage) +// .Command("--version") +// .Build() +// .Start(); +// +// using var log = eventstore.Logs(true, cts.Token); +// foreach (var line in log.ReadToEnd()) { +// if (line.StartsWith(versionPrefix) && +// Version.TryParse(new string(ReadVersion(line[(versionPrefix.Length + 1)..]).ToArray()), out var version)) { +// return version; +// } +// } +// +// throw new InvalidOperationException("Could not determine server version."); +// +// IEnumerable ReadVersion(string s) { +// foreach (var c in s.TakeWhile(c => c == '.' || char.IsDigit(c))) { +// yield return c; +// } +// } +// } +// +// string[] GetEnvironmentVariables() => +// Options.Environment.Select(pair => $"{pair.Key}={pair.Value}").ToArray(); +// +// protected abstract ContainerBuilder ConfigureContainer(ContainerBuilder builder); +// +// protected override ContainerBuilder Configure() { +// var certsPath = Path.Combine(Environment.CurrentDirectory, "certs"); +// +// CertificatesManager.VerifyCertificatesExist(certsPath); +// +// var builder = new Builder().UseContainer().WithEnvironment(GetEnvironmentVariables()); +// +// return ConfigureContainer(builder); +// } +// } +// +// /// +// /// Using the default 2113 port assumes that the test is running sequentially. +// /// +// /// +// class NetworkPortProvider(int port = 2114) { +// public const int DefaultEsdbPort = 2113; +// +// static readonly SemaphoreSlim Semaphore = new(1, 1); +// +// async Task GetNextAvailablePort(TimeSpan delay = default) { +// if (port == DefaultEsdbPort) +// return port; +// +// await Semaphore.WaitAsync(); +// +// try { +// using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); +// +// while (true) { +// var nexPort = Interlocked.Increment(ref port); +// +// try { +// await socket.ConnectAsync(IPAddress.Any, nexPort); +// } catch (SocketException ex) { +// if (ex.SocketErrorCode is SocketError.ConnectionRefused or not SocketError.IsConnected) { +// return nexPort; +// } +// +// await Task.Delay(delay); +// } finally { +// #if NET +// if (socket.Connected) await socket.DisconnectAsync(true); +// #else +// if (socket.Connected) socket.Disconnect(true); +// #endif +// } +// } +// } finally { +// Semaphore.Release(); +// } +// } +// +// public int NextAvailablePort => GetNextAvailablePort(FromMilliseconds(100)).GetAwaiter().GetResult(); +// } diff --git a/test/EventStore.Client.Tests.Common/Fixtures/DiagnosticsFixture.cs b/test/EventStore.Client.Tests.Common/Fixtures/DiagnosticsFixture.cs deleted file mode 100644 index 549093654..000000000 --- a/test/EventStore.Client.Tests.Common/Fixtures/DiagnosticsFixture.cs +++ /dev/null @@ -1,107 +0,0 @@ -using System.Collections.Concurrent; -using System.Diagnostics; -using EventStore.Client.Diagnostics; -using EventStore.Diagnostics; -using EventStore.Diagnostics.Telemetry; -using EventStore.Diagnostics.Tracing; - -namespace EventStore.Client.Tests; - -[PublicAPI] -public class DiagnosticsFixture : EventStoreFixture { - readonly ConcurrentDictionary<(string Operation, string Stream), List> _activities = []; - - public DiagnosticsFixture() : base(x => x.RunProjections()) { - var diagnosticActivityListener = new ActivityListener { - ShouldListenTo = source => source.Name == EventStoreClientDiagnostics.InstrumentationName, - Sample = (ref ActivityCreationOptions _) => ActivitySamplingResult.AllDataAndRecorded, - ActivityStopped = activity => { - var operation = (string?)activity.GetTagItem(TelemetryTags.Database.Operation); - var stream = (string?)activity.GetTagItem(TelemetryTags.EventStore.Stream); - - if (operation is null || stream is null) - return; - - _activities.AddOrUpdate( - (operation, stream), - _ => [activity], - (_, activities) => { - activities.Add(activity); - return activities; - } - ); - } - }; - - OnSetup = () => { - ActivitySource.AddActivityListener(diagnosticActivityListener); - return Task.CompletedTask; - }; - - OnTearDown = () => { - diagnosticActivityListener.Dispose(); - return Task.CompletedTask; - }; - } - - public List GetActivitiesForOperation(string operation, string stream) => - _activities.TryGetValue((operation, stream), out var activities) ? activities : []; - - public void AssertAppendActivityHasExpectedTags(Activity activity, string stream) { - var expectedTags = new Dictionary { - { TelemetryTags.Database.System, EventStoreClientDiagnostics.InstrumentationName }, - { TelemetryTags.Database.Operation, TracingConstants.Operations.Append }, - { TelemetryTags.EventStore.Stream, stream }, - { TelemetryTags.Database.User, TestCredentials.Root.Username }, - { TelemetryTags.Otel.StatusCode, ActivityStatusCodeHelper.OkStatusCodeTagValue } - }; - - foreach (var tag in expectedTags) - activity.Tags.ShouldContain(tag); - } - - public void AssertErroneousAppendActivityHasExpectedTags(Activity activity, Exception actualException) { - var expectedTags = new Dictionary { - { TelemetryTags.Otel.StatusCode, ActivityStatusCodeHelper.ErrorStatusCodeTagValue } - }; - - foreach (var tag in expectedTags) - activity.Tags.ShouldContain(tag); - - var actualEvent = activity.Events.ShouldHaveSingleItem(); - - actualEvent.Name.ShouldBe(TelemetryTags.Exception.EventName); - actualEvent.Tags.ShouldContain( - new KeyValuePair(TelemetryTags.Exception.Type, actualException.GetType().FullName) - ); - - actualEvent.Tags.ShouldContain( - new KeyValuePair(TelemetryTags.Exception.Message, actualException.Message) - ); - - actualEvent.Tags.Any(x => x.Key == TelemetryTags.Exception.Stacktrace).ShouldBeTrue(); - } - - public void AssertSubscriptionActivityHasExpectedTags( - Activity activity, - string stream, - string eventId, - string? subscriptionId = null - ) { - var expectedTags = new Dictionary { - { TelemetryTags.Database.System, EventStoreClientDiagnostics.InstrumentationName }, - { TelemetryTags.Database.Operation, TracingConstants.Operations.Subscribe }, - { TelemetryTags.EventStore.Stream, stream }, - { TelemetryTags.EventStore.EventId, eventId }, - { TelemetryTags.EventStore.EventType, TestEventType }, - { TelemetryTags.Database.User, TestCredentials.Root.Username } - }; - - if (subscriptionId != null) - expectedTags[TelemetryTags.EventStore.SubscriptionId] = subscriptionId; - - foreach (var tag in expectedTags) { - activity.Tags.ShouldContain(tag); - } - } -} diff --git a/test/EventStore.Client.Tests.Common/Fixtures/EventStoreTestCluster.cs b/test/EventStore.Client.Tests.Common/Fixtures/EventStoreTestCluster.cs deleted file mode 100644 index ad8246843..000000000 --- a/test/EventStore.Client.Tests.Common/Fixtures/EventStoreTestCluster.cs +++ /dev/null @@ -1,52 +0,0 @@ -using Ductus.FluentDocker.Builders; -using EventStore.Client.Tests.FluentDocker; -using Serilog; -using Serilog.Extensions.Logging; - -namespace EventStore.Client.Tests; - -public class EventStoreTestCluster(EventStoreFixtureOptions options) : TestCompositeService { - EventStoreFixtureOptions Options { get; } = options; - - public static EventStoreFixtureOptions DefaultOptions() { - const string connString = "esdb://localhost:2113,localhost:2112,localhost:2111?tls=true&tlsVerifyCert=false"; - - var defaultSettings = EventStoreClientSettings - .Create(connString) - .With(x => x.LoggerFactory = new SerilogLoggerFactory(Log.Logger)) - .With(x => x.DefaultDeadline = Application.DebuggerIsAttached ? new TimeSpan?() : TimeSpan.FromSeconds(30)) - .With(x => x.ConnectivitySettings.MaxDiscoverAttempts = 30) - .With(x => x.ConnectivitySettings.DiscoveryInterval = TimeSpan.FromSeconds(1)); - - var defaultEnvironment = new Dictionary(GlobalEnvironment.Variables) { - ["ES_CERTS_CLUSTER"] = Path.Combine(Environment.CurrentDirectory, "certs-cluster"), - ["EVENTSTORE_CLUSTER_SIZE"] = "3", - ["EVENTSTORE_INT_TCP_PORT"] = "1112", - ["EVENTSTORE_HTTP_PORT"] = "2113", - ["EVENTSTORE_DISCOVER_VIA_DNS"] = "false", - ["EVENTSTORE_STREAM_EXISTENCE_FILTER_SIZE"] = "10000", - ["EVENTSTORE_STREAM_INFO_CACHE_CAPACITY"] = "10000" - }; - - return new(defaultSettings, defaultEnvironment); - } - - protected override CompositeBuilder Configure() { - var env = Options.Environment.Select(pair => $"{pair.Key}={pair.Value}").ToArray(); - - var builder = new Builder() - .UseContainer() - .FromComposeFile("docker-compose.yml") - .ServiceName("esdb-test-cluster") - .WithEnvironment(env) - .RemoveOrphans() - .NoRecreate() - .KeepRunning(); - - return builder; - } - - protected override async Task OnServiceStarted() { - await Service.WaitUntilNodesAreHealthy("esdb-node", TimeSpan.FromSeconds(60)); - } -} diff --git a/test/EventStore.Client.Tests.Common/Fixtures/InsecureClientTestFixture.cs b/test/EventStore.Client.Tests.Common/Fixtures/InsecureClientTestFixture.cs deleted file mode 100644 index 33407d177..000000000 --- a/test/EventStore.Client.Tests.Common/Fixtures/InsecureClientTestFixture.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace EventStore.Client.Tests; - -/// -/// The clients dont have default credentials set. -/// -[PublicAPI] -public class InsecureClientTestFixture() : EventStoreFixture(x => x.WithoutDefaultCredentials()); \ No newline at end of file diff --git a/test/EventStore.Client.Tests.Common/Fixtures/KurrentFixtureOptions.cs b/test/EventStore.Client.Tests.Common/Fixtures/KurrentFixtureOptions.cs new file mode 100644 index 000000000..9e8496d27 --- /dev/null +++ b/test/EventStore.Client.Tests.Common/Fixtures/KurrentFixtureOptions.cs @@ -0,0 +1,20 @@ +namespace EventStore.Client.Tests; + +public record KurrentFixtureOptions( + EventStoreClientSettings ClientSettings, + IDictionary Environment +) { + public KurrentFixtureOptions WithoutDefaultCredentials() => this with { ClientSettings = ClientSettings.With(x => x.DefaultCredentials = null) }; + + public KurrentFixtureOptions RunProjections(bool runProjections = true) => + this with { + Environment = Environment.With( + x => { + x["EVENTSTORE_START_STANDARD_PROJECTIONS"] = runProjections.ToString(); + x["EVENTSTORE_RUN_PROJECTIONS"] = runProjections ? "All" : "None"; + } + ) + }; +} + +public delegate KurrentFixtureOptions ConfigureFixture(KurrentFixtureOptions options); diff --git a/test/EventStore.Client.Tests.Common/Fixtures/EventStoreFixture.Helpers.cs b/test/EventStore.Client.Tests.Common/Fixtures/KurrentPermanentFixture.Helpers.cs similarity index 78% rename from test/EventStore.Client.Tests.Common/Fixtures/EventStoreFixture.Helpers.cs rename to test/EventStore.Client.Tests.Common/Fixtures/KurrentPermanentFixture.Helpers.cs index 1e8bb3d83..41457d3b4 100644 --- a/test/EventStore.Client.Tests.Common/Fixtures/EventStoreFixture.Helpers.cs +++ b/test/EventStore.Client.Tests.Common/Fixtures/KurrentPermanentFixture.Helpers.cs @@ -3,7 +3,7 @@ namespace EventStore.Client.Tests; -public partial class EventStoreFixture { +public partial class KurrentPermanentFixture { public const string TestEventType = "test-event-type"; public const string AnotherTestEventTypePrefix = "another"; public const string AnotherTestEventType = $"{AnotherTestEventTypePrefix}-test-event-type"; @@ -12,7 +12,17 @@ public partial class EventStoreFixture { (T)Activator.CreateInstance(typeof(T), [ClientSettings.With(configure)])!; public string GetStreamName([CallerMemberName] string? testMethod = null) => - $"{testMethod}-{Guid.NewGuid():N}"; + $"stream-{testMethod}-{Guid.NewGuid():N}"; + + public string GetGroupName([CallerMemberName] string? testMethod = null) => + $"group-{testMethod}-{Guid.NewGuid():N}"; + + public UserCredentials GetUserCredentials([CallerMemberName] string? testMethod = null) => new UserCredentials( + $"user-{testMethod}-{Guid.NewGuid():N}", "pa$$word" + ); + + public string GetProjectionName([CallerMemberName] string? testMethod = null) => + $"projection-{testMethod}-{Guid.NewGuid():N}"; public ReadOnlyMemory CreateMetadataOfSize(int metadataSize) => Encoding.UTF8.GetBytes($"\"{new string('$', metadataSize)}\""); @@ -21,6 +31,16 @@ public ReadOnlyMemory CreateMetadataOfSize(int metadataSize) => public ReadOnlyMemory CreateTestNonJsonMetadata() => "non-json-metadata"u8.ToArray(); + public (IEnumerable Events, uint size) CreateTestEventsUpToMaxSize(uint maxSize) { + var size = 0; + + var events = CreateTestEvents(int.MaxValue) + .TakeWhile(evt => (size += evt.Data.Length) < maxSize) + .ToList(); + + return (events, (uint)size); + } + public IEnumerable CreateTestEvents( int count = 1, string? type = null, ReadOnlyMemory? metadata = null, string? contentType = null ) => diff --git a/test/EventStore.Client.Tests.Common/Fixtures/EventStoreFixture.cs b/test/EventStore.Client.Tests.Common/Fixtures/KurrentPermanentFixture.cs similarity index 64% rename from test/EventStore.Client.Tests.Common/Fixtures/EventStoreFixture.cs rename to test/EventStore.Client.Tests.Common/Fixtures/KurrentPermanentFixture.cs index 50faebf7a..e3c8e426f 100644 --- a/test/EventStore.Client.Tests.Common/Fixtures/EventStoreFixture.cs +++ b/test/EventStore.Client.Tests.Common/Fixtures/KurrentPermanentFixture.cs @@ -8,59 +8,27 @@ namespace EventStore.Client.Tests; -public record EventStoreFixtureOptions( - EventStoreClientSettings ClientSettings, - IDictionary Environment -) { - public EventStoreFixtureOptions RunInMemory(bool runInMemory = true) => - this with { Environment = Environment.With(x => x["EVENTSTORE_MEM_DB"] = runInMemory.ToString()) }; - - public EventStoreFixtureOptions RunProjections(bool runProjections = true) => - this with { - Environment = Environment.With( - x => { - x["EVENTSTORE_START_STANDARD_PROJECTIONS"] = runProjections.ToString(); - x["EVENTSTORE_RUN_PROJECTIONS"] = runProjections ? "All" : "None"; - } - ) - }; - - public EventStoreFixtureOptions WithoutDefaultCredentials() => - this with { ClientSettings = ClientSettings.With(x => x.DefaultCredentials = null) }; - - public EventStoreFixtureOptions WithMaxAppendSize(uint maxAppendSize) => - this with { Environment = Environment.With(x => x["EVENTSTORE_MAX_APPEND_SIZE"] = $"{maxAppendSize}") }; -} - -public delegate EventStoreFixtureOptions ConfigureFixture(EventStoreFixtureOptions options); - [PublicAPI] -public partial class EventStoreFixture : IAsyncLifetime, IAsyncDisposable { +public partial class KurrentPermanentFixture : IAsyncLifetime, IAsyncDisposable { static readonly ILogger Logger; - static EventStoreFixture() { + static KurrentPermanentFixture() { Logging.Initialize(); - Logger = Serilog.Log.ForContext(); + Logger = Serilog.Log.ForContext(); +#if NET9_0_OR_GREATER + var httpClientHandler = new HttpClientHandler(); + httpClientHandler.ServerCertificateCustomValidationCallback = delegate { return true; }; +#else ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; +#endif } - public EventStoreFixture() : this(options => options) { } - - protected EventStoreFixture(ConfigureFixture configure) { - // TODO SS: should I verify the certificates exist here? - if (GlobalEnvironment.UseExternalServer) { - Options = new(new(), new Dictionary()); - Service = new TestBypassService(); - } + public KurrentPermanentFixture() : this(options => options) { } - if (GlobalEnvironment.UseCluster) { - Options = configure(EventStoreTestCluster.DefaultOptions()); - Service = new EventStoreTestCluster(Options); - } else { - Options = configure(EventStoreTestNode.DefaultOptions()); - Service = new EventStoreTestNode(Options); - } + protected KurrentPermanentFixture(ConfigureFixture configure) { + Options = configure(KurrentPermanentTestNode.DefaultOptions()); + Service = new KurrentPermanentTestNode(Options); } List TestRuns { get; } = new(); @@ -68,7 +36,7 @@ protected EventStoreFixture(ConfigureFixture configure) { public ILogger Log => Logger; public ITestService Service { get; } - public EventStoreFixtureOptions Options { get; } + public KurrentFixtureOptions Options { get; } public Faker Faker { get; } = new Faker(); public Version EventStoreVersion { get; private set; } = null!; @@ -80,6 +48,8 @@ protected EventStoreFixture(ConfigureFixture configure) { public EventStorePersistentSubscriptionsClient Subscriptions { get; private set; } = null!; public EventStoreOperationsClient Operations { get; private set; } = null!; + public bool SkipPsWarmUp { get; set; } + public Func OnSetup { get; init; } = () => Task.CompletedTask; public Func OnTearDown { get; init; } = () => Task.CompletedTask; @@ -102,6 +72,8 @@ protected EventStoreFixture(ConfigureFixture configure) { InterlockedBoolean WarmUpCompleted { get; } = new InterlockedBoolean(); SemaphoreSlim WarmUpGatekeeper { get; } = new(1, 1); + static readonly SemaphoreSlim ContainerSemaphore = new(1, 1); + public void CaptureTestRun(ITestOutputHelper outputHelper) { var testRunId = Logging.CaptureLogs(outputHelper); TestRuns.Add(testRunId); @@ -110,7 +82,12 @@ public void CaptureTestRun(ITestOutputHelper outputHelper) { } public async Task InitializeAsync() { - await Service.Start(); + await ContainerSemaphore.WaitAsync(); + try { + await Service.Start(); + } finally { + ContainerSemaphore.Release(); + } EventStoreVersion = GetEventStoreVersion(); EventStoreHasLastStreamPosition = (EventStoreVersion?.Major ?? int.MaxValue) >= 21; @@ -128,7 +105,7 @@ await Task.WhenAll( async x => Projections = await x.WarmUp(), Options.Environment["EVENTSTORE_RUN_PROJECTIONS"] != "None" ), - InitClient(async x => Subscriptions = await x.WarmUp()), + InitClient(async x => Subscriptions = SkipPsWarmUp ? x : await x.WarmUp()), InitClient(async x => Operations = await x.WarmUp()) ); @@ -149,7 +126,7 @@ await Task.WhenAll( async Task InitClient(Func action, bool execute = true) where T : EventStoreClientBase { if (!execute) return default(T)!; - var client = (Activator.CreateInstance(typeof(T), new object?[] { ClientSettings }) as T)!; + var client = (Activator.CreateInstance(typeof(T), ClientSettings) as T)!; await action(client); return client; } @@ -202,21 +179,8 @@ public async Task DisposeAsync() { async ValueTask IAsyncDisposable.DisposeAsync() => await DisposeAsync(); } -[CollectionDefinition(nameof(EventStoreSharedDatabaseFixture))] -public class EventStoreSharedDatabaseFixture : ICollectionFixture { - // This class has no code, and is never created. Its purpose is simply - // to be the place to apply [CollectionDefinition] and all the - // ICollectionFixture<> interfaces. -} +public abstract class EventStorePermanentTests : IClassFixture where TFixture : KurrentPermanentFixture { + protected EventStorePermanentTests(ITestOutputHelper output, TFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); -public abstract class EventStoreTests : IClassFixture where TFixture : EventStoreFixture { - protected EventStoreTests(ITestOutputHelper output, TFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - protected TFixture Fixture { get; } } - -[Collection(nameof(EventStoreSharedDatabaseFixture))] -public abstract class EventStoreSharedDatabaseTests(ITestOutputHelper output, TFixture fixture) - : EventStoreTests(output, fixture) - where TFixture : EventStoreFixture; diff --git a/test/EventStore.Client.Tests.Common/Fixtures/EventStoreTestNode.cs b/test/EventStore.Client.Tests.Common/Fixtures/KurrentPermanentTestNode.cs similarity index 54% rename from test/EventStore.Client.Tests.Common/Fixtures/EventStoreTestNode.cs rename to test/EventStore.Client.Tests.Common/Fixtures/KurrentPermanentTestNode.cs index 6417ad3b9..d2c4549ab 100644 --- a/test/EventStore.Client.Tests.Common/Fixtures/EventStoreTestNode.cs +++ b/test/EventStore.Client.Tests.Common/Fixtures/KurrentPermanentTestNode.cs @@ -1,25 +1,61 @@ +// ReSharper disable InconsistentNaming + +// using Ductus.FluentDocker.Builders; +// using Ductus.FluentDocker.Model.Builders; +// using EventStore.Client.Tests.FluentDocker; +// +// namespace EventStore.Client.Tests; +// +// public class EventStorePermanentTestNode(EventStoreFixtureOptions? options = null) : BaseTestNode(options) { +// protected override ContainerBuilder ConfigureContainer(ContainerBuilder builder) { +// var port = Options.ClientSettings.ConnectivitySettings.ResolvedAddressOrDefault.Port; +// var certsPath = Path.Combine(Environment.CurrentDirectory, "certs"); +// +// var containerName = "es-client-dotnet-test"; +// +// return builder +// .UseImage(Options.Environment["ES_DOCKER_IMAGE"]) +// .WithName(containerName) +// .WithPublicEndpointResolver() +// .MountVolume(certsPath, "/etc/eventstore/certs", MountType.ReadOnly) +// .ExposePort(port, 2113) +// .KeepContainer().KeepRunning().ReuseIfExists() +// .WaitUntilReadyWithConstantBackoff( +// 1_000, +// 60, +// service => { +// var output = service.ExecuteCommand("curl -u admin:changeit --cacert /etc/eventstore/certs/ca/ca.crt https://localhost:2113/health/live"); +// if (!output.Success) +// throw new Exception(output.Error); +// } +// ); +// } +// } + +using System.Globalization; using System.Net; -using System.Net.Http; using System.Net.Sockets; using Ductus.FluentDocker.Builders; -using Ductus.FluentDocker.Common; +using Ductus.FluentDocker.Extensions; using Ductus.FluentDocker.Model.Builders; +using Ductus.FluentDocker.Services.Extensions; +using EventStore.Client; using EventStore.Client.Tests.FluentDocker; -using Polly; -using Polly.Contrib.WaitAndRetry; +using Humanizer; using Serilog; using Serilog.Extensions.Logging; using static System.TimeSpan; -namespace EventStore.Client.Tests; +public class KurrentPermanentTestNode(KurrentFixtureOptions? options = null) : TestContainerService { + static readonly NetworkPortProvider NetworkPortProvider = new(NetworkPortProvider.DefaultEsdbPort); -public class EventStoreTestNode(EventStoreFixtureOptions? options = null) : TestContainerService { + KurrentFixtureOptions Options { get; } = options ?? DefaultOptions(); - static readonly NetworkPortProvider NetworkPortProvider = new(NetworkPortProvider.DefaultEsdbPort); + static Version? _version; - EventStoreFixtureOptions Options { get; } = options ?? DefaultOptions(); + public static Version Version => _version ??= GetVersion(); - public static EventStoreFixtureOptions DefaultOptions() { + public static KurrentFixtureOptions DefaultOptions() { const string connString = "esdb://admin:changeit@localhost:{port}/?tlsVerifyCert=false"; var port = NetworkPortProvider.NextAvailablePort; @@ -33,23 +69,20 @@ public static EventStoreFixtureOptions DefaultOptions() { var defaultEnvironment = new Dictionary(GlobalEnvironment.Variables) { ["EVENTSTORE_MEM_DB"] = "true", - ["EVENTSTORE_CHUNK_SIZE"] = (1024 * 1024 * 1024).ToString(), ["EVENTSTORE_CERTIFICATE_FILE"] = "/etc/eventstore/certs/node/node.crt", ["EVENTSTORE_CERTIFICATE_PRIVATE_KEY_FILE"] = "/etc/eventstore/certs/node/node.key", ["EVENTSTORE_STREAM_EXISTENCE_FILTER_SIZE"] = "10000", ["EVENTSTORE_STREAM_INFO_CACHE_CAPACITY"] = "10000", ["EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP"] = "true", - ["EVENTSTORE_LOG_LEVEL"] = "Default", // required to use serilog settings + ["EVENTSTORE_LOG_LEVEL"] = "Default", // required to use serilog settings ["EVENTSTORE_DISABLE_LOG_FILE"] = "true", + ["EVENTSTORE_START_STANDARD_PROJECTIONS"] = "true", + ["EVENTSTORE_RUN_PROJECTIONS"] = "All", + ["EVENTSTORE_CHUNK_SIZE"] = (1024 * 1024 * 1024).ToString(), + ["EVENTSTORE_MAX_APPEND_SIZE"] = 100.Kilobytes().Bytes.ToString(CultureInfo.InvariantCulture), ["EVENTSTORE_ADVERTISE_HTTP_PORT_TO_CLIENT_AS"] = $"{NetworkPortProvider.DefaultEsdbPort}" }; - if (GlobalEnvironment.DockerImage.Contains("commercial")) { - defaultEnvironment["EVENTSTORE_TRUSTED_ROOT_CERTIFICATES_PATH"] = "/etc/eventstore/certs/ca"; - defaultEnvironment["EventStore__Plugins__UserCertificates__Enabled"] = "true"; - } - - // TODO SS: must find a way to enable parallel tests on CI. It works locally. if (port != NetworkPortProvider.DefaultEsdbPort) { if (GlobalEnvironment.Variables.TryGetValue("ES_DOCKER_TAG", out var tag) && tag == "ci") defaultEnvironment["EVENTSTORE_ADVERTISE_NODE_PORT_TO_CLIENT_AS"] = $"{port}"; @@ -60,6 +93,33 @@ public static EventStoreFixtureOptions DefaultOptions() { return new(defaultSettings, defaultEnvironment); } + static Version GetVersion() { + const string versionPrefix = "EventStoreDB version"; + + using var cts = new CancellationTokenSource(FromSeconds(30)); + using var eventstore = new Builder().UseContainer() + .UseImage(GlobalEnvironment.DockerImage) + .Command("--version") + .Build() + .Start(); + + using var log = eventstore.Logs(true, cts.Token); + foreach (var line in log.ReadToEnd()) { + if (line.StartsWith(versionPrefix) && + Version.TryParse(new string(ReadVersion(line[(versionPrefix.Length + 1)..]).ToArray()), out var version)) { + return version; + } + } + + throw new InvalidOperationException("Could not determine server version."); + + IEnumerable ReadVersion(string s) { + foreach (var c in s.TakeWhile(c => c == '.' || char.IsDigit(c))) { + yield return c; + } + } + } + protected override ContainerBuilder Configure() { var env = Options.Environment.Select(pair => $"{pair.Key}={pair.Value}").ToArray(); @@ -76,44 +136,21 @@ protected override ContainerBuilder Configure() { .UseContainer() .UseImage(Options.Environment["ES_DOCKER_IMAGE"]) .WithName(containerName) - .WithPublicEndpointResolver() + .WithPublicEndpointResolver() .WithEnvironment(env) .MountVolume(certsPath, "/etc/eventstore/certs", MountType.ReadOnly) .ExposePort(port, 2113) - // .KeepContainer().KeepRunning().ReuseIfExists() - .WaitUntilReadyWithConstantBackoff(1_000, 60, service => { - var output = service.ExecuteCommand("curl -u admin:changeit --cacert /etc/eventstore/certs/ca/ca.crt https://localhost:2113/health/live"); - if (!output.Success) - throw new Exception(output.Error); - }); + .KeepContainer().KeepRunning().ReuseIfExists() + .WaitUntilReadyWithConstantBackoff( + 1_000, + 60, + service => { + var output = service.ExecuteCommand("curl -u admin:changeit --cacert /etc/eventstore/certs/ca/ca.crt https://localhost:2113/health/live"); + if (!output.Success) + throw new Exception(output.Error); + } + ); } - -// /// -// /// max of 30 seconds (300 * 100ms) -// /// -// static readonly IEnumerable DefaultBackoffDelay = Backoff.ConstantBackoff(FromMilliseconds(100), 300); -// -// protected override async Task OnServiceStarted() { -// using var http = new HttpClient( -// #if NET -// new SocketsHttpHandler { SslOptions = { RemoteCertificateValidationCallback = delegate { return true; } } } -// #else -// new WinHttpHandler { ServerCertificateValidationCallback = delegate { return true; } } -// #endif -// ) { -// BaseAddress = Options.ClientSettings.ConnectivitySettings.Address -// }; -// -// await Policy.Handle() -// .WaitAndRetryAsync(DefaultBackoffDelay) -// .ExecuteAsync( -// async () => { -// using var response = await http.GetAsync("/health/live", CancellationToken.None); -// if (response.StatusCode >= HttpStatusCode.BadRequest) -// throw new FluentDockerException($"Health check failed with status code: {response.StatusCode}."); -// } -// ); -// } } /// @@ -125,7 +162,7 @@ class NetworkPortProvider(int port = 2114) { static readonly SemaphoreSlim Semaphore = new(1, 1); - public async Task GetNextAvailablePort(TimeSpan delay = default) { + async Task GetNextAvailablePort(TimeSpan delay = default) { // TODO SS: find a way to enable parallel tests on CI if (port == DefaultEsdbPort) return port; @@ -140,15 +177,13 @@ public async Task GetNextAvailablePort(TimeSpan delay = default) { try { await socket.ConnectAsync(IPAddress.Any, nexPort); - } - catch (SocketException ex) { + } catch (SocketException ex) { if (ex.SocketErrorCode is SocketError.ConnectionRefused or not SocketError.IsConnected) { return nexPort; } await Task.Delay(delay); - } - finally { + } finally { #if NET if (socket.Connected) await socket.DisconnectAsync(true); #else @@ -156,8 +191,7 @@ public async Task GetNextAvailablePort(TimeSpan delay = default) { #endif } } - } - finally { + } finally { Semaphore.Release(); } } diff --git a/test/EventStore.Client.Tests.Common/Fixtures/KurrentTemporaryFixture.Helpers.cs b/test/EventStore.Client.Tests.Common/Fixtures/KurrentTemporaryFixture.Helpers.cs new file mode 100644 index 000000000..3090742b9 --- /dev/null +++ b/test/EventStore.Client.Tests.Common/Fixtures/KurrentTemporaryFixture.Helpers.cs @@ -0,0 +1,107 @@ +using System.Runtime.CompilerServices; +using System.Text; + +namespace EventStore.Client.Tests.TestNode; + +public partial class KurrentTemporaryFixture { + public const string TestEventType = "test-event-type"; + public const string AnotherTestEventTypePrefix = "another"; + public const string AnotherTestEventType = $"{AnotherTestEventTypePrefix}-test-event-type"; + + public T NewClient(Action configure) where T : EventStoreClientBase, new() => + (T)Activator.CreateInstance(typeof(T), [ClientSettings.With(configure)])!; + + public string GetStreamName([CallerMemberName] string? testMethod = null) => + $"stream-{testMethod}-{Guid.NewGuid():N}"; + + public string GetGroupName([CallerMemberName] string? testMethod = null) => + $"group-{testMethod}-{Guid.NewGuid():N}"; + + public UserCredentials GetUserCredentials([CallerMemberName] string? testMethod = null) => new UserCredentials( + $"user-{testMethod}-{Guid.NewGuid():N}", + "pa$$word" + ); + + public string GetProjectionName([CallerMemberName] string? testMethod = null) => + $"projection-{testMethod}-{Guid.NewGuid():N}"; + + public ReadOnlyMemory CreateMetadataOfSize(int metadataSize) => + Encoding.UTF8.GetBytes($"\"{new string('$', metadataSize)}\""); + + public ReadOnlyMemory CreateTestJsonMetadata() => "{\"Foo\": \"Bar\"}"u8.ToArray(); + + public ReadOnlyMemory CreateTestNonJsonMetadata() => "non-json-metadata"u8.ToArray(); + + public (IEnumerable Events, uint size) CreateTestEventsUpToMaxSize(uint maxSize) { + var size = 0; + + var events = CreateTestEvents(int.MaxValue) + .TakeWhile(evt => (size += evt.Data.Length) < maxSize) + .ToList(); + + return (events, (uint)size); + } + + public IEnumerable CreateTestEvents( + int count = 1, string? type = null, ReadOnlyMemory? metadata = null, string? contentType = null + ) => + Enumerable.Range(0, count) + .Select(index => CreateTestEvent(index, type ?? TestEventType, metadata, contentType)); + + public EventData CreateTestEvent( + string? type = null, ReadOnlyMemory? metadata = null, string? contentType = null + ) => + CreateTestEvent(0, type ?? TestEventType, metadata, contentType); + + public IEnumerable CreateTestEventsThatThrowsException() { + // Ensure initial IEnumerator.Current does not throw + yield return CreateTestEvent(1); + + // Throw after enumerator advances + throw new Exception(); + } + + protected static EventData CreateTestEvent(int index) => CreateTestEvent(index, TestEventType); + + protected static EventData CreateTestEvent( + int index, string type, ReadOnlyMemory? metadata = null, string? contentType = null + ) => + new( + Uuid.NewUuid(), + type, + Encoding.UTF8.GetBytes($$"""{"x":{{index}}}"""), + metadata, + contentType ?? "application/json" + ); + + public async Task CreateTestUser(bool withoutGroups = true, bool useUserCredentials = false) { + var result = await CreateTestUsers(1, withoutGroups, useUserCredentials); + return result.First(); + } + + public Task CreateTestUsers( + int count = 3, bool withoutGroups = true, bool useUserCredentials = false + ) => + Fakers.Users + .RuleFor(x => x.Groups, f => withoutGroups ? Array.Empty() : f.Lorem.Words()) + .Generate(count) + .Select( + async user => { + await Users.CreateUserAsync( + user.LoginName, + user.FullName, + user.Groups, + user.Password, + userCredentials: useUserCredentials ? user.Credentials : TestCredentials.Root + ); + + return user; + } + ).WhenAll(); + + public async Task RestartService(TimeSpan delay) { + await Service.Restart(delay); + await Streams.WarmUp(); + Log.Information("Service restarted."); + } +} diff --git a/test/EventStore.Client.Tests.Common/Fixtures/KurrentTemporaryFixture.cs b/test/EventStore.Client.Tests.Common/Fixtures/KurrentTemporaryFixture.cs new file mode 100644 index 000000000..e7e6bb889 --- /dev/null +++ b/test/EventStore.Client.Tests.Common/Fixtures/KurrentTemporaryFixture.cs @@ -0,0 +1,189 @@ +// ReSharper disable InconsistentNaming + +using System.Net; +using Ductus.FluentDocker.Builders; +using Ductus.FluentDocker.Extensions; +using Ductus.FluentDocker.Services.Extensions; +using EventStore.Client.Tests.FluentDocker; +using Serilog; +using static System.TimeSpan; + +namespace EventStore.Client.Tests.TestNode; + +[PublicAPI] +public partial class KurrentTemporaryFixture : IAsyncLifetime, IAsyncDisposable { + static readonly ILogger Logger; + + static KurrentTemporaryFixture() { + Logging.Initialize(); + Logger = Serilog.Log.ForContext(); + +#if NET9_0_OR_GREATER + var httpClientHandler = new HttpClientHandler(); + httpClientHandler.ServerCertificateCustomValidationCallback = delegate { return true; }; +#else + ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; +#endif + } + + public KurrentTemporaryFixture() : this(options => options) { } + + protected KurrentTemporaryFixture(ConfigureFixture configure) { + // Options = configure(EventStoreTemporaryTestNode.DefaultOptions()); + Options = configure(KurrentTemporaryTestNode.DefaultOptions()); + Service = new KurrentTemporaryTestNode(Options); + } + + List TestRuns { get; } = new(); + + public ILogger Log => Logger; + + public ITestService Service { get; } + public KurrentFixtureOptions Options { get; } + public Faker Faker { get; } = new Faker(); + + public Version EventStoreVersion { get; private set; } = null!; + public bool EventStoreHasLastStreamPosition { get; private set; } + + public EventStoreClient Streams { get; private set; } = null!; + public EventStoreUserManagementClient Users { get; private set; } = null!; + public EventStoreProjectionManagementClient Projections { get; private set; } = null!; + public EventStorePersistentSubscriptionsClient Subscriptions { get; private set; } = null!; + public EventStoreOperationsClient Operations { get; private set; } = null!; + + public bool SkipPsWarmUp { get; set; } + + public Func OnSetup { get; init; } = () => Task.CompletedTask; + public Func OnTearDown { get; init; } = () => Task.CompletedTask; + + /// + /// must test this + /// + public EventStoreClientSettings ClientSettings => + new() { + Interceptors = Options.ClientSettings.Interceptors, + ConnectionName = Options.ClientSettings.ConnectionName, + CreateHttpMessageHandler = Options.ClientSettings.CreateHttpMessageHandler, + LoggerFactory = Options.ClientSettings.LoggerFactory, + ChannelCredentials = Options.ClientSettings.ChannelCredentials, + OperationOptions = Options.ClientSettings.OperationOptions, + ConnectivitySettings = Options.ClientSettings.ConnectivitySettings, + DefaultCredentials = Options.ClientSettings.DefaultCredentials, + DefaultDeadline = Options.ClientSettings.DefaultDeadline + }; + + InterlockedBoolean WarmUpCompleted { get; } = new InterlockedBoolean(); + SemaphoreSlim WarmUpGatekeeper { get; } = new(1, 1); + static readonly SemaphoreSlim ContainerSemaphore = new(1, 1); + + public void CaptureTestRun(ITestOutputHelper outputHelper) { + var testRunId = Logging.CaptureLogs(outputHelper); + TestRuns.Add(testRunId); + Logger.Information(">>> Test Run {TestRunId} {Operation} <<<", testRunId, "starting"); + Service.ReportStatus(); + } + + public async Task InitializeAsync() { + await ContainerSemaphore.WaitAsync(); + try { + await Service.Start(); + } finally { + ContainerSemaphore.Release(); + } + + EventStoreVersion = GetEventStoreVersion(); + EventStoreHasLastStreamPosition = (EventStoreVersion?.Major ?? int.MaxValue) >= 21; + + await WarmUpGatekeeper.WaitAsync(); + + try { + if (!WarmUpCompleted.CurrentValue) { + Logger.Warning("*** Warmup started ***"); + + await Task.WhenAll( + InitClient(async x => Users = await x.WarmUp()), + InitClient(async x => Streams = await x.WarmUp()), + InitClient( + async x => Projections = await x.WarmUp(), + Options.Environment["EVENTSTORE_RUN_PROJECTIONS"] != "None" + ), + InitClient(async x => Subscriptions = SkipPsWarmUp ? x : await x.WarmUp()), + InitClient(async x => Operations = await x.WarmUp()) + ); + + WarmUpCompleted.EnsureCalledOnce(); + + Logger.Warning("*** Warmup completed ***"); + } else { + Logger.Information("*** Warmup skipped ***"); + } + } finally { + WarmUpGatekeeper.Release(); + } + + await OnSetup(); + + return; + + async Task InitClient(Func action, bool execute = true) where T : EventStoreClientBase { + if (!execute) return default(T)!; + + var client = (Activator.CreateInstance(typeof(T), ClientSettings) as T)!; + await action(client); + return client; + } + + static Version GetEventStoreVersion() { + const string versionPrefix = "EventStoreDB version"; + + using var cancellator = new CancellationTokenSource(FromSeconds(30)); + using var eventstore = new Builder() + .UseContainer() + .UseImage(GlobalEnvironment.DockerImage) + .Command("--version") + .Build() + .Start(); + + using var log = eventstore.Logs(true, cancellator.Token); + foreach (var line in log.ReadToEnd()) { + if (line.StartsWith(versionPrefix) && + Version.TryParse( + new string(ReadVersion(line[(versionPrefix.Length + 1)..]).ToArray()), + out var version + )) { + return version; + } + } + + throw new InvalidOperationException("Could not determine server version."); + + IEnumerable ReadVersion(string s) { + foreach (var c in s.TakeWhile(c => c == '.' || char.IsDigit(c))) { + yield return c; + } + } + } + } + + public async Task DisposeAsync() { + try { + await OnTearDown(); + } catch { + // ignored + } + + await Service.DisposeAsync().AsTask().WithTimeout(FromMinutes(5)); + + foreach (var testRunId in TestRuns) + Logging.ReleaseLogs(testRunId); + } + + async ValueTask IAsyncDisposable.DisposeAsync() => await DisposeAsync(); +} + +public abstract class KurrentTemporaryTests : IClassFixture where TFixture : KurrentTemporaryFixture { + protected KurrentTemporaryTests(ITestOutputHelper output, TFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); + + protected TFixture Fixture { get; } +} diff --git a/test/EventStore.Client.Tests.Common/Fixtures/KurrentTemporaryTestNode.cs b/test/EventStore.Client.Tests.Common/Fixtures/KurrentTemporaryTestNode.cs new file mode 100644 index 000000000..ca7ef8cc0 --- /dev/null +++ b/test/EventStore.Client.Tests.Common/Fixtures/KurrentTemporaryTestNode.cs @@ -0,0 +1,193 @@ +// ReSharper disable InconsistentNaming + +// using Ductus.FluentDocker.Builders; +// using Ductus.FluentDocker.Model.Builders; +// using EventStore.Client.Tests.FluentDocker; +// +// namespace EventStore.Client.Tests.TestNode; +// +// public class EventStoreTemporaryTestNode(EventStoreFixtureOptions? options = null) : BaseTestNode(options) { +// protected override ContainerBuilder ConfigureContainer(ContainerBuilder builder) { +// var port = Options.ClientSettings.ConnectivitySettings.ResolvedAddressOrDefault.Port; +// var certsPath = Path.Combine(Environment.CurrentDirectory, "certs"); +// +// var containerName = $"es-client-dotnet-test-{port}-{Guid.NewGuid().ToString()[30..]}"; +// +// return builder +// .UseImage(Options.Environment["ES_DOCKER_IMAGE"]) +// .WithName(containerName) +// .WithPublicEndpointResolver() +// .MountVolume(certsPath, "/etc/eventstore/certs", MountType.ReadOnly) +// .ExposePort(port, 2113) +// .WaitUntilReadyWithConstantBackoff( +// 1_000, +// 60, +// service => { +// var output = service.ExecuteCommand("curl -u admin:changeit --cacert /etc/eventstore/certs/ca/ca.crt https://localhost:2113/health/live"); +// if (!output.Success) +// throw new Exception(output.Error); +// } +// ); +// } +// } + +using System.Globalization; +using System.Net; +using System.Net.Sockets; +using Ductus.FluentDocker.Builders; +using Ductus.FluentDocker.Extensions; +using Ductus.FluentDocker.Model.Builders; +using Ductus.FluentDocker.Services.Extensions; +using EventStore.Client.Tests.FluentDocker; +using Humanizer; +using Serilog; +using Serilog.Extensions.Logging; +using static System.TimeSpan; + +namespace EventStore.Client.Tests.TestNode; + +public class KurrentTemporaryTestNode(KurrentFixtureOptions? options = null) : TestContainerService { + static readonly NetworkPortProvider NetworkPortProvider = new(NetworkPortProvider.DefaultEsdbPort); + + KurrentFixtureOptions Options { get; } = options ?? DefaultOptions(); + + static Version? _version; + + public static Version Version => _version ??= GetVersion(); + + public static KurrentFixtureOptions DefaultOptions() { + const string connString = "esdb://admin:changeit@localhost:{port}/?tlsVerifyCert=false"; + + var port = NetworkPortProvider.NextAvailablePort; + + var defaultSettings = EventStoreClientSettings + .Create(connString.Replace("{port}", $"{port}")) + .With(x => x.LoggerFactory = new SerilogLoggerFactory(Log.Logger)) + .With(x => x.DefaultDeadline = Application.DebuggerIsAttached ? new TimeSpan?() : FromSeconds(30)) + .With(x => x.ConnectivitySettings.MaxDiscoverAttempts = 20) + .With(x => x.ConnectivitySettings.DiscoveryInterval = FromSeconds(1)); + + var defaultEnvironment = new Dictionary(GlobalEnvironment.Variables) { + ["EVENTSTORE_MEM_DB"] = "true", + ["EVENTSTORE_CERTIFICATE_FILE"] = "/etc/eventstore/certs/node/node.crt", + ["EVENTSTORE_CERTIFICATE_PRIVATE_KEY_FILE"] = "/etc/eventstore/certs/node/node.key", + ["EVENTSTORE_STREAM_EXISTENCE_FILTER_SIZE"] = "10000", + ["EVENTSTORE_STREAM_INFO_CACHE_CAPACITY"] = "10000", + ["EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP"] = "true", + ["EVENTSTORE_LOG_LEVEL"] = "Default", // required to use serilog settings + ["EVENTSTORE_DISABLE_LOG_FILE"] = "true", + ["EVENTSTORE_CHUNK_SIZE"] = (1024 * 1024 * 1024).ToString(), + ["EVENTSTORE_MAX_APPEND_SIZE"] = 100.Kilobytes().Bytes.ToString(CultureInfo.InvariantCulture), + ["EVENTSTORE_ADVERTISE_HTTP_PORT_TO_CLIENT_AS"] = $"{NetworkPortProvider.DefaultEsdbPort}" + }; + + if (port != NetworkPortProvider.DefaultEsdbPort) { + if (GlobalEnvironment.Variables.TryGetValue("ES_DOCKER_TAG", out var tag) && tag == "ci") + defaultEnvironment["EVENTSTORE_ADVERTISE_NODE_PORT_TO_CLIENT_AS"] = $"{port}"; + else + defaultEnvironment["EVENTSTORE_ADVERTISE_HTTP_PORT_TO_CLIENT_AS"] = $"{port}"; + } + + return new(defaultSettings, defaultEnvironment); + } + + static Version GetVersion() { + const string versionPrefix = "EventStoreDB version"; + + using var cts = new CancellationTokenSource(FromSeconds(30)); + using var eventstore = new Builder().UseContainer() + .UseImage(GlobalEnvironment.DockerImage) + .Command("--version") + .Build() + .Start(); + + using var log = eventstore.Logs(true, cts.Token); + foreach (var line in log.ReadToEnd()) { + if (line.StartsWith(versionPrefix) && + Version.TryParse(new string(ReadVersion(line[(versionPrefix.Length + 1)..]).ToArray()), out var version)) { + return version; + } + } + + throw new InvalidOperationException("Could not determine server version."); + + IEnumerable ReadVersion(string s) { + foreach (var c in s.TakeWhile(c => c == '.' || char.IsDigit(c))) { + yield return c; + } + } + } + + protected override ContainerBuilder Configure() { + var env = Options.Environment.Select(pair => $"{pair.Key}={pair.Value}").ToArray(); + + var port = Options.ClientSettings.ConnectivitySettings.ResolvedAddressOrDefault.Port; + var certsPath = Path.Combine(Environment.CurrentDirectory, "certs"); + + var containerName = $"es-client-dotnet-test-{port}-{Guid.NewGuid().ToString()[30..]}"; + + CertificatesManager.VerifyCertificatesExist(certsPath); + + var builder = new Builder() + .UseContainer() + .UseImage(Options.Environment["ES_DOCKER_IMAGE"]) + .WithName(containerName) + .WithPublicEndpointResolver() + .WithEnvironment(env) + .MountVolume(certsPath, "/etc/eventstore/certs", MountType.ReadOnly) + .ExposePort(port, 2113) + .WaitUntilReadyWithConstantBackoff( + 1_000, + 60, + service => { + var output = service.ExecuteCommand("curl -u admin:changeit --cacert /etc/eventstore/certs/ca/ca.crt https://localhost:2113/health/live"); + if (!output.Success) + throw new Exception(output.Error); + } + ); + + return builder; + } +} + +/// +/// Using the default 2113 port assumes that the test is running sequentially. +/// +/// +class NetworkPortProvider(int port = 2114) { + public const int DefaultEsdbPort = 2113; + + static readonly SemaphoreSlim Semaphore = new(1, 1); + + async Task GetNextAvailablePort(TimeSpan delay = default) { + await Semaphore.WaitAsync(); + + try { + using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + + while (true) { + var nexPort = Interlocked.Increment(ref port); + + try { + await socket.ConnectAsync(IPAddress.Any, nexPort); + } catch (SocketException ex) { + if (ex.SocketErrorCode is SocketError.ConnectionRefused or not SocketError.IsConnected) { + return nexPort; + } + + await Task.Delay(delay); + } finally { +#if NET + if (socket.Connected) await socket.DisconnectAsync(true); +#else + if (socket.Connected) socket.Disconnect(true); +#endif + } + } + } finally { + Semaphore.Release(); + } + } + + public int NextAvailablePort => GetNextAvailablePort(FromMilliseconds(100)).GetAwaiter().GetResult(); +} diff --git a/test/EventStore.Client.Tests.Common/Fixtures/RunInMemoryTestFixture.cs b/test/EventStore.Client.Tests.Common/Fixtures/RunInMemoryTestFixture.cs deleted file mode 100644 index 61cfbc77c..000000000 --- a/test/EventStore.Client.Tests.Common/Fixtures/RunInMemoryTestFixture.cs +++ /dev/null @@ -1,4 +0,0 @@ -namespace EventStore.Client.Tests; - -[PublicAPI] -public class RunInMemoryTestFixture() : EventStoreFixture(x => x.RunInMemory()); \ No newline at end of file diff --git a/test/EventStore.Client.Tests.Common/Fixtures/RunProjectionsTestFixture.cs b/test/EventStore.Client.Tests.Common/Fixtures/RunProjectionsTestFixture.cs deleted file mode 100644 index cb42cc1db..000000000 --- a/test/EventStore.Client.Tests.Common/Fixtures/RunProjectionsTestFixture.cs +++ /dev/null @@ -1,4 +0,0 @@ -namespace EventStore.Client.Tests; - -[PublicAPI] -public class RunProjectionsTestFixture() : EventStoreFixture(x => x.RunProjections()); \ No newline at end of file diff --git a/test/EventStore.Client.Tests.Common/FluentDocker/FluentDockerBuilderExtensions.cs b/test/EventStore.Client.Tests.Common/FluentDocker/FluentDockerBuilderExtensions.cs index b41c031c9..3dd450676 100644 --- a/test/EventStore.Client.Tests.Common/FluentDocker/FluentDockerBuilderExtensions.cs +++ b/test/EventStore.Client.Tests.Common/FluentDocker/FluentDockerBuilderExtensions.cs @@ -85,4 +85,4 @@ public static ContainerBuilder WaitUntilReadyWithConstantBackoffAsync( public static ContainerBuilder WaitUntilReadyWithExponentialBackoffAsync( this ContainerBuilder builder, int delayMs, int retryCount, Func action ) => builder.WaitUntilReadyWithExponentialBackoffAsync(FromMilliseconds(delayMs), retryCount, action); -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests.Common/FluentDocker/FluentDockerServiceExtensions.cs b/test/EventStore.Client.Tests.Common/FluentDocker/FluentDockerServiceExtensions.cs index 3fab79a6e..0546c4e04 100644 --- a/test/EventStore.Client.Tests.Common/FluentDocker/FluentDockerServiceExtensions.cs +++ b/test/EventStore.Client.Tests.Common/FluentDocker/FluentDockerServiceExtensions.cs @@ -85,4 +85,4 @@ public static CommandResponse> ExecuteCommand(this IContainerServi var config = service.GetConfiguration(); return service.DockerHost.Execute(config.Id, command, service.Certificates); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests.Common/FluentDocker/TestCompositeService.cs b/test/EventStore.Client.Tests.Common/FluentDocker/TestCompositeService.cs index 104827f30..262133e9f 100644 --- a/test/EventStore.Client.Tests.Common/FluentDocker/TestCompositeService.cs +++ b/test/EventStore.Client.Tests.Common/FluentDocker/TestCompositeService.cs @@ -3,4 +3,4 @@ namespace EventStore.Client.Tests.FluentDocker; -public abstract class TestCompositeService : TestService; \ No newline at end of file +public abstract class TestCompositeService : TestService; diff --git a/test/EventStore.Client.Tests.Common/FluentDocker/TestContainerService.cs b/test/EventStore.Client.Tests.Common/FluentDocker/TestContainerService.cs index 40ed937fc..ae37c353d 100644 --- a/test/EventStore.Client.Tests.Common/FluentDocker/TestContainerService.cs +++ b/test/EventStore.Client.Tests.Common/FluentDocker/TestContainerService.cs @@ -3,4 +3,4 @@ namespace EventStore.Client.Tests.FluentDocker; -public abstract class TestContainerService : TestService; \ No newline at end of file +public abstract class TestContainerService : TestService; diff --git a/test/EventStore.Client.Tests.Common/GlobalEnvironment.cs b/test/EventStore.Client.Tests.Common/GlobalEnvironment.cs index 1186d5f68..1fd1ee020 100644 --- a/test/EventStore.Client.Tests.Common/GlobalEnvironment.cs +++ b/test/EventStore.Client.Tests.Common/GlobalEnvironment.cs @@ -23,7 +23,7 @@ static void EnsureDefaults(IConfiguration configuration) { configuration.EnsureValue("ES_USE_EXTERNAL_SERVER", "false"); configuration.EnsureValue("ES_DOCKER_REGISTRY", "docker.eventstore.com/eventstore-ce/eventstoredb-ce"); - configuration.EnsureValue("ES_DOCKER_TAG", "previous-lts"); + configuration.EnsureValue("ES_DOCKER_TAG", "ci"); configuration.EnsureValue("ES_DOCKER_IMAGE", $"{configuration["ES_DOCKER_REGISTRY"]}:{configuration["ES_DOCKER_TAG"]}"); configuration.EnsureValue("EVENTSTORE_TELEMETRY_OPTOUT", "true"); @@ -35,7 +35,6 @@ static void EnsureDefaults(IConfiguration configuration) { configuration.EnsureValue("EVENTSTORE_DISABLE_LOG_FILE", "true"); configuration.EnsureValue("EVENTSTORE_TRUSTED_ROOT_CERTIFICATES_PATH", "/etc/eventstore/certs/ca"); configuration.EnsureValue("EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP", "true"); - } } @@ -44,35 +43,4 @@ static void EnsureDefaults(IConfiguration configuration) { public static bool UseCluster { get; } public static bool UseExternalServer { get; } public static string DockerImage { get; } - - #region . Obsolete . - - //[Obsolete("Use the EventStoreFixture instead so you don't have to use this method.", false)] - public static IDictionary GetEnvironmentVariables(IDictionary? overrides = null) { - var env = new Dictionary { - ["ES_DOCKER_TAG"] = "ci", - ["EVENTSTORE_DB_LOG_FORMAT"] = "V2", - }; - - foreach (var @override in overrides ?? Enumerable.Empty>()) { - if (@override.Key.StartsWith("EVENTSTORE") && !SharedEnv.Contains(@override.Key)) - throw new Exception($"Add {@override.Key} to shared.env and _sharedEnv to pass it to the cluster containers"); - - env[@override.Key] = @override.Value; - } - - return env; - } - - // matches with the pass-through vars in shared.env... better way? - static readonly HashSet SharedEnv = new() { - "EVENTSTORE_DB_LOG_FORMAT", - "EVENTSTORE_LOG_LEVEL", - "EVENTSTORE_MAX_APPEND_SIZE", - "EVENTSTORE_MEM_DB", - "EVENTSTORE_RUN_PROJECTIONS", - "EVENTSTORE_START_STANDARD_PROJECTIONS", - }; - - #endregion } diff --git a/test/EventStore.Client.Tests.Common/Logging.cs b/test/EventStore.Client.Tests.Common/Logging.cs index a9df9709a..5742e1134 100644 --- a/test/EventStore.Client.Tests.Common/Logging.cs +++ b/test/EventStore.Client.Tests.Common/Logging.cs @@ -78,4 +78,4 @@ public static void ReleaseLogs(Guid captureId) { // ignored } } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests.Common/PasswordGenerator.cs b/test/EventStore.Client.Tests.Common/PasswordGenerator.cs index 298600529..f8990b18d 100644 --- a/test/EventStore.Client.Tests.Common/PasswordGenerator.cs +++ b/test/EventStore.Client.Tests.Common/PasswordGenerator.cs @@ -63,4 +63,4 @@ public static string GenerateSimplePassword(int length = 8) { return new(password); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests.Common/Shouldly/ShouldThrowAsyncExtensions.cs b/test/EventStore.Client.Tests.Common/Shouldly/ShouldThrowAsyncExtensions.cs index b75778b47..f5ec36636 100644 --- a/test/EventStore.Client.Tests.Common/Shouldly/ShouldThrowAsyncExtensions.cs +++ b/test/EventStore.Client.Tests.Common/Shouldly/ShouldThrowAsyncExtensions.cs @@ -9,4 +9,4 @@ namespace Shouldly; public static class ShouldThrowAsyncExtensions { public static Task ShouldThrowAsync(this EventStoreClient.ReadStreamResult source) where TException : Exception => source.ToArrayAsync().AsTask().ShouldThrowAsync(); -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests.Common/TestCredentials.cs b/test/EventStore.Client.Tests.Common/TestCredentials.cs index a489cd13d..b3d075ba4 100644 --- a/test/EventStore.Client.Tests.Common/TestCredentials.cs +++ b/test/EventStore.Client.Tests.Common/TestCredentials.cs @@ -6,4 +6,4 @@ public static class TestCredentials { public static readonly UserCredentials TestUser2 = new("user2", "pa$$2"); public static readonly UserCredentials TestAdmin = new("adm", "admpa$$"); public static readonly UserCredentials TestBadUser = new("badlogin", "badpass"); -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests/Assertions/ComparableAssertion.cs b/test/EventStore.Client.Tests/Assertions/ComparableAssertion.cs index 0d626cf61..a41bd9fa9 100644 --- a/test/EventStore.Client.Tests/Assertions/ComparableAssertion.cs +++ b/test/EventStore.Client.Tests/Assertions/ComparableAssertion.cs @@ -142,4 +142,4 @@ public override void Verify(Type type) { } } } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests/Assertions/EqualityAssertion.cs b/test/EventStore.Client.Tests/Assertions/EqualityAssertion.cs index 055cef40b..69ab7aed6 100644 --- a/test/EventStore.Client.Tests/Assertions/EqualityAssertion.cs +++ b/test/EventStore.Client.Tests/Assertions/EqualityAssertion.cs @@ -67,4 +67,4 @@ public override void Verify(Type type) { throw new($"The type '{type}' did not implement the inequality (!=) operator correctly."); } } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests/Assertions/NullArgumentAssertion.cs b/test/EventStore.Client.Tests/Assertions/NullArgumentAssertion.cs index 770591afc..866ce8a47 100644 --- a/test/EventStore.Client.Tests/Assertions/NullArgumentAssertion.cs +++ b/test/EventStore.Client.Tests/Assertions/NullArgumentAssertion.cs @@ -50,4 +50,4 @@ public override void Verify(Type type) { } ); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests/Assertions/StringConversionAssertion.cs b/test/EventStore.Client.Tests/Assertions/StringConversionAssertion.cs index 8b97e33f8..302803c51 100644 --- a/test/EventStore.Client.Tests/Assertions/StringConversionAssertion.cs +++ b/test/EventStore.Client.Tests/Assertions/StringConversionAssertion.cs @@ -43,4 +43,4 @@ public override void Verify(Type type) { if (toString is not null) Assert.Equal(value, toString.Invoke(instance, null)); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests/Assertions/ValueObjectAssertion.cs b/test/EventStore.Client.Tests/Assertions/ValueObjectAssertion.cs index dbdbb5ca2..3ff92b7c9 100644 --- a/test/EventStore.Client.Tests/Assertions/ValueObjectAssertion.cs +++ b/test/EventStore.Client.Tests/Assertions/ValueObjectAssertion.cs @@ -13,4 +13,4 @@ static IEnumerable CreateChildrenAssertions(ISpecimenBuilde yield return new StringConversionAssertion(builder); yield return new NullArgumentAssertion(builder); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests/AutoScenarioDataAttribute.cs b/test/EventStore.Client.Tests/AutoScenarioDataAttribute.cs index d5840a41b..1bad5bce5 100644 --- a/test/EventStore.Client.Tests/AutoScenarioDataAttribute.cs +++ b/test/EventStore.Client.Tests/AutoScenarioDataAttribute.cs @@ -25,4 +25,4 @@ public override IEnumerable GetData(MethodInfo testMethod) { class CustomAutoData : AutoDataAttribute { public CustomAutoData(Type fixtureType) : base(() => (IFixture)Activator.CreateInstance(fixtureType)!) { } } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Plugins.Tests/ClientCertificateTests.cs b/test/EventStore.Client.Tests/ClientCertificatesTests.cs similarity index 76% rename from test/EventStore.Client.Plugins.Tests/ClientCertificateTests.cs rename to test/EventStore.Client.Tests/ClientCertificatesTests.cs index e50fde0a5..e2e1a248c 100644 --- a/test/EventStore.Client.Plugins.Tests/ClientCertificateTests.cs +++ b/test/EventStore.Client.Tests/ClientCertificatesTests.cs @@ -1,9 +1,12 @@ -namespace EventStore.Client.Plugins.Tests; +using Humanizer; + +namespace EventStore.Client.Tests; [Trait("Category", "Target:Plugins")] [Trait("Category", "Type:UserCertificate")] -public class ClientCertificateTests(ITestOutputHelper output, EventStoreFixture fixture) : EventStoreTests(output, fixture) { - [Theory, BadClientCertificatesTestCases] +public class ClientCertificateTests(ITestOutputHelper output, KurrentPermanentFixture fixture) + : EventStorePermanentTests(output, fixture) { + [SupportsPlugins.Theory(EventStoreRepository.Commercial, "This server version does not support plugins"), BadClientCertificatesTestCases] async Task bad_certificates_combinations_should_return_authentication_error(string userCertFile, string userKeyFile, string tlsCaFile) { var stream = Fixture.GetStreamName(); var seedEvents = Fixture.CreateTestEvents(); @@ -17,7 +20,7 @@ async Task bad_certificates_combinations_should_return_authentication_error(stri await client.AppendToStreamAsync(stream, StreamState.NoStream, seedEvents).ShouldThrowAsync(); } - [Theory, ValidClientCertificatesTestCases] + [SupportsPlugins.Theory(EventStoreRepository.Commercial, "This server version does not support plugins"), ValidClientCertificatesTestCases] async Task valid_certificates_combinations_should_write_to_stream(string userCertFile, string userKeyFile, string tlsCaFile) { var stream = Fixture.GetStreamName(); var seedEvents = Fixture.CreateTestEvents(); @@ -32,7 +35,7 @@ async Task valid_certificates_combinations_should_write_to_stream(string userCer result.ShouldNotBeNull(); } - [Theory, BadClientCertificatesTestCases] + [SupportsPlugins.Theory(EventStoreRepository.Commercial, "This server version does not support plugins"), BadClientCertificatesTestCases] async Task basic_authentication_should_take_precedence(string userCertFile, string userKeyFile, string tlsCaFile) { var stream = Fixture.GetStreamName(); var seedEvents = Fixture.CreateTestEvents(); @@ -65,3 +68,17 @@ protected override IEnumerable Data() { } } } + +public enum EventStoreRepository { + Commercial = 1 +} + +[PublicAPI] +public class SupportsPlugins { + public class TheoryAttribute(EventStoreRepository repository, string skipMessage) : Xunit.TheoryAttribute { + public override string? Skip { + get => !GlobalEnvironment.DockerImage.Contains(repository.Humanize().ToLower()) ? skipMessage : null; + set => throw new NotSupportedException(); + } + } +} diff --git a/test/EventStore.Client.Tests/ConnectionStringTests.cs b/test/EventStore.Client.Tests/ConnectionStringTests.cs index e258c682d..15b86703c 100644 --- a/test/EventStore.Client.Tests/ConnectionStringTests.cs +++ b/test/EventStore.Client.Tests/ConnectionStringTests.cs @@ -1,8 +1,11 @@ using System.Net; -using System.Net.Http; -using AutoFixture; using System.Reflection; using System.Security.Cryptography.X509Certificates; +using AutoFixture; + +#if NET48 +using System.Net.Http; +#endif namespace EventStore.Client.Tests; @@ -130,8 +133,7 @@ public void tls_verify_cert(bool tlsVerifyCert) { default ) ); - } - else { + } else { Assert.Null(socketsHandler.SslOptions.RemoteCertificateValidationCallback); } #else @@ -156,16 +158,14 @@ public void tls_verify_cert(bool tlsVerifyCert) { [Theory] [MemberData(nameof(InvalidTlsCertificates))] public void connection_string_with_invalid_tls_certificate_should_throw(string clientCertificatePath) { - Assert.Throws( - () => EventStoreClientSettings.Create( - $"esdb://admin:changeit@localhost:2113/?tls=true&tlsVerifyCert=true&tlsCAFile={clientCertificatePath}" - ) + Assert.Throws( + () => EventStoreClientSettings.Create($"esdb://admin:changeit@localhost:2113/?tls=true&tlsVerifyCert=true&tlsCAFile={clientCertificatePath}") ); } public static IEnumerable InvalidClientCertificates() { var invalidPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "path", "not", "found"); - var validPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "certs", "ca", "ca.crt"); + var validPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "certs", "ca", "ca.crt"); yield return [invalidPath, invalidPath]; yield return [validPath, invalidPath]; } @@ -180,7 +180,7 @@ public void connection_string_with_invalid_client_certificate_should_throw(strin ); } - [Fact] + [RetryFact] public void infinite_grpc_timeouts() { var result = EventStoreClientSettings.Create("esdb://localhost:2113?keepAliveInterval=-1&keepAliveTimeout=-1"); @@ -200,7 +200,7 @@ public void infinite_grpc_timeouts() { #endif } - [Fact] + [RetryFact] public void connection_string_with_no_schema() => Assert.Throws(() => EventStoreClientSettings.Create(":so/mething/random")); [Theory] @@ -271,7 +271,7 @@ public void connection_string_with_duplicate_key_should_throw(string connectionS public void connection_string_with_invalid_settings_should_throw(string connectionString) => Assert.Throws(() => EventStoreClientSettings.Create(connectionString)); - [Fact] + [RetryFact] public void with_default_settings() { var settings = EventStoreClientSettings.Create("esdb://hostname:4321/"); diff --git a/test/EventStore.Client.Tests/EventStoreClientOperationOptionsTests.cs b/test/EventStore.Client.Tests/EventStoreClientOperationsTests.cs similarity index 89% rename from test/EventStore.Client.Tests/EventStoreClientOperationOptionsTests.cs rename to test/EventStore.Client.Tests/EventStoreClientOperationsTests.cs index baf9bf5b3..031a4bfd6 100644 --- a/test/EventStore.Client.Tests/EventStoreClientOperationOptionsTests.cs +++ b/test/EventStore.Client.Tests/EventStoreClientOperationsTests.cs @@ -1,7 +1,7 @@ -namespace EventStore.Client.Tests; +namespace EventStore.Client.Tests; public class EventStoreClientOperationOptionsTests { - [Fact] + [RetryFact] public void setting_options_on_clone_should_not_modify_original() { var options = EventStoreClientOperationOptions.Default; @@ -11,4 +11,4 @@ public void setting_options_on_clone_should_not_modify_original() { Assert.Equal(options.BatchAppendSize, EventStoreClientOperationOptions.Default.BatchAppendSize); Assert.Equal(int.MaxValue, clonedOptions.BatchAppendSize); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests/FromAllTests.cs b/test/EventStore.Client.Tests/FromAllTests.cs index 82b8338ec..ae00af5dc 100644 --- a/test/EventStore.Client.Tests/FromAllTests.cs +++ b/test/EventStore.Client.Tests/FromAllTests.cs @@ -5,7 +5,7 @@ namespace EventStore.Client.Tests; public class FromAllTests : ValueObjectTests { public FromAllTests() : base(new ScenarioFixture()) { } - [Fact] + [RetryFact] public void IsComparable() => Assert.IsAssignableFrom>(_fixture.Create()); [Theory] @@ -28,10 +28,10 @@ public FromAllTests() : base(new ScenarioFixture()) { } [MemberData(nameof(ToStringCases))] public void ToStringReturnsExpectedResult(FromAll sut, string expected) => Assert.Equal(expected, sut.ToString()); - [Fact] + [RetryFact] public void AfterLiveThrows() => Assert.Throws(() => FromAll.After(Position.End)); - [Fact] + [RetryFact] public void ToUInt64ReturnsExpectedResults() { var position = _fixture.Create(); Assert.Equal( @@ -46,4 +46,4 @@ public ScenarioFixture() { Customize(composter => composter.FromFactory(FromAll.After)); } } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests/FromStreamTests.cs b/test/EventStore.Client.Tests/FromStreamTests.cs index a293aa44d..e6e1c08f8 100644 --- a/test/EventStore.Client.Tests/FromStreamTests.cs +++ b/test/EventStore.Client.Tests/FromStreamTests.cs @@ -5,7 +5,7 @@ namespace EventStore.Client.Tests; public class FromStreamTests : ValueObjectTests { public FromStreamTests() : base(new ScenarioFixture()) { } - [Fact] + [RetryFact] public void IsComparable() => Assert.IsAssignableFrom>(_fixture.Create()); [Theory] @@ -19,19 +19,19 @@ public FromStreamTests() : base(new ScenarioFixture()) { } public static IEnumerable ToStringCases() { var fixture = new ScenarioFixture(); var position = fixture.Create(); - yield return new object?[] { FromStream.After(position), position.ToString() }; - yield return new object?[] { FromStream.Start, "Start" }; - yield return new object?[] { FromStream.End, "Live" }; + yield return [FromStream.After(position), position.ToString()]; + yield return [FromStream.Start, "Start"]; + yield return [FromStream.End, "Live"]; } [Theory] [MemberData(nameof(ToStringCases))] public void ToStringReturnsExpectedResult(FromStream sut, string expected) => Assert.Equal(expected, sut.ToString()); - [Fact] + [RetryFact] public void AfterLiveThrows() => Assert.Throws(() => FromStream.After(StreamPosition.End)); - [Fact] + [RetryFact] public void ToUInt64ReturnsExpectedResults() { var position = _fixture.Create(); Assert.Equal(position.ToUInt64(), FromStream.After(position).ToUInt64()); @@ -43,4 +43,4 @@ public ScenarioFixture() { Customize(composter => composter.FromFactory(FromStream.After)); } } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests/GossipChannelSelectorTests.cs b/test/EventStore.Client.Tests/GossipChannelSelectorTests.cs index 5967f7384..00cdc0e0f 100644 --- a/test/EventStore.Client.Tests/GossipChannelSelectorTests.cs +++ b/test/EventStore.Client.Tests/GossipChannelSelectorTests.cs @@ -4,7 +4,7 @@ namespace EventStore.Client.Tests; public class GossipChannelSelectorTests { - [Fact] + [RetryFact] public async Task ExplicitlySettingEndPointChangesChannels() { var firstId = Uuid.NewUuid(); var secondId = Uuid.NewUuid(); @@ -53,7 +53,7 @@ public async Task ExplicitlySettingEndPointChangesChannels() { Assert.Equal($"{secondSelection.Host}:{secondSelection.Port}", channel.Target); } - [Fact] + [RetryFact] public async Task ThrowsWhenDiscoveryFails() { var settings = new EventStoreClientSettings { ConnectivitySettings = { @@ -93,4 +93,4 @@ CancellationToken cancellationToken ) => throw new NotSupportedException(); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests/GrpcServerCapabilitiesClientTests.cs b/test/EventStore.Client.Tests/GrpcServerCapabilitiesClientTests.cs index 258f51cd6..b1b5014df 100644 --- a/test/EventStore.Client.Tests/GrpcServerCapabilitiesClientTests.cs +++ b/test/EventStore.Client.Tests/GrpcServerCapabilitiesClientTests.cs @@ -99,4 +99,4 @@ // public override Task GetSupportedMethods(Empty request, ServerCallContext context) => Task.FromResult(_supportedMethods); // } // } -// #endif \ No newline at end of file +// #endif diff --git a/test/EventStore.Client.Tests/Interceptors/ReportLeaderInterceptorTests.cs b/test/EventStore.Client.Tests/Interceptors/ReportLeaderInterceptorTests.cs deleted file mode 100644 index 5703c3bd7..000000000 --- a/test/EventStore.Client.Tests/Interceptors/ReportLeaderInterceptorTests.cs +++ /dev/null @@ -1,224 +0,0 @@ -using EventStore.Client.Interceptors; -using Grpc.Core; -using Grpc.Core.Interceptors; - -namespace EventStore.Client.Tests.Interceptors; - -public class ReportLeaderInterceptorTests { - public delegate Task GrpcCall(Interceptor interceptor, Task? response = null); - - static readonly StatusCode[] ForcesRediscoveryStatusCodes = { - //StatusCode.Unknown, TODO: use RPC exceptions on server - StatusCode.Unavailable - }; - - static readonly Marshaller Marshaller = new(_ => Array.Empty(), _ => new()); - - static IEnumerable GrpcCalls() { - yield return MakeUnaryCall; - yield return MakeClientStreamingCall; - yield return MakeDuplexStreamingCall; - yield return MakeServerStreamingCall; - yield return MakeClientStreamingCallForWriting; - yield return MakeDuplexStreamingCallForWriting; - } - - public static IEnumerable ReportsNewLeaderCases() => GrpcCalls().Select(call => new object[] { call }); - - [Theory] - [MemberData(nameof(ReportsNewLeaderCases))] - public async Task ReportsNewLeader(GrpcCall call) { - ReconnectionRequired? actual = default; - - var sut = new ReportLeaderInterceptor(result => actual = result); - - var result = await Assert.ThrowsAsync(() => call(sut, Task.FromException(new NotLeaderException("a.host", 2112)))); - - Assert.Equal(new ReconnectionRequired.NewLeader(result.LeaderEndpoint), actual); - } - - public static IEnumerable ForcesRediscoveryCases() => - from call in GrpcCalls() - from statusCode in ForcesRediscoveryStatusCodes - select new object[] { call, statusCode }; - - [Theory] - [MemberData(nameof(ForcesRediscoveryCases))] - public async Task ForcesRediscovery(GrpcCall call, StatusCode statusCode) { - ReconnectionRequired? actual = default; - - var sut = new ReportLeaderInterceptor(result => actual = result); - - await Assert.ThrowsAsync(() => call(sut, Task.FromException(new RpcException(new(statusCode, "oops"))))); - - Assert.Equal(ReconnectionRequired.Rediscover.Instance, actual); - } - - public static IEnumerable DoesNotForceRediscoveryCases() => - from call in GrpcCalls() - from statusCode in Enum.GetValues(typeof(StatusCode)) - .OfType() - .Except(ForcesRediscoveryStatusCodes) - select new object[] { call, statusCode }; - - [Theory] - [MemberData(nameof(DoesNotForceRediscoveryCases))] - public async Task DoesNotForceRediscovery(GrpcCall call, StatusCode statusCode) { - ReconnectionRequired actual = ReconnectionRequired.None.Instance; - - var sut = new ReportLeaderInterceptor(result => actual = result); - - await Assert.ThrowsAsync(() => call(sut, Task.FromException(new RpcException(new(statusCode, "oops"))))); - - Assert.Equal(ReconnectionRequired.None.Instance, actual); - } - - static async Task MakeUnaryCall(Interceptor interceptor, Task? response = null) { - using var call = interceptor.AsyncUnaryCall( - new(), - CreateClientInterceptorContext(MethodType.Unary), - (_, context) => new( - response ?? Task.FromResult(new object()), - Task.FromResult(context.Options.Headers!), - GetSuccess, - GetTrailers, - OnDispose - ) - ); - - await call.ResponseAsync; - } - - static async Task MakeClientStreamingCall(Interceptor interceptor, Task? response = null) { - using var call = interceptor.AsyncClientStreamingCall( - CreateClientInterceptorContext(MethodType.ClientStreaming), - context => new( - null!, - response ?? Task.FromResult(new object()), - Task.FromResult(context.Options.Headers!), - GetSuccess, - GetTrailers, - OnDispose - ) - ); - - await call.ResponseAsync; - } - - static async Task MakeServerStreamingCall(Interceptor interceptor, Task? response = null) { - using var call = interceptor.AsyncServerStreamingCall( - new(), - CreateClientInterceptorContext(MethodType.ServerStreaming), - (_, context) => new( - new TestAsyncStreamReader(response), - Task.FromResult(context.Options.Headers!), - GetSuccess, - GetTrailers, - OnDispose - ) - ); - - await call.ResponseStream.ReadAllAsync().ToArrayAsync(); - } - - static async Task MakeDuplexStreamingCall(Interceptor interceptor, Task? response = null) { - using var call = interceptor.AsyncDuplexStreamingCall( - CreateClientInterceptorContext(MethodType.ServerStreaming), - context => new( - null!, - new TestAsyncStreamReader(response), - Task.FromResult(context.Options.Headers!), - GetSuccess, - GetTrailers, - OnDispose - ) - ); - - await call.ResponseStream.ReadAllAsync().ToArrayAsync(); - } - - // we might write to the server before listening to its response. if that write fails because - // the server is down then we will never listen to its response, so the failed write should - // trigger rediscovery itself - static async Task MakeClientStreamingCallForWriting(Interceptor interceptor, Task? response = null) { - using var call = interceptor.AsyncClientStreamingCall( - CreateClientInterceptorContext(MethodType.ClientStreaming), - context => new( - new TestAsyncStreamWriter(response), - Task.FromResult(new object()), - Task.FromResult(context.Options.Headers!), - GetSuccess, - GetTrailers, - OnDispose - ) - ); - - await call.RequestStream.WriteAsync(new()); - } - - static async Task MakeDuplexStreamingCallForWriting(Interceptor interceptor, Task? response = null) { - using var call = interceptor.AsyncDuplexStreamingCall( - CreateClientInterceptorContext(MethodType.ServerStreaming), - _ => new( - new TestAsyncStreamWriter(response), - null!, - null!, - GetSuccess, - GetTrailers, - OnDispose - ) - ); - - await call.RequestStream.WriteAsync(new()); - } - - static Status GetSuccess() => Status.DefaultSuccess; - - static Metadata GetTrailers() => Metadata.Empty; - - static void OnDispose() { } - - static ClientInterceptorContext CreateClientInterceptorContext(MethodType methodType) => - new( - new( - methodType, - string.Empty, - string.Empty, - Marshaller, - Marshaller - ), - null, - new(new()) - ); - - class TestAsyncStreamReader : IAsyncStreamReader { - readonly Task _response; - - public TestAsyncStreamReader(Task? response = null) => _response = response ?? Task.FromResult(new object()); - - public Task MoveNext(CancellationToken cancellationToken) => - _response.IsFaulted - ? Task.FromException(_response.Exception!.GetBaseException()) - : Task.FromResult(false); - - public object Current => _response.Result; - } - - class TestAsyncStreamWriter : IClientStreamWriter { - readonly Task _response; - - public TestAsyncStreamWriter(Task? response = null) => _response = response ?? Task.FromResult(new object()); - - public WriteOptions? WriteOptions { - get => throw new NotImplementedException(); - set => throw new NotImplementedException(); - } - - public Task CompleteAsync() => throw new NotImplementedException(); - - public Task WriteAsync(object message) => - _response.IsFaulted - ? Task.FromException(_response.Exception!.GetBaseException()) - : Task.FromResult(false); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.Tests/ListProjectionTests.cs b/test/EventStore.Client.Tests/ListProjectionTests.cs new file mode 100644 index 000000000..d5d673657 --- /dev/null +++ b/test/EventStore.Client.Tests/ListProjectionTests.cs @@ -0,0 +1,43 @@ +// ReSharper disable InconsistentNaming + +using EventStore.Client.Tests.TestNode; + +namespace EventStore.Client.Tests; + +public class ListProjectionTests(ITestOutputHelper output, ListProjectionTests.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [Fact] + public async Task list_all_projections() { + var result = await Fixture.Projections.ListAllAsync(userCredentials: TestCredentials.Root) + .ToArrayAsync(); + + Assert.Equal(result.Select(x => x.Name).OrderBy(x => x), Names.OrderBy(x => x)); + } + + [Fact] + public async Task list_continuous_projections() { + var name = Fixture.GetProjectionName(); + + await Fixture.Projections.CreateContinuousAsync( + name, + "fromAll().when({$init: function (state, ev) {return {};}});", + userCredentials: TestCredentials.Root + ); + + var result = await Fixture.Projections.ListContinuousAsync(userCredentials: TestCredentials.Root) + .ToArrayAsync(); + + Assert.Equal( + result.Select(x => x.Name).OrderBy(x => x), + Names.Concat([name]).OrderBy(x => x) + ); + + Assert.True(result.All(x => x.Mode == "Continuous")); + } + + static readonly string[] Names = ["$streams", "$stream_by_category", "$by_category", "$by_event_type", "$by_correlation_id"]; + + public class CustomFixture : KurrentTemporaryFixture { + public CustomFixture() : base(x => x.RunProjections()) { } + } +} diff --git a/test/EventStore.Client.Tests/NodePreferenceComparerTests.cs b/test/EventStore.Client.Tests/NodePreferenceComparerTests.cs index 1866e3444..abbec81a1 100644 --- a/test/EventStore.Client.Tests/NodePreferenceComparerTests.cs +++ b/test/EventStore.Client.Tests/NodePreferenceComparerTests.cs @@ -56,4 +56,4 @@ internal void ReadOnlyReplicaTests(ClusterMessages.VNodeState expected, params C Assert.Equal(expected, actual); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests/NodeSelectorTests.cs b/test/EventStore.Client.Tests/NodeSelectorTests.cs index 9815305cd..19855b362 100644 --- a/test/EventStore.Client.Tests/NodeSelectorTests.cs +++ b/test/EventStore.Client.Tests/NodeSelectorTests.cs @@ -60,7 +60,7 @@ DnsEndPoint allowedNode Assert.Equal(allowedNode.Port, selectedNode.Port); } - [Fact] + [RetryFact] public void DeadNodesAreNotConsidered() { var allowedNodeId = Uuid.NewUuid(); var allowedNode = new DnsEndPoint(allowedNodeId.ToString(), 2113); @@ -119,4 +119,4 @@ public void CanPrefer(NodePreference nodePreference, string expectedHost) { Assert.Equal(expectedHost, selectedNode.Host); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Operations.Tests/AuthenticationTests.cs b/test/EventStore.Client.Tests/Operations/AuthenticationTests.cs similarity index 64% rename from test/EventStore.Client.Operations.Tests/AuthenticationTests.cs rename to test/EventStore.Client.Tests/Operations/AuthenticationTests.cs index 084a92989..b05bd46ba 100644 --- a/test/EventStore.Client.Operations.Tests/AuthenticationTests.cs +++ b/test/EventStore.Client.Tests/Operations/AuthenticationTests.cs @@ -1,18 +1,15 @@ -namespace EventStore.Client.Operations.Tests; +namespace EventStore.Client.Tests; -public class AuthenticationTests : IClassFixture { - public AuthenticationTests(ITestOutputHelper output, InsecureClientTestFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); - - InsecureClientTestFixture Fixture { get; } - +public class AuthenticationTests(ITestOutputHelper output, AuthenticationTests.CustomFixture fixture) + : EventStorePermanentTests(output, fixture) { public enum CredentialsCase { None, TestUser, RootUser } public static IEnumerable InvalidAuthenticationCases() { - yield return new object?[] { 2, CredentialsCase.TestUser, CredentialsCase.None }; - yield return new object?[] { 3, CredentialsCase.None, CredentialsCase.None }; - yield return new object?[] { 4, CredentialsCase.RootUser, CredentialsCase.TestUser }; - yield return new object?[] { 5, CredentialsCase.TestUser, CredentialsCase.TestUser }; - yield return new object?[] { 6, CredentialsCase.None, CredentialsCase.TestUser }; + yield return [2, CredentialsCase.TestUser, CredentialsCase.None]; + yield return [3, CredentialsCase.None, CredentialsCase.None]; + yield return [4, CredentialsCase.RootUser, CredentialsCase.TestUser]; + yield return [5, CredentialsCase.TestUser, CredentialsCase.TestUser]; + yield return [6, CredentialsCase.None, CredentialsCase.TestUser]; } [Theory] @@ -21,10 +18,10 @@ public async Task system_call_with_invalid_credentials(int caseNr, CredentialsCa await ExecuteTest(caseNr, defaultCredentials, actualCredentials, true); public static IEnumerable ValidAuthenticationCases() { - yield return new object?[] { 1, CredentialsCase.RootUser, CredentialsCase.None }; - yield return new object?[] { 7, CredentialsCase.RootUser, CredentialsCase.RootUser }; - yield return new object?[] { 8, CredentialsCase.TestUser, CredentialsCase.RootUser }; - yield return new object?[] { 9, CredentialsCase.None, CredentialsCase.RootUser }; + yield return [1, CredentialsCase.RootUser, CredentialsCase.None]; + yield return [7, CredentialsCase.RootUser, CredentialsCase.RootUser]; + yield return [8, CredentialsCase.TestUser, CredentialsCase.RootUser]; + yield return [9, CredentialsCase.None, CredentialsCase.RootUser]; } [Theory] @@ -34,7 +31,7 @@ public async Task system_call_with_valid_credentials(int caseNr, CredentialsCase async Task ExecuteTest(int caseNr, CredentialsCase defaultCredentials, CredentialsCase actualCredentials, bool shouldThrow) { var testUser = await Fixture.CreateTestUser(); - + var defaultUserCredentials = GetCredentials(defaultCredentials); var actualUserCredentials = GetCredentials(actualCredentials); @@ -64,4 +61,6 @@ await operations _ => throw new ArgumentOutOfRangeException(nameof(credentialsCase), credentialsCase, null) }; } -} \ No newline at end of file + + public class CustomFixture() : KurrentPermanentFixture(x => x.WithoutDefaultCredentials()); +} diff --git a/test/EventStore.Client.Operations.Tests/MergeIndexesTests.cs b/test/EventStore.Client.Tests/Operations/MergeIndexTests.cs similarity index 50% rename from test/EventStore.Client.Operations.Tests/MergeIndexesTests.cs rename to test/EventStore.Client.Tests/Operations/MergeIndexTests.cs index c4cf7bfb0..9da4fc434 100644 --- a/test/EventStore.Client.Operations.Tests/MergeIndexesTests.cs +++ b/test/EventStore.Client.Tests/Operations/MergeIndexTests.cs @@ -1,20 +1,18 @@ -namespace EventStore.Client.Operations.Tests; +namespace EventStore.Client.Tests; -public class MergeIndexesTests : IClassFixture { - public MergeIndexesTests(ITestOutputHelper output, InsecureClientTestFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - InsecureClientTestFixture Fixture { get; } - - [Fact] +public class MergeIndexTests(ITestOutputHelper output, MergeIndexTests.CustomFixture fixture) + : EventStorePermanentTests(output, fixture) { + [RetryFact] public async Task merge_indexes_does_not_throw() => await Fixture.Operations .MergeIndexesAsync(userCredentials: TestCredentials.Root) .ShouldNotThrowAsync(); - [Fact] + [RetryFact] public async Task merge_indexes_without_credentials_throws() => await Fixture.Operations .MergeIndexesAsync() .ShouldThrowAsync(); -} \ No newline at end of file + + public class CustomFixture() : KurrentPermanentFixture(x => x.WithoutDefaultCredentials()); +} diff --git a/test/EventStore.Client.Tests/Operations/ResignNodeTests.cs b/test/EventStore.Client.Tests/Operations/ResignNodeTests.cs new file mode 100644 index 000000000..b707a41b5 --- /dev/null +++ b/test/EventStore.Client.Tests/Operations/ResignNodeTests.cs @@ -0,0 +1,21 @@ +using EventStore.Client.Tests.TestNode; +using EventStore.Client.Tests; + +namespace EventStore.Client.Tests.Operations; + +public class ResignNodeTests(ITestOutputHelper output, ResignNodeTests.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryFact] + public async Task resign_node_does_not_throw() => + await Fixture.Operations + .ResignNodeAsync(userCredentials: TestCredentials.Root) + .ShouldNotThrowAsync(); + + [RetryFact] + public async Task resign_node_without_credentials_throws() => + await Fixture.Operations + .ResignNodeAsync() + .ShouldThrowAsync(); + + public class CustomFixture() : KurrentTemporaryFixture(x => x.WithoutDefaultCredentials()); +} diff --git a/test/EventStore.Client.Tests/Operations/RestartPersistentSubscriptionsTests.cs b/test/EventStore.Client.Tests/Operations/RestartPersistentSubscriptionsTests.cs new file mode 100644 index 000000000..b14242f80 --- /dev/null +++ b/test/EventStore.Client.Tests/Operations/RestartPersistentSubscriptionsTests.cs @@ -0,0 +1,20 @@ +using EventStore.Client.Tests.TestNode; + +namespace EventStore.Client.Tests.Operations; + +public class RestartPersistentSubscriptionsTests(ITestOutputHelper output, RestartPersistentSubscriptionsTests.NoDefaultCredentialsFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryFact] + public async Task restart_persistent_subscriptions_does_not_throw() => + await Fixture.Operations + .RestartPersistentSubscriptions(userCredentials: TestCredentials.Root) + .ShouldNotThrowAsync(); + + [RetryFact] + public async Task restart_persistent_subscriptions_without_credentials_throws() => + await Fixture.Operations + .RestartPersistentSubscriptions() + .ShouldThrowAsync(); + + public class NoDefaultCredentialsFixture() : KurrentTemporaryFixture(x => x.WithoutDefaultCredentials()); +} diff --git a/test/EventStore.Client.Operations.Tests/ScavengeTests.cs b/test/EventStore.Client.Tests/Operations/ScavengeTests.cs similarity index 79% rename from test/EventStore.Client.Operations.Tests/ScavengeTests.cs rename to test/EventStore.Client.Tests/Operations/ScavengeTests.cs index 35c1b3a1d..39090938b 100644 --- a/test/EventStore.Client.Operations.Tests/ScavengeTests.cs +++ b/test/EventStore.Client.Tests/Operations/ScavengeTests.cs @@ -1,21 +1,18 @@ -namespace EventStore.Client.Operations.Tests; +using EventStore.Client.Tests.TestNode; +using EventStore.Client.Tests; -public class ScavengeTests : IClassFixture { - public class TestFixture() : EventStoreFixture(x => x.WithoutDefaultCredentials().RunInMemory(false)); - - public ScavengeTests(ITestOutputHelper output, TestFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); +namespace EventStore.Client.Tests; - TestFixture Fixture { get; } - - [Fact] +public class ScavengeTests(ITestOutputHelper output, ScavengeTests.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryFact] public async Task start() { var result = await Fixture.Operations.StartScavengeAsync(userCredentials: TestCredentials.Root); - result.ShouldBe(DatabaseScavengeResult.Started(result.ScavengeId)); + result.ScavengeId.ShouldNotBeNullOrEmpty(); } - [Fact] + [RetryFact] public async Task start_without_credentials_throws() => await Fixture.Operations .StartScavengeAsync() @@ -56,10 +53,10 @@ public async Task stop() { stopResult.ShouldBe(DatabaseScavengeResult.Stopped(startResult.ScavengeId)); } - [Fact] + [RetryFact] public async Task stop_when_no_scavenge_is_running() { var scavengeId = Guid.NewGuid().ToString(); - + var ex = await Fixture.Operations .StopScavengeAsync(scavengeId, userCredentials: TestCredentials.Root) .ShouldThrowAsync(); @@ -67,9 +64,11 @@ public async Task stop_when_no_scavenge_is_running() { // ex.ScavengeId.ShouldBeNull(); // it is blowing up because of this } - [Fact] + [RetryFact] public async Task stop_without_credentials_throws() => await Fixture.Operations .StopScavengeAsync(Guid.NewGuid().ToString()) .ShouldThrowAsync(); -} \ No newline at end of file + + public class CustomFixture() : KurrentTemporaryFixture(x => x.WithoutDefaultCredentials()); +} diff --git a/test/EventStore.Client.Tests/Operations/ShutdownNodeAuthenticationTests.cs b/test/EventStore.Client.Tests/Operations/ShutdownNodeAuthenticationTests.cs new file mode 100644 index 000000000..da575c581 --- /dev/null +++ b/test/EventStore.Client.Tests/Operations/ShutdownNodeAuthenticationTests.cs @@ -0,0 +1,13 @@ +using EventStore.Client.Tests.TestNode; +using EventStore.Client.Tests; + +namespace EventStore.Client.Tests; + +public class ShutdownNodeAuthenticationTests(ITestOutputHelper output, ShutdownNodeAuthenticationTests.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryFact] + public async Task shutdown_without_credentials_throws() => + await Fixture.Operations.ShutdownAsync().ShouldThrowAsync(); + + public class CustomFixture() : KurrentTemporaryFixture(x => x.WithoutDefaultCredentials()); +} diff --git a/test/EventStore.Client.Tests/Operations/ShutdownNodeTests.cs b/test/EventStore.Client.Tests/Operations/ShutdownNodeTests.cs new file mode 100644 index 000000000..8680865d2 --- /dev/null +++ b/test/EventStore.Client.Tests/Operations/ShutdownNodeTests.cs @@ -0,0 +1,13 @@ +using EventStore.Client.Tests.TestNode; +using EventStore.Client.Tests; + +namespace EventStore.Client.Tests.Operations; + +public class ShutdownNodeTests(ITestOutputHelper output, ShutdownNodeTests.NoDefaultCredentialsFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryFact] + public async Task shutdown_does_not_throw() => + await Fixture.Operations.ShutdownAsync(userCredentials: TestCredentials.Root).ShouldNotThrowAsync(); + + public class NoDefaultCredentialsFixture() : KurrentTemporaryFixture(x => x.WithoutDefaultCredentials()); +} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/FilterTestCase.cs b/test/EventStore.Client.Tests/PersistentSubscriptions/FilterTestCases.cs similarity index 95% rename from test/EventStore.Client.PersistentSubscriptions.Tests/FilterTestCase.cs rename to test/EventStore.Client.Tests/PersistentSubscriptions/FilterTestCases.cs index 4787105a4..e7a2355e8 100644 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/FilterTestCase.cs +++ b/test/EventStore.Client.Tests/PersistentSubscriptions/FilterTestCases.cs @@ -1,6 +1,6 @@ using System.Reflection; -namespace EventStore.Client.PersistentSubscriptions.Tests; +namespace EventStore.Client.Tests.PersistentSubscriptions; public static class Filters { const string StreamNamePrefix = nameof(StreamNamePrefix); @@ -37,4 +37,4 @@ public static class Filters { public static (Func getFilter, Func prepareEvent) GetFilter(string name) => s_filters[name]; -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllConnectWithoutReadPermissionsTests.cs b/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllConnectWithoutReadPermissionsTests.cs new file mode 100644 index 000000000..d31a6d3f3 --- /dev/null +++ b/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllConnectWithoutReadPermissionsTests.cs @@ -0,0 +1,30 @@ +using EventStore.Client.Tests.TestNode; +using EventStore.Client.Tests; + +namespace EventStore.Client.Tests.PersistentSubscriptions; + +public class SubscribeToAllConnectWithoutReadPermissionsTests(ITestOutputHelper output, KurrentTemporaryFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryFact] + public async Task connect_to_existing_without_read_all_permissions() { + var group = Fixture.GetGroupName(); + var user = Fixture.GetUserCredentials(); + + await Fixture.Subscriptions.CreateToAllAsync(group, new(), userCredentials: TestCredentials.Root); + + await Fixture.Users.CreateUserWithRetry( + user.Username!, + user.Username!, + [], + user.Password!, + TestCredentials.Root + ); + + await Assert.ThrowsAsync( + async () => { + await using var subscription = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: user); + await subscription.Messages.AnyAsync().AsTask().WithTimeout(); + } + ); + } +} diff --git a/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllFilterTests.cs b/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllFilterTests.cs new file mode 100644 index 000000000..b4607e03f --- /dev/null +++ b/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllFilterTests.cs @@ -0,0 +1,129 @@ +using EventStore.Client.Tests.TestNode; +using EventStore.Client.Tests; + +namespace EventStore.Client.Tests.PersistentSubscriptions; + +public class SubscribeToAllFilterTests(ITestOutputHelper output, KurrentTemporaryFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryTheory] + [MemberData(nameof(FilterCases))] + public async Task happy_case_filtered_reads_all_existing_filtered_events(string filterName) { + var streamPrefix = $"{filterName}-{Fixture.GetStreamName()}"; + var group = Fixture.GetGroupName(); + var (getFilter, prepareEvent) = Filters.GetFilter(filterName); + var filter = getFilter(streamPrefix); + + await Fixture.Streams.AppendToStreamAsync( + Guid.NewGuid().ToString(), + StreamState.NoStream, + Fixture.CreateTestEvents(256) + ); + + await Fixture.Streams.SetStreamMetadataAsync( + SystemStreams.AllStream, + StreamState.Any, + new(acl: new(SystemRoles.All)), + userCredentials: TestCredentials.Root + ); + + var appearedEvents = new List(); + var events = Fixture.CreateTestEvents(20).Select(e => prepareEvent(streamPrefix, e)).ToArray(); + + foreach (var e in events) { + await Fixture.Streams.AppendToStreamAsync( + $"{streamPrefix}_{Guid.NewGuid():n}", + StreamState.NoStream, + [e] + ); + } + + await Fixture.Subscriptions.CreateToAllAsync( + group, + filter, + new(startFrom: Position.Start), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + + await subscription.Messages + .OfType() + .Take(events.Length) + .ForEachAwaitAsync( + async e => { + var (resolvedEvent, _) = e; + appearedEvents.Add(resolvedEvent.Event); + await subscription.Ack(resolvedEvent); + } + ) + .WithTimeout(); + + Assert.Equal(events.Select(x => x.EventId), appearedEvents.Select(x => x.EventId)); + } + + [RetryTheory] + [MemberData(nameof(FilterCases))] + public async Task happy_case_filtered_with_start_from_set(string filterName) { + var group = Fixture.GetGroupName(); + var streamPrefix = $"{filterName}-{Fixture.GetStreamName()}"; + var (getFilter, prepareEvent) = Filters.GetFilter(filterName); + var filter = getFilter(streamPrefix); + + var events = Fixture.CreateTestEvents(20).Select(e => prepareEvent(streamPrefix, e)).ToArray(); + var eventsToSkip = events.Take(10).ToArray(); + var eventsToCapture = events.Skip(10).ToArray(); + + IWriteResult? eventToCaptureResult = null; + + await Fixture.Streams.AppendToStreamAsync( + Guid.NewGuid().ToString(), + StreamState.NoStream, + Fixture.CreateTestEvents(256) + ); + + await Fixture.Streams.SetStreamMetadataAsync( + SystemStreams.AllStream, + StreamState.Any, + new(acl: new(SystemRoles.All)), + userCredentials: TestCredentials.Root + ); + + foreach (var e in eventsToSkip) { + await Fixture.Streams.AppendToStreamAsync( + $"{streamPrefix}_{Guid.NewGuid():n}", + StreamState.NoStream, + new[] { e } + ); + } + + foreach (var e in eventsToCapture) { + var result = await Fixture.Streams.AppendToStreamAsync( + $"{streamPrefix}_{Guid.NewGuid():n}", + StreamState.NoStream, + new[] { e } + ); + + eventToCaptureResult ??= result; + } + + await Fixture.Subscriptions.CreateToAllAsync( + group, + filter, + new(startFrom: eventToCaptureResult!.LogPosition), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + + var appearedEvents = await subscription.Messages.OfType() + .Take(10) + .Select(e => e.ResolvedEvent.Event) + .ToArrayAsync() + .AsTask() + .WithTimeout(); + + Assert.Equal(eventsToCapture.Select(x => x.EventId), appearedEvents.Select(x => x.EventId)); + } + + public static IEnumerable FilterCases() => Filters.All.Select(filter => new object[] { filter }); +} diff --git a/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllGetInfoTests.cs b/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllGetInfoTests.cs new file mode 100644 index 000000000..c9f11f171 --- /dev/null +++ b/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllGetInfoTests.cs @@ -0,0 +1,101 @@ +// ReSharper disable InconsistentNaming + +using EventStore.Client.Tests.TestNode; +using EventStore.Client.Tests; + +namespace EventStore.Client.Tests.PersistentSubscriptions; + +public class SubscribeToAllGetInfoTests(SubscribeToAllGetInfoTests.CustomFixture fixture) + : IClassFixture { + static readonly PersistentSubscriptionSettings Settings = new( + resolveLinkTos: true, + startFrom: Position.Start, + extraStatistics: true, + messageTimeout: TimeSpan.FromSeconds(9), + maxRetryCount: 11, + liveBufferSize: 303, + readBatchSize: 30, + historyBufferSize: 909, + checkPointAfter: TimeSpan.FromSeconds(1), + checkPointLowerBound: 1, + checkPointUpperBound: 1, + maxSubscriberCount: 500, + consumerStrategyName: SystemConsumerStrategies.Pinned + ); + + [RetryFact] + public async Task throws_with_non_existing_subscription() { + var group = $"NonExisting-{fixture.GetGroupName()}"; + + await Assert.ThrowsAsync( + async () => await fixture.Subscriptions.GetInfoToAllAsync(group, userCredentials: TestCredentials.Root) + ); + } + + [RetryFact] + public async Task throws_with_no_credentials() { + var group = $"NonExisting-{fixture.GetGroupName()}"; + + await Assert.ThrowsAsync( + async () => + await fixture.Subscriptions.GetInfoToAllAsync(group) + ); + } + + [RetryFact] + public async Task throws_with_non_existing_user() { + var group = $"NonExisting-{fixture.GetGroupName()}"; + + await Assert.ThrowsAsync( + async () => + await fixture.Subscriptions.GetInfoToAllAsync(group, userCredentials: TestCredentials.TestBadUser) + ); + } + + [RetryFact] + public async Task returns_result_with_normal_user_credentials() { + var result = await fixture.Subscriptions.GetInfoToAllAsync(fixture.Group, userCredentials: TestCredentials.Root); + + Assert.Equal("$all", result.EventSource); + } + + public class CustomFixture : KurrentTemporaryFixture { + public string Group { get; } + + public CustomFixture() : base(x => x.WithoutDefaultCredentials()) { + Group = GetGroupName(); + + OnSetup += async () => { + await Subscriptions.CreateToAllAsync(Group, Settings, userCredentials: TestCredentials.Root); + + foreach (var eventData in CreateTestEvents(20)) { + await Streams.AppendToStreamAsync( + $"test-{Guid.NewGuid():n}", + StreamState.NoStream, + [eventData], + userCredentials: TestCredentials.Root + ); + } + + var counter = 0; + + await using var subscription = Subscriptions.SubscribeToAll(Group, userCredentials: TestCredentials.Root); + + var enumerator = subscription.Messages.GetAsyncEnumerator(); + + while (await enumerator.MoveNextAsync()) { + if (enumerator.Current is not PersistentSubscriptionMessage.Event (var resolvedEvent, _)) + continue; + + counter++; + + if (counter == 1) + await subscription.Nack(PersistentSubscriptionNakEventAction.Park, "Test", resolvedEvent); + + if (counter > 10) + return; + } + }; + } + }; +} diff --git a/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllListWithIncorrectCredentialsTests.cs b/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllListWithIncorrectCredentialsTests.cs new file mode 100644 index 000000000..6df8b9d7b --- /dev/null +++ b/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllListWithIncorrectCredentialsTests.cs @@ -0,0 +1,63 @@ +using EventStore.Client.Tests.TestNode; +using EventStore.Client.Tests; + +namespace EventStore.Client.Tests.PersistentSubscriptions; + +public class SubscribeToAllListWithIncorrectCredentialsTests(ITestOutputHelper output, SubscribeToAllListWithIncorrectCredentialsTests.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryFact] + public async Task throws_with_no_credentials() { + var group = Fixture.GetGroupName(); + var stream = Fixture.GetStreamName(); + + const int streamSubscriptionCount = 4; + const int allStreamSubscriptionCount = 3; + + for (var i = 0; i < streamSubscriptionCount; i++) + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group + i, + new(), + userCredentials: TestCredentials.Root + ); + + for (var i = 0; i < allStreamSubscriptionCount; i++) + await Fixture.Subscriptions.CreateToAllAsync( + group + i, + new(), + userCredentials: TestCredentials.Root + ); + + await Assert.ThrowsAsync(async () => await Fixture.Subscriptions.ListToAllAsync()); + } + + [RetryFact] + public async Task throws_with_non_existing_user() { + var group = Fixture.GetGroupName(); + var stream = Fixture.GetStreamName(); + + const int streamSubscriptionCount = 4; + const int allStreamSubscriptionCount = 3; + + for (var i = 0; i < streamSubscriptionCount; i++) + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group + i, + new(), + userCredentials: TestCredentials.Root + ); + + for (var i = 0; i < allStreamSubscriptionCount; i++) + await Fixture.Subscriptions.CreateToAllAsync( + group + i, + new(), + userCredentials: TestCredentials.Root + ); + + await Assert.ThrowsAsync( + async () => await Fixture.Subscriptions.ListToAllAsync(userCredentials: TestCredentials.TestBadUser) + ); + } + + public class CustomFixture() : KurrentTemporaryFixture(x => x.WithoutDefaultCredentials()); +} diff --git a/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllNoDefaultCredentialsTests.cs b/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllNoDefaultCredentialsTests.cs new file mode 100644 index 000000000..d7143d1d2 --- /dev/null +++ b/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllNoDefaultCredentialsTests.cs @@ -0,0 +1,93 @@ +namespace EventStore.Client.Tests.PersistentSubscriptions; + +public class SubscribeToAllNoDefaultCredentialsTests(ITestOutputHelper output, SubscribeToAllNoDefaultCredentialsTests.CustomFixture fixture) + : EventStorePermanentTests(output, fixture) { + [RetryFact] + public async Task connect_to_existing_without_permissions() { + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToAllAsync(group, new(), userCredentials: TestCredentials.Root); + + await Assert.ThrowsAsync( + async () => { + await using var subscription = Fixture.Subscriptions.SubscribeToAll(group); + await subscription.AnyAsync().AsTask().WithTimeout(); + } + ); + } + + [RetryFact] + public async Task throws_persistent_subscription_not_found() { + var group = Fixture.GetGroupName(); + + await using var subscription = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + + Assert.True( + await subscription.Messages.OfType().AnyAsync() + .AsTask() + .WithTimeout() + ); + } + + [RetryFact] + public async Task deleting_without_permissions() { + await Assert.ThrowsAsync(() => Fixture.Subscriptions.DeleteToAllAsync(Guid.NewGuid().ToString())); + } + + [RetryFact] + public async Task create_without_permissions() { + var group = Fixture.GetGroupName(); + + await Assert.ThrowsAsync( + () => + Fixture.Subscriptions.CreateToAllAsync( + group, + new() + ) + ); + } + + [RetryFact] + public async Task update_existing_without_permissions() { + var group = Fixture.GetGroupName(); + await Fixture.Subscriptions.CreateToAllAsync( + group, + new(), + userCredentials: TestCredentials.Root + ); + + await Assert.ThrowsAsync( + () => Fixture.Subscriptions.UpdateToAllAsync( + group, + new() + ) + ); + } + + [RetryFact] + public async Task update_non_existent() { + var group = Fixture.GetGroupName(); + await Assert.ThrowsAsync( + () => Fixture.Subscriptions.UpdateToAllAsync( + group, + new(), + userCredentials: TestCredentials.Root + ) + ); + } + + [RetryFact] + public Task update_with_prepare_position_larger_than_commit_position() { + var group = Fixture.GetGroupName(); + return Assert.ThrowsAsync( + () => + Fixture.Subscriptions.UpdateToAllAsync( + group, + new(startFrom: new Position(0, 1)), + userCredentials: TestCredentials.Root + ) + ); + } + + public class CustomFixture() : KurrentPermanentFixture(x => x.WithoutDefaultCredentials()); +} diff --git a/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllReplayParkedTests.cs b/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllReplayParkedTests.cs new file mode 100644 index 000000000..ca608d092 --- /dev/null +++ b/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllReplayParkedTests.cs @@ -0,0 +1,84 @@ +namespace EventStore.Client.Tests.PersistentSubscriptions; + +public class SubscribeToAllReplayParkedTests(ITestOutputHelper output, SubscribeToAllReplayParkedTests.CustomFixture fixture) + : EventStorePermanentTests(output, fixture) { + [RetryFact] + public async Task does_not_throw() { + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToAllAsync(group, new(), userCredentials: TestCredentials.Root); + + await Fixture.Subscriptions.ReplayParkedMessagesToAllAsync( + group, + userCredentials: TestCredentials.Root + ); + + await Fixture.Subscriptions.ReplayParkedMessagesToAllAsync( + group, + 100, + userCredentials: TestCredentials.Root + ); + } + + [RetryFact] + public async Task throws_when_given_non_existing_subscription() { + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToAllAsync(group, new(), userCredentials: TestCredentials.Root); + + var nonExistingGroup = Fixture.GetGroupName(); + await Assert.ThrowsAsync( + () => + Fixture.Subscriptions.ReplayParkedMessagesToAllAsync( + nonExistingGroup, + userCredentials: TestCredentials.Root + ) + ); + } + + [RetryFact] + public async Task throws_with_no_credentials() { + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToAllAsync(group, new(), userCredentials: TestCredentials.Root); + + await Assert.ThrowsAsync( + () => + Fixture.Subscriptions.ReplayParkedMessagesToAllAsync(group) + ); + } + + [RetryFact] + public async Task throws_with_non_existing_user() { + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToAllAsync(group, new(), userCredentials: TestCredentials.Root); + + await Assert.ThrowsAsync( + () => + Fixture.Subscriptions.ReplayParkedMessagesToAllAsync( + group, + userCredentials: TestCredentials.TestBadUser + ) + ); + } + + [RetryFact] + public async Task throws_with_normal_user_credentials() { + var user = Fixture.GetUserCredentials(); + + await Fixture.Users + .CreateUserWithRetry(user.Username!, user.Username!, [], user.Password!, TestCredentials.Root) + .WithTimeout(); + + await Assert.ThrowsAsync( + () => + Fixture.Subscriptions.ReplayParkedMessagesToAllAsync( + Fixture.GetGroupName(), + userCredentials: user + ) + ); + } + + public class CustomFixture() : KurrentPermanentFixture(x => x.WithoutDefaultCredentials()); +} diff --git a/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllResultWithNormalUserCredentialsTests.cs b/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllResultWithNormalUserCredentialsTests.cs new file mode 100644 index 000000000..906bbde8f --- /dev/null +++ b/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllResultWithNormalUserCredentialsTests.cs @@ -0,0 +1,34 @@ +using EventStore.Client.Tests.TestNode; +using EventStore.Client.Tests; + +namespace EventStore.Client.Tests.PersistentSubscriptions; + +public class SubscribeToAllResultWithNormalUserCredentialsTests(ITestOutputHelper output, KurrentTemporaryFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryFact] + public async Task returns_result_with_normal_user_credentials() { + var group = Fixture.GetGroupName(); + var stream = Fixture.GetStreamName(); + + const int streamSubscriptionCount = 4; + const int allStreamSubscriptionCount = 3; + + for (var i = 0; i < streamSubscriptionCount; i++) + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group + i, + new(), + userCredentials: TestCredentials.Root + ); + + for (var i = 0; i < allStreamSubscriptionCount; i++) + await Fixture.Subscriptions.CreateToAllAsync( + group + i, + new(), + userCredentials: TestCredentials.Root + ); + + var result = await Fixture.Subscriptions.ListToAllAsync(userCredentials: TestCredentials.Root); + Assert.Equal(allStreamSubscriptionCount, result.Count()); + } +} diff --git a/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllReturnsAllSubscriptions.cs b/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllReturnsAllSubscriptions.cs new file mode 100644 index 000000000..e7b542da9 --- /dev/null +++ b/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllReturnsAllSubscriptions.cs @@ -0,0 +1,41 @@ +using EventStore.Client.Tests.TestNode; +using EventStore.Client.Tests; + +namespace EventStore.Client.Tests.PersistentSubscriptions; + +public class SubscribeToAllReturnsAllSubscriptions(ITestOutputHelper output, SubscribeToAllReturnsAllSubscriptions.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryFact] + public async Task returns_all_subscriptions() { + var group = Fixture.GetGroupName(); + var stream = Fixture.GetStreamName(); + + const int streamSubscriptionCount = 4; + const int allStreamSubscriptionCount = 3; + const int totalSubscriptionCount = streamSubscriptionCount + allStreamSubscriptionCount; + + for (var i = 0; i < streamSubscriptionCount; i++) + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group + i, + new(), + userCredentials: TestCredentials.Root + ); + + for (var i = 0; i < allStreamSubscriptionCount; i++) + await Fixture.Subscriptions.CreateToAllAsync( + group + i, + new(), + userCredentials: TestCredentials.Root + ); + + var result = (await Fixture.Subscriptions.ListAllAsync(userCredentials: TestCredentials.Root)).ToList(); + Assert.Equal(totalSubscriptionCount, result.Count); + } + + public class CustomFixture : KurrentTemporaryFixture { + public CustomFixture() { + SkipPsWarmUp = true; + } + } +} diff --git a/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllReturnsSubscriptionsToAllStreamTests.cs b/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllReturnsSubscriptionsToAllStreamTests.cs new file mode 100644 index 000000000..9a5e9c2a1 --- /dev/null +++ b/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllReturnsSubscriptionsToAllStreamTests.cs @@ -0,0 +1,35 @@ +using EventStore.Client.Tests.TestNode; +using EventStore.Client.Tests; + +namespace EventStore.Client.Tests.PersistentSubscriptions; + +public class SubscribeToAllReturnsSubscriptionsToAllStreamTests(ITestOutputHelper output, KurrentTemporaryFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryFact] + public async Task returns_subscriptions_to_all_stream() { + var group = Fixture.GetGroupName(); + var stream = Fixture.GetStreamName(); + + const int streamSubscriptionCount = 4; + const int allStreamSubscriptionCount = 3; + + for (var i = 0; i < streamSubscriptionCount; i++) + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group + i, + new(), + userCredentials: TestCredentials.Root + ); + + for (var i = 0; i < allStreamSubscriptionCount; i++) + await Fixture.Subscriptions.CreateToAllAsync( + group + i, + new(), + userCredentials: TestCredentials.Root + ); + + var result = (await Fixture.Subscriptions.ListToAllAsync(userCredentials: TestCredentials.Root)).ToList(); + Assert.Equal(allStreamSubscriptionCount, result.Count); + Assert.All(result, s => Assert.Equal("$all", s.EventSource)); + } +} diff --git a/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllTests.cs b/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllTests.cs new file mode 100644 index 000000000..1b6e55834 --- /dev/null +++ b/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllTests.cs @@ -0,0 +1,903 @@ +using System.Text; +using Grpc.Core; + +namespace EventStore.Client.Tests.PersistentSubscriptions; + +public class SubscribeToAllTests(ITestOutputHelper output, KurrentPermanentFixture fixture) + : EventStorePermanentTests(output, fixture) { + [RetryFact] + public async Task can_create_duplicate_name_on_different_streams() { + // Arrange + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + // Act + await Fixture.Subscriptions.CreateToAllAsync( + group, + new(), + userCredentials: TestCredentials.Root + ); + + await Fixture.Subscriptions.CreateToStreamAsync(stream, group, new(), userCredentials: TestCredentials.Root); + } + + [RetryFact] + public async Task connect_to_existing_with_max_one_client() { + // Arrange + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToAllAsync(group, new(maxSubscriberCount: 1), userCredentials: TestCredentials.Root); + + var ex = await Assert.ThrowsAsync(() => Task.WhenAll(Subscribe().WithTimeout(), Subscribe().WithTimeout())); + + Assert.Equal(SystemStreams.AllStream, ex.StreamName); + Assert.Equal(group, ex.GroupName); + return; + + async Task Subscribe() { + await using var subscription = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + await subscription.Messages.AnyAsync(); + } + } + + [RetryFact] + public async Task connect_to_existing_with_permissions() { + // Arrange + var group = Fixture.GetGroupName(); + await Fixture.Subscriptions.CreateToAllAsync(group, new(), userCredentials: TestCredentials.Root); + + // Act + await using var subscription = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + + // Assert + subscription.Messages + .FirstAsync().AsTask().WithTimeout() + .GetAwaiter().GetResult() + .ShouldBeOfType(); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_beginning() { + var group = Fixture.GetGroupName(); + + // append 10 events to random streams to make sure we have at least 10 events in the transaction file + foreach (var @event in Fixture.CreateTestEvents(10)) { + await Fixture.Streams.AppendToStreamAsync( + Guid.NewGuid().ToString(), + StreamState.NoStream, + [@event] + ); + } + + var events = await Fixture.Streams + .ReadAllAsync(Direction.Forwards, Position.Start, 10, userCredentials: TestCredentials.Root) + .ToArrayAsync(); + + await Fixture.Subscriptions.CreateToAllAsync(group, new(startFrom: Position.Start), userCredentials: TestCredentials.Root); + + var subscription = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + + var resolvedEvent = await subscription.Messages.OfType() + .Select(e => e.ResolvedEvent) + .FirstOrDefaultAsync().AsTask().WithTimeout(); + + Assert.Equal(events[0].Event.EventId, resolvedEvent.Event.EventId); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_not_set() { + var group = Fixture.GetGroupName(); + var stream = Fixture.GetStreamName(); + + foreach (var @event in Fixture.CreateTestEvents(10)) + await Fixture.Streams.AppendToStreamAsync( + stream, + StreamState.Any, + [@event] + ); + + await Fixture.Subscriptions.CreateToAllAsync(group, new(), userCredentials: TestCredentials.Root); + var subscription = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + + await Assert.ThrowsAsync( + () => subscription!.Messages + .OfType() + .Where(e => !SystemStreams.IsSystemStream(e.ResolvedEvent.OriginalStreamId)) + .AnyAsync() + .AsTask() + .WithTimeout(TimeSpan.FromMilliseconds(250)) + ); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_not_set_then_event_written() { + var group = Fixture.GetGroupName(); + var stream = Fixture.GetStreamName(); + + var expectedStreamId = Guid.NewGuid().ToString(); + var expectedEvent = Fixture.CreateTestEvents(1).First(); + + foreach (var @event in Fixture.CreateTestEvents(10)) { + await Fixture.Streams.AppendToStreamAsync( + stream, + StreamState.Any, + [@event] + ); + } + + await Fixture.Subscriptions.CreateToAllAsync(group, new(), userCredentials: TestCredentials.Root); + var subscription = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + + await Fixture.Streams.AppendToStreamAsync(expectedStreamId, StreamState.NoStream, [expectedEvent]); + + var resolvedEvent = await subscription!.Messages.OfType() + .Select(e => e.ResolvedEvent) + .Where(resolvedEvent => !SystemStreams.IsSystemStream(resolvedEvent.OriginalStreamId)) + .FirstOrDefaultAsync().AsTask().WithTimeout(); + + Assert.Equal(expectedEvent.EventId, resolvedEvent.Event.EventId); + Assert.Equal(expectedStreamId, resolvedEvent.Event.EventStreamId); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_set_to_end_position() { + var group = Fixture.GetGroupName(); + var stream = Fixture.GetStreamName(); + + foreach (var @event in Fixture.CreateTestEvents(10)) { + await Fixture.Streams.AppendToStreamAsync( + stream, + StreamState.Any, + [@event] + ); + } + + await Fixture.Subscriptions.CreateToAllAsync(group, new(startFrom: Position.End), userCredentials: TestCredentials.Root); + + var subscription = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + + await Assert.ThrowsAsync( + () => subscription.Messages + .OfType() + .Where(e => !SystemStreams.IsSystemStream(e.ResolvedEvent.OriginalStreamId)) + .AnyAsync() + .AsTask() + .WithTimeout(TimeSpan.FromMilliseconds(250)) + ); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_set_to_end_position_then_event_written() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + var expectedStreamId = Fixture.GetStreamName(); + var expectedEvent = Fixture.CreateTestEvents().First(); + + foreach (var @event in Fixture.CreateTestEvents(10)) { + await Fixture.Streams.AppendToStreamAsync( + stream, + StreamState.Any, + [@event] + ); + } + + await Fixture.Subscriptions.CreateToAllAsync(group, new(startFrom: Position.End), userCredentials: TestCredentials.Root); + var subscription = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + + await Fixture.Streams.AppendToStreamAsync(expectedStreamId, StreamState.NoStream, [expectedEvent]); + + var resolvedEvent = await subscription!.Messages + .OfType() + .Select(e => e.ResolvedEvent) + .Where(resolvedEvent => !SystemStreams.IsSystemStream(resolvedEvent.OriginalStreamId)) + .FirstAsync() + .AsTask() + .WithTimeout(); + + Assert.Equal(expectedEvent.EventId, resolvedEvent.Event.EventId); + Assert.Equal(expectedStreamId, resolvedEvent.Event.EventStreamId); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_set_to_invalid_middle_position() { + var group = Fixture.GetGroupName(); + + var invalidPosition = new Position(1L, 1L); + await Fixture.Subscriptions.CreateToAllAsync( + group, + new(startFrom: invalidPosition), + userCredentials: TestCredentials.Root + ); + + var subscription = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + var enumerator = subscription.Messages.GetAsyncEnumerator(); + + await enumerator.MoveNextAsync(); + var ex = await Assert.ThrowsAsync( + async () => + await enumerator!.MoveNextAsync() + ); + + Assert.Equal(SystemStreams.AllStream, ex.StreamName); + Assert.Equal(group, ex.GroupName); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_set_to_valid_middle_position() { + var group = Fixture.GetGroupName(); + + var events = await Fixture.Streams + .ReadAllAsync(Direction.Forwards, Position.Start, 10, userCredentials: TestCredentials.Root) + .ToArrayAsync(); + + var expectedEvent = events[events.Length / 2]; //just a random event in the middle of the results + + await Fixture.Subscriptions.CreateToAllAsync( + group, + new(startFrom: expectedEvent.OriginalPosition), + userCredentials: TestCredentials.Root + ); + + var subscription = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + + var resolvedEvent = await subscription!.Messages.OfType() + .Select(e => e.ResolvedEvent) + .FirstAsync() + .AsTask() + .WithTimeout(); + + Assert.Equal(expectedEvent.OriginalPosition, resolvedEvent.Event.Position); + Assert.Equal(expectedEvent.Event.EventId, resolvedEvent.Event.EventId); + Assert.Equal(expectedEvent.Event.EventStreamId, resolvedEvent.Event.EventStreamId); + } + + [RetryFact] + public async Task connect_with_retries() { + // Arrange + var group = Fixture.GetGroupName(); + await Fixture.Subscriptions.CreateToAllAsync(group, new(startFrom: Position.Start), userCredentials: TestCredentials.Root); + + // Act + var subscription = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + var retryCount = await subscription.Messages.OfType() + .SelectAwait( + async e => { + if (e.RetryCount > 4) { + await subscription.Ack(e.ResolvedEvent); + } else { + await subscription.Nack( + PersistentSubscriptionNakEventAction.Retry, + "Not yet tried enough times", + e.ResolvedEvent + ); + } + + return e.RetryCount; + } + ) + .Where(retryCount => retryCount > 4) + .FirstOrDefaultAsync() + .AsTask() + .WithTimeout(); + + // Assert + retryCount.ShouldBe(5); + } + + [RetryFact] + public async Task create_after_deleting_the_same() { + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToAllAsync(group, new(), userCredentials: TestCredentials.Root); + await Fixture.Subscriptions.DeleteToAllAsync(group, userCredentials: TestCredentials.Root); + await Fixture.Subscriptions.CreateToAllAsync(group, new(), userCredentials: TestCredentials.Root); + } + + [RetryFact] + public async Task create_duplicate() { + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToAllAsync( + group, + new(), + userCredentials: TestCredentials.Root + ); + + var ex = await Assert.ThrowsAsync( + () => Fixture.Subscriptions.CreateToAllAsync( + group, + new(), + userCredentials: TestCredentials.Root + ) + ); + + ex.StatusCode.ShouldBe(StatusCode.AlreadyExists); + } + + [RetryFact] + public async Task create_with_commit_position_equal_to_last_indexed_position() { + // Arrange + var group = Fixture.GetGroupName(); + + // Act + var lastEvent = await Fixture.Streams.ReadAllAsync( + Direction.Backwards, + Position.End, + 1, + userCredentials: TestCredentials.Root + ).FirstAsync(); + + var lastCommitPosition = lastEvent.OriginalPosition?.CommitPosition ?? throw new(); + await Fixture.Subscriptions.CreateToAllAsync( + group, + new(startFrom: new Position(lastCommitPosition, lastCommitPosition)), + userCredentials: TestCredentials.Root + ); + } + + [RetryFact] + public Task create_with_prepare_position_larger_than_commit_position() { + var group = Fixture.GetGroupName(); + + return Assert.ThrowsAsync( + () => + Fixture.Subscriptions.CreateToAllAsync( + group, + new(startFrom: new Position(0, 1)), + userCredentials: TestCredentials.Root + ) + ); + } + + [RetryFact] + public async Task deleting_existing_with_subscriber() { + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToAllAsync(group, new(), userCredentials: TestCredentials.Root); + await Fixture.Subscriptions.DeleteToAllAsync(group, userCredentials: TestCredentials.Root); + + await using var subscription = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + + Assert.True( + await subscription.Messages.OfType().AnyAsync() + .AsTask() + .WithTimeout() + ); + } + + [RetryFact] + public async Task deleting_existing_with_permissions() { + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToAllAsync( + group, + new(), + userCredentials: TestCredentials.Root + ); + + await Fixture.Subscriptions.DeleteToAllAsync( + group, + userCredentials: TestCredentials.Root + ); + } + + [RetryFact] + public async Task deleting_filtered() { + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToAllAsync( + group, + EventTypeFilter.Prefix("prefix-filter-"), + new(), + userCredentials: TestCredentials.Root + ); + + await Fixture.Subscriptions.DeleteToAllAsync(group, userCredentials: TestCredentials.Root); + } + + [RetryFact] + public async Task deleting_nonexistent() { + await Assert.ThrowsAsync( + () => Fixture.Subscriptions.DeleteToAllAsync(Guid.NewGuid().ToString(), userCredentials: TestCredentials.Root) + ); + } + + [RetryFact] + public async Task happy_case_catching_up_to_link_to_events_manual_ack() { + var group = Fixture.GetGroupName(); + var bufferCount = 10; + var eventWriteCount = bufferCount * 2; + + var events = Fixture.CreateTestEvents(eventWriteCount) + .Select( + (e, i) => new EventData( + e.EventId, + SystemEventTypes.LinkTo, + Encoding.UTF8.GetBytes($"{i}@test"), + contentType: Constants.Metadata.ContentTypes.ApplicationOctetStream + ) + ) + .ToArray(); + + foreach (var e in events) { + await Fixture.Streams.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.Any, new[] { e }); + } + + await Fixture.Subscriptions.CreateToAllAsync( + group, + new(startFrom: Position.Start, resolveLinkTos: true), + userCredentials: TestCredentials.Root + ); + + var subscription = Fixture.Subscriptions.SubscribeToAll(group, bufferSize: bufferCount, userCredentials: TestCredentials.Root); + await subscription.Messages.OfType() + .Take(events.Length) + .ForEachAwaitAsync(e => subscription.Ack(e.ResolvedEvent)) + .WithTimeout(); + } + + [RetryFact] + public async Task happy_case_catching_up_to_normal_events_manual_ack() { + var group = Fixture.GetGroupName(); + var stream = Fixture.GetStreamName(); + var bufferCount = 10; + var eventWriteCount = bufferCount * 2; + + var events = Fixture.CreateTestEvents(eventWriteCount).ToArray(); + + foreach (var e in events) + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, [e]); + + await Fixture.Subscriptions.CreateToAllAsync( + group, + new(startFrom: Position.Start, resolveLinkTos: true), + userCredentials: TestCredentials.Root + ); + + var subscription = Fixture.Subscriptions.SubscribeToAll(group, bufferSize: bufferCount, userCredentials: TestCredentials.Root); + await subscription!.Messages.OfType() + .Take(events.Length) + .ForEachAwaitAsync(e => subscription.Ack(e.ResolvedEvent)) + .WithTimeout(); + } + + [RetryFact] + public async Task happy_case_writing_and_subscribing_to_normal_events_manual_ack() { + var group = Fixture.GetGroupName(); + var bufferCount = 10; + var eventWriteCount = bufferCount * 2; + + var events = Fixture.CreateTestEvents(eventWriteCount).ToArray(); + + await Fixture.Subscriptions.CreateToAllAsync( + group, + new(startFrom: Position.End, resolveLinkTos: true), + userCredentials: TestCredentials.Root + ); + + var subscription = Fixture.Subscriptions.SubscribeToAll(group, bufferSize: bufferCount, userCredentials: TestCredentials.Root); + foreach (var e in events) { + await Fixture.Streams.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.Any, new[] { e }); + } + + await subscription!.Messages.OfType() + .SelectAwait( + async e => { + await subscription.Ack(e.ResolvedEvent); + return e; + } + ) + .Where(e => e.ResolvedEvent.OriginalStreamId.StartsWith("test-")) + .Take(events.Length) + .ToArrayAsync() + .AsTask() + .WithTimeout(); + } + + [RetryFact] + public async Task update_existing() { + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToAllAsync( + group, + new(), + userCredentials: TestCredentials.Root + ); + + await Fixture.Subscriptions.UpdateToAllAsync( + group, + new(), + userCredentials: TestCredentials.Root + ); + } + + [RetryFact] + public async Task update_existing_filtered() { + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToAllAsync( + group, + EventTypeFilter.Prefix("prefix-filter-"), + new(), + userCredentials: TestCredentials.Root + ); + + await Fixture.Subscriptions.UpdateToAllAsync( + group, + new(true), + userCredentials: TestCredentials.Root + ); + } + + [RetryFact] + public async Task update_existing_with_check_point() { + var group = Fixture.GetGroupName(); + var events = Fixture.CreateTestEvents(5).ToArray(); + var appearedEvents = new List(); + Position checkPoint = default; + + foreach (var e in events) + await Fixture.Streams.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.Any, [e]); + + await Fixture.Subscriptions.CreateToAllAsync( + group, + new(checkPointLowerBound: 5, checkPointAfter: TimeSpan.FromSeconds(1), startFrom: Position.Start), + userCredentials: TestCredentials.Root + ); + + var subscription = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + var enumerator = subscription.Messages.GetAsyncEnumerator(); + await enumerator.MoveNextAsync(); + + await Task.WhenAll(Subscribe().WithTimeout(), WaitForCheckpoint().WithTimeout()); + + // Force restart of the subscription + await Fixture.Subscriptions.UpdateToAllAsync(group, new(), userCredentials: TestCredentials.Root); + + try { + while (await enumerator!.MoveNextAsync()) { } + } catch (PersistentSubscriptionDroppedByServerException) { } + + foreach (var e in events) { + await Fixture.Streams.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.NoStream, new[] { e }); + } + + await using var sub = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + var resumed = await sub.Messages.OfType() + .Select(e => e.ResolvedEvent) + .Take(1) + .FirstAsync() + .AsTask() + .WithTimeout(); + + Assert.True(resumed.Event.Position > checkPoint); + + return; + + async Task Subscribe() { + while (await enumerator.MoveNextAsync()) { + if (enumerator.Current is not PersistentSubscriptionMessage.Event(var resolvedEvent, _)) { + continue; + } + + appearedEvents.Add(resolvedEvent); + await subscription.Ack(resolvedEvent); + if (appearedEvents.Count == events.Length) { + break; + } + } + } + + async Task WaitForCheckpoint() { + await using var subscription = Fixture.Streams.SubscribeToStream( + $"$persistentsubscription-$all::{group}-checkpoint", + FromStream.Start, + userCredentials: TestCredentials.Root + ); + + await foreach (var message in subscription.Messages) { + if (message is not StreamMessage.Event(var resolvedEvent)) { + continue; + } + + checkPoint = resolvedEvent.Event.Data.ParsePosition(); + return; + } + } + } + + [RetryFact] + public async Task update_existing_with_check_point_filtered() { + List appearedEvents = []; + var events = Fixture.CreateTestEvents(5).ToArray(); + var group = Fixture.GetGroupName(); + Position checkPoint = default; + + foreach (var e in events) { + await Fixture.Streams.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.NoStream, [e]); + } + + await Fixture.Subscriptions.CreateToAllAsync( + group, + StreamFilter.Prefix("test"), + new(checkPointLowerBound: 5, checkPointAfter: TimeSpan.FromSeconds(1), startFrom: Position.Start), + userCredentials: TestCredentials.Root + ); + + var subscription = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + var enumerator = subscription.Messages.GetAsyncEnumerator(); + await enumerator.MoveNextAsync(); + + await Task.WhenAll(Subscribe().WithTimeout(), WaitForCheckpoint().WithTimeout()); + + // Force restart of the subscription + await Fixture.Subscriptions.UpdateToAllAsync(group, new(), userCredentials: TestCredentials.Root); + + try { + while (await enumerator.MoveNextAsync()) { } + } catch (PersistentSubscriptionDroppedByServerException) { } + + foreach (var e in events) { + await Fixture.Streams.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.NoStream, [e]); + } + + await using var sub = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + var resumed = await sub.Messages.OfType() + .Select(e => e.ResolvedEvent) + .Take(1) + .FirstAsync() + .AsTask() + .WithTimeout(); + + Assert.True(resumed.Event.Position > checkPoint); + + return; + + async Task Subscribe() { + while (await enumerator.MoveNextAsync()) { + if (enumerator.Current is not PersistentSubscriptionMessage.Event(var resolvedEvent, _)) { + continue; + } + + appearedEvents.Add(resolvedEvent); + await subscription.Ack(resolvedEvent); + if (appearedEvents.Count == events.Length) { + break; + } + } + } + + async Task WaitForCheckpoint() { + await using var subscription = Fixture.Streams.SubscribeToStream( + $"$persistentsubscription-$all::{group}-checkpoint", + FromStream.Start, + userCredentials: TestCredentials.Root + ); + + await foreach (var message in subscription.Messages) { + if (message is not StreamMessage.Event(var resolvedEvent)) { + continue; + } + + checkPoint = resolvedEvent.Event.Data.ParsePosition(); + return; + } + } + } + + [RetryFact] + public async Task update_existing_with_commit_position_equal_to_last_indexed_position() { + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToAllAsync( + group, + new(), + userCredentials: TestCredentials.Root + ); + + var lastEvent = await Fixture.Streams.ReadAllAsync( + Direction.Backwards, + Position.End, + 1, + userCredentials: TestCredentials.Root + ).FirstAsync(); + + var lastCommitPosition = lastEvent.OriginalPosition?.CommitPosition ?? throw new(); + await Fixture.Subscriptions.UpdateToAllAsync( + group, + new(startFrom: new Position(lastCommitPosition, lastCommitPosition)), + userCredentials: TestCredentials.Root + ); + } + + [RetryFact] + public async Task update_existing_with_subscribers() { + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToAllAsync(group, new(startFrom: Position.Start), userCredentials: TestCredentials.Root); + + var subscription = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + + var enumerator = subscription.Messages.GetAsyncEnumerator(); + + await enumerator.MoveNextAsync(); + await Fixture.Subscriptions.UpdateToAllAsync(group, new(), userCredentials: TestCredentials.Root); + var ex = await Assert.ThrowsAsync( + async () => { + while (await enumerator.MoveNextAsync()) { } + } + ).WithTimeout(); + + Assert.Equal(SystemStreams.AllStream, ex.StreamName); + Assert.Equal(group, ex.GroupName); + } + + [RetryFact] + public async Task when_writing_and_filtering_out_events() { + var events = Fixture.CreateTestEvents(10).ToArray(); + var group = Fixture.GetGroupName(); + var prefix = Guid.NewGuid().ToString("N"); + + Position firstCheckPoint = default; + Position secondCheckPoint = default; + List appearedEvents = []; + + foreach (var e in events) + await Fixture.Streams.AppendToStreamAsync(prefix + Guid.NewGuid(), StreamState.Any, [e]); + + await Fixture.Subscriptions.CreateToAllAsync( + group, + StreamFilter.Prefix(prefix), + new( + checkPointLowerBound: 1, + checkPointUpperBound: 5, + checkPointAfter: TimeSpan.FromSeconds(1), + startFrom: Position.Start + ), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + await using var enumerator = subscription.Messages.GetAsyncEnumerator(); + + await Task.WhenAll(Subscribe().WithTimeout(), WaitForCheckpoints().WithTimeout()); + + foreach (var e in events) { + await Fixture.Streams.AppendToStreamAsync( + "filtered-out-stream-" + Guid.NewGuid(), + StreamState.Any, + [e] + ); + } + + Assert.True(secondCheckPoint > firstCheckPoint); + Assert.Equal(events.Select(e => e.EventId), appearedEvents.Select(e => e.Event.EventId)); + + return; + + async Task Subscribe() { + while (await enumerator.MoveNextAsync()) { + if (enumerator.Current is not PersistentSubscriptionMessage.Event(var resolvedEvent, _)) { + continue; + } + + appearedEvents.Add(resolvedEvent); + await subscription.Ack(resolvedEvent); + if (appearedEvents.Count == events.Length) { + break; + } + } + } + + async Task WaitForCheckpoints() { + bool firstCheckpointSet = false; + await using var subscription = Fixture.Streams.SubscribeToStream( + $"$persistentsubscription-$all::{group}-checkpoint", + FromStream.Start, + userCredentials: TestCredentials.Root + ); + + await foreach (var message in subscription.Messages) { + if (message is not StreamMessage.Event(var resolvedEvent)) { + continue; + } + + if (!firstCheckpointSet) { + firstCheckPoint = resolvedEvent.Event.Data.ParsePosition(); + firstCheckpointSet = true; + } else { + secondCheckPoint = resolvedEvent.Event.Data.ParsePosition(); + return; + } + } + } + } + + // [RetryFact] + // public async Task when_writing_and_subscribing_to_normal_events_manual_nack() { + // var group = Fixture.GetGroupName(); + // var bufferCount = 10; + // var eventWriteCount = bufferCount * 2; + // var prefix = $"{Guid.NewGuid():N}-"; + // + // var events = Fixture.CreateTestEvents(eventWriteCount).ToArray(); + // + // await Fixture.Subscriptions.CreateToAllAsync( + // group, + // new(startFrom: Position.Start, resolveLinkTos: true), + // userCredentials: TestCredentials.Root + // ); + // + // var subscription = Fixture.Subscriptions.SubscribeToAll(group, bufferSize: bufferCount, userCredentials: TestCredentials.Root); + // + // foreach (var e in events) + // await Fixture.Streams.AppendToStreamAsync(prefix + Guid.NewGuid(), StreamState.Any, [e]); + // + // await subscription.Messages.OfType() + // .SelectAwait( + // async e => { + // await subscription.Nack(PersistentSubscriptionNakEventAction.Park, "fail", e.ResolvedEvent); + // return e; + // } + // ) + // .Where(e => e.ResolvedEvent.OriginalStreamId.StartsWith(prefix)) + // .Take(events.Length) + // .ToArrayAsync() + // .AsTask() + // .WithTimeout(); + // } + + // [RetryFact] + // public async Task update_existing_with_commit_position_larger_than_last_indexed_position() { + // var group = Fixture.GetGroupName(); + // + // await Fixture.Subscriptions.CreateToAllAsync( + // group, + // new(), + // userCredentials: TestCredentials.Root + // ); + // + // var lastEvent = await Fixture.Streams.ReadAllAsync( + // Direction.Backwards, + // Position.End, + // 1, + // userCredentials: TestCredentials.Root + // ).FirstAsync(); + // + // var lastCommitPosition = lastEvent.OriginalPosition?.CommitPosition ?? throw new(); + // var ex = await Assert.ThrowsAsync( + // () => + // Fixture.Subscriptions.UpdateToAllAsync( + // group, + // new(startFrom: new Position(lastCommitPosition + 1, lastCommitPosition)), + // userCredentials: TestCredentials.Root + // ) + // ); + // + // Assert.Equal(StatusCode.Internal, ex.StatusCode); + // } + + [RetryFact] + public async Task create_with_commit_position_larger_than_last_indexed_position() { + var group = Fixture.GetGroupName(); + + var lastEvent = await Fixture.Streams.ReadAllAsync( + Direction.Backwards, + Position.End, + 1, + userCredentials: TestCredentials.Root + ).FirstAsync(); + + var lastCommitPosition = lastEvent.OriginalPosition?.CommitPosition ?? throw new(); + var ex = await Assert.ThrowsAsync( + () => + Fixture.Subscriptions.CreateToAllAsync( + group, + new(startFrom: new Position(lastCommitPosition + 1, lastCommitPosition)), + userCredentials: TestCredentials.Root + ) + ); + + Assert.Equal(StatusCode.Internal, ex.StatusCode); + } +} diff --git a/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllUpdateExistingWithCheckpointTest.cs b/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllUpdateExistingWithCheckpointTest.cs new file mode 100644 index 000000000..091d55583 --- /dev/null +++ b/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllUpdateExistingWithCheckpointTest.cs @@ -0,0 +1,86 @@ +using EventStore.Client.Tests.TestNode; +using EventStore.Client.Tests; + +namespace EventStore.Client.Tests.PersistentSubscriptions; + +public class SubscribeToAllUpdateExistingWithCheckpointTest(ITestOutputHelper output, KurrentTemporaryFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryFact] + public async Task update_existing_with_check_point_should_resumes_from_check_point() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + StreamPosition checkPoint = default; + + var events = Fixture.CreateTestEvents(5).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(checkPointLowerBound: 5, checkPointAfter: TimeSpan.FromSeconds(1), startFrom: StreamPosition.Start), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream(stream, group, userCredentials: TestCredentials.Root); + + await using var enumerator = subscription.Messages.GetAsyncEnumerator(); + + await enumerator.MoveNextAsync(); + + await Task.WhenAll(Subscribe().WithTimeout(), WaitForCheckpoint().WithTimeout()); + + // Force restart of the subscription + await Fixture.Subscriptions.UpdateToStreamAsync(stream, group, new(), userCredentials: TestCredentials.Root); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, Fixture.CreateTestEvents(1)); + + await using var sub = Fixture.Subscriptions.SubscribeToStream(stream, group, userCredentials: TestCredentials.Root); + + var resolvedEvent = await sub.Messages + .OfType() + .Select(e => e.ResolvedEvent) + .FirstAsync() + .AsTask() + .WithTimeout(); + + Assert.Equal(checkPoint.Next(), resolvedEvent.Event.EventNumber); + + return; + + async Task Subscribe() { + var count = 0; + + while (await enumerator.MoveNextAsync()) { + if (enumerator.Current is not PersistentSubscriptionMessage.Event(var resolvedEvent, _)) { + continue; + } + + count++; + + await subscription.Ack(resolvedEvent); + if (count >= events.Length) { + break; + } + } + } + + async Task WaitForCheckpoint() { + await using var subscription = Fixture.Streams.SubscribeToStream( + $"$persistentsubscription-{stream}::{group}-checkpoint", + FromStream.Start, + userCredentials: TestCredentials.Root + ); + + await foreach (var message in subscription.Messages) { + if (message is not StreamMessage.Event (var resolvedEvent)) { + continue; + } + + checkPoint = resolvedEvent.Event.Data.ParseStreamPosition(); + return; + } + } + } +} diff --git a/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllWithoutPSTests.cs b/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllWithoutPSTests.cs new file mode 100644 index 000000000..4afb8744e --- /dev/null +++ b/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToAllWithoutPSTests.cs @@ -0,0 +1,15 @@ +using EventStore.Client.Tests.TestNode; +using EventStore.Client.Tests; + +namespace EventStore.Client.Tests.PersistentSubscriptions; + +public class SubscribeToAllWithoutPsTests(ITestOutputHelper output, KurrentTemporaryFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryFact] + public async Task list_without_persistent_subscriptions() { + await Assert.ThrowsAsync( + async () => + await Fixture.Subscriptions.ListToAllAsync(userCredentials: TestCredentials.Root) + ); + } +} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/get_info_obsolete.cs b/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToStreamGetInfoTests.cs similarity index 52% rename from test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/get_info_obsolete.cs rename to test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToStreamGetInfoTests.cs index 6f42531fa..941ae6a9a 100644 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/get_info_obsolete.cs +++ b/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToStreamGetInfoTests.cs @@ -1,51 +1,47 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; +// ReSharper disable InconsistentNaming -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class get_info_obsolete : IClassFixture { - const string GroupName = nameof(get_info_obsolete); +using EventStore.Client.Tests.TestNode; +using EventStore.Client.Tests; +namespace EventStore.Client.Tests.PersistentSubscriptions; + +public class SubscribeToStreamGetInfoTests(SubscribeToStreamGetInfoTests.NoDefaultCredentialsFixture fixture) + : IClassFixture { static readonly PersistentSubscriptionSettings Settings = new( - resolveLinkTos: true, - startFrom: Position.Start, - extraStatistics: true, - messageTimeout: TimeSpan.FromSeconds(9), - maxRetryCount: 11, - liveBufferSize: 303, - readBatchSize: 30, - historyBufferSize: 909, - checkPointAfter: TimeSpan.FromSeconds(1), - checkPointLowerBound: 1, - checkPointUpperBound: 1, - maxSubscriberCount: 500, - consumerStrategyName: SystemConsumerStrategies.Pinned + true, + StreamPosition.Start, + true, + TimeSpan.FromSeconds(9), + 11, + 303, + 30, + 909, + TimeSpan.FromSeconds(1), + 1, + 1, + 500, + SystemConsumerStrategies.RoundRobin ); - readonly Fixture _fixture; - - public get_info_obsolete(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task throws_when_not_supported() { - if (SupportsPSToAll.No) - await Assert.ThrowsAsync( - async () => { await _fixture.Client.GetInfoToAllAsync(GroupName, userCredentials: TestCredentials.Root); } - ); + public static IEnumerable AllowedUsers() { + yield return new object[] { TestCredentials.Root }; } - [SupportsPSToAll.Fact] - public async Task returns_expected_result() { - var result = await _fixture.Client.GetInfoToAllAsync(GroupName, userCredentials: TestCredentials.Root); - - Assert.Equal("$all", result.EventSource); - Assert.Equal(GroupName, result.GroupName); - Assert.Equal("Live", result.Status); + [Theory] + [MemberData(nameof(AllowedUsers))] + public async Task returns_expected_result(UserCredentials credentials) { + var result = await fixture.Subscriptions.GetInfoToStreamAsync(fixture.Stream, fixture.Group, userCredentials: credentials); + Assert.Equal(fixture.Stream, result.EventSource); + Assert.Equal(fixture.Group, result.GroupName); Assert.NotNull(Settings.StartFrom); Assert.True(result.Stats.TotalItems > 0); Assert.True(result.Stats.OutstandingMessagesCount > 0); Assert.True(result.Stats.AveragePerSecond >= 0); - Assert.True(result.Stats.ParkedMessageCount > 0); + Assert.True(result.Stats.ParkedMessageCount >= 0); Assert.True(result.Stats.AveragePerSecond >= 0); + Assert.True(result.Stats.ReadBufferCount >= 0); + Assert.True(result.Stats.RetryBufferCount >= 0); Assert.True(result.Stats.CountSinceLastMeasurement >= 0); Assert.True(result.Stats.TotalInFlightMessages >= 0); Assert.NotNull(result.Stats.LastKnownEventPosition); @@ -54,13 +50,12 @@ public async Task returns_expected_result() { Assert.NotNull(result.Connections); Assert.NotEmpty(result.Connections); - var connection = result.Connections.First(); Assert.NotNull(connection.From); Assert.Equal(TestCredentials.Root.Username, connection.Username); Assert.NotEmpty(connection.ConnectionName); Assert.True(connection.AverageItemsPerSecond >= 0); - Assert.True(connection.TotalItems > 0); + Assert.True(connection.TotalItems >= 0); Assert.True(connection.CountSinceLastMeasurement >= 0); Assert.True(connection.AvailableSlots >= 0); Assert.True(connection.InFlightMessages >= 0); @@ -98,86 +93,118 @@ public async Task returns_expected_result() { Assert.Equal(Settings.ConsumerStrategyName, result.Settings!.ConsumerStrategyName); } - [SupportsPSToAll.Fact] - public async Task throws_with_non_existing_subscription() => + [RetryFact] + public async Task throws_when_given_non_existing_subscription() => await Assert.ThrowsAsync( async () => { - await _fixture.Client.GetInfoToAllAsync( + await fixture.Subscriptions.GetInfoToStreamAsync( + "NonExisting", "NonExisting", userCredentials: TestCredentials.Root ); } ); - [SupportsPSToAll.Fact] - public async Task throws_with_no_credentials() => - await Assert.ThrowsAsync(async () => { await _fixture.Client.GetInfoToAllAsync("NonExisting"); }); + [Fact(Skip = "Unable to produce same behavior with HTTP fallback!")] + public async Task throws_with_non_existing_user() { + var group = $"NonExisting-{fixture.GetGroupName()}"; + var stream = $"NonExisting-{fixture.GetStreamName()}"; - [SupportsPSToAll.Fact] - public async Task throws_with_non_existing_user() => await Assert.ThrowsAsync( async () => { - await _fixture.Client.GetInfoToAllAsync( - "NonExisting", + await fixture.Subscriptions.GetInfoToStreamAsync( + stream, + group, userCredentials: TestCredentials.TestBadUser ); } ); + } - [SupportsPSToAll.Fact] - public async Task returns_result_with_normal_user_credentials() { - var result = await _fixture.Client.GetInfoToAllAsync( - GroupName, - userCredentials: TestCredentials.TestUser1 - ); + [RetryFact] + public async Task throws_with_no_credentials() { + var group = $"NonExisting-{fixture.GetGroupName()}"; + var stream = $"NonExisting-{fixture.GetStreamName()}"; - Assert.Equal("$all", result.EventSource); + await Assert.ThrowsAsync( + async () => { + await fixture.Subscriptions.GetInfoToStreamAsync( + stream, + group + ); + } + ); } - void AssertKeyAndValue(IDictionary items, string key) { - Assert.True(items.ContainsKey(key)); - Assert.True(items[key] > 0); + [RetryFact] + public async Task returns_result_for_normal_user() { + var result = await fixture.Subscriptions.GetInfoToStreamAsync( + fixture.Stream, + fixture.Group, + userCredentials: TestCredentials.Root + ); + + Assert.NotNull(result); } - public class Fixture : EventStoreClientFixture { - public Fixture() : base(noDefaultCredentials: true) { } + public class NoDefaultCredentialsFixture : KurrentTemporaryFixture { + public string Group { get; set; } + public string Stream { get; set; } - protected override async Task Given() { - if (SupportsPSToAll.No) - return; + EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription; + IAsyncEnumerator? Enumerator; - await Client.CreateToAllAsync( - GroupName, - get_info_obsolete.Settings, - userCredentials: TestCredentials.Root - ); - } + public NoDefaultCredentialsFixture() : base(x => x.WithoutDefaultCredentials()) { + Group = GetGroupName(); + Stream = GetStreamName(); - protected override async Task When() { - if (SupportsPSToAll.No) - return; + OnSetup += async () => { + await Subscriptions.CreateToStreamAsync( + groupName: Group, + streamName: Stream, + settings: Settings, + userCredentials: TestCredentials.Root + ); - var counter = 0; - var tcs = new TaskCompletionSource(); + var counter = 0; + Subscription = Subscriptions.SubscribeToStream(Stream, Group, userCredentials: TestCredentials.Root); + Enumerator = Subscription.Messages.GetAsyncEnumerator(); + + for (var i = 0; i < 15; i++) { + await Streams.AppendToStreamAsync( + Stream, + StreamState.Any, + [new EventData(Uuid.NewUuid(), "test-event", ReadOnlyMemory.Empty)], + userCredentials: TestCredentials.Root + ); + } + + while (await Enumerator.MoveNextAsync()) { + if (Enumerator.Current is not PersistentSubscriptionMessage.Event(var resolvedEvent, _)) { + continue; + } - await Client.SubscribeToAllAsync( - GroupName, - (s, e, r, ct) => { counter++; - switch (counter) { - case 1: s.Nack(PersistentSubscriptionNakEventAction.Park, "Test", e); - break; - case > 10: - tcs.TrySetResult(); - break; + if (counter == 1) { + await Subscription.Nack(PersistentSubscriptionNakEventAction.Park, "Test", resolvedEvent); + } + + if (counter > 10) { + return; } - return Task.CompletedTask; - }, - userCredentials: TestCredentials.Root - ); + } + }; - await tcs.Task; + OnTearDown += async () => { + if (Enumerator is not null) await Enumerator.DisposeAsync(); + if (Subscription is not null) await Subscription.DisposeAsync(); + }; } + }; + + void AssertKeyAndValue(IDictionary items, string key) { + Assert.True(items.ContainsKey(key)); + Assert.True(items[key] > 0); } } diff --git a/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToStreamListTests.cs b/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToStreamListTests.cs new file mode 100644 index 000000000..bea57c9ab --- /dev/null +++ b/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToStreamListTests.cs @@ -0,0 +1,44 @@ +namespace EventStore.Client.Tests.PersistentSubscriptions; + +public class SubscribeToStreamListTests(ITestOutputHelper output, SubscribeToStreamListTests.CustomFixture fixture) + : EventStorePermanentTests(output, fixture) { + [RetryFact] + public async Task throws_with_no_credentials() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + const int streamSubscriptionCount = 4; + + for (var i = 0; i < streamSubscriptionCount; i++) + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group + i, + new(), + userCredentials: TestCredentials.Root + ); + + await Assert.ThrowsAsync(async () => await Fixture.Subscriptions.ListToStreamAsync(stream)); + } + + [RetryFact] + public async Task throws_with_non_existing_user() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + const int streamSubscriptionCount = 4; + + for (var i = 0; i < streamSubscriptionCount; i++) + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group + i, + new(), + userCredentials: TestCredentials.Root + ); + + await Assert.ThrowsAsync( + async () => await Fixture.Subscriptions.ListToStreamAsync(stream, userCredentials: TestCredentials.TestBadUser) + ); + } + + public class CustomFixture() : KurrentPermanentFixture(x => x.WithoutDefaultCredentials()); +} diff --git a/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToStreamNoDefaultCredentialsTests.cs b/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToStreamNoDefaultCredentialsTests.cs new file mode 100644 index 000000000..3a473b58e --- /dev/null +++ b/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToStreamNoDefaultCredentialsTests.cs @@ -0,0 +1,77 @@ +namespace EventStore.Client.Tests.PersistentSubscriptions; + +public class SubscribeToStreamNoDefaultCredentialsTests(ITestOutputHelper output, SubscribeToStreamNoDefaultCredentialsTests.CustomFixture fixture) + : EventStorePermanentTests(output, fixture) { + [RetryFact] + public async Task connect_to_existing_without_permissions() { + var group = Fixture.GetGroupName(); + var stream = Fixture.GetStreamName(); + + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(), + userCredentials: TestCredentials.Root + ); + + await Assert.ThrowsAsync( + async () => { + await using var subscription = Fixture.Subscriptions.SubscribeToStream(stream, group); + await subscription.Messages.AnyAsync(); + } + ).WithTimeout(); + } + + [RetryFact] + public async Task create_without_permissions() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Assert.ThrowsAsync( + () => + Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new() + ) + ); + } + + [RetryFact] + public async Task deleting_without_permissions() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Assert.ThrowsAsync(() => Fixture.Subscriptions.DeleteToStreamAsync(stream, group)); + } + + [RetryFact] + public async Task update_existing_without_permissions() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Fixture.Streams.AppendToStreamAsync( + stream, + StreamState.NoStream, + Fixture.CreateTestEvents(), + userCredentials: TestCredentials.Root + ); + + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(), + userCredentials: TestCredentials.Root + ); + + await Assert.ThrowsAsync( + () => Fixture.Subscriptions.UpdateToStreamAsync( + stream, + group, + new() + ) + ); + } + + public class CustomFixture() : KurrentPermanentFixture(x => x.WithoutDefaultCredentials()); +} diff --git a/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToStreamReplayParkedTests.cs b/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToStreamReplayParkedTests.cs new file mode 100644 index 000000000..384cc8dfb --- /dev/null +++ b/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToStreamReplayParkedTests.cs @@ -0,0 +1,68 @@ +namespace EventStore.Client.Tests.PersistentSubscriptions; + +public class SubscribeToStreamReplayParkedTests(ITestOutputHelper output, SubscribeToStreamReplayParkedTests.CustomFixture fixture) + : EventStorePermanentTests(output, fixture) { + [RetryFact] + public async Task does_not_throw() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToStreamAsync(stream, group, new(), userCredentials: TestCredentials.Root); + + await Fixture.Subscriptions.ReplayParkedMessagesToStreamAsync( + stream, + group, + userCredentials: TestCredentials.Root + ); + + await Fixture.Subscriptions.ReplayParkedMessagesToStreamAsync( + stream, + group, + 100, + userCredentials: TestCredentials.Root + ); + } + + [RetryFact] + public async Task throws_with_no_credentials() { + var group = Fixture.GetGroupName(); + var stream = Fixture.GetStreamName(); + + await Fixture.Subscriptions.CreateToStreamAsync(stream, group, new(), userCredentials: TestCredentials.Root); + + await Assert.ThrowsAsync( + () => + Fixture.Subscriptions.ReplayParkedMessagesToStreamAsync(stream, group) + ); + } + + [Fact(Skip = "Unable to produce same behavior with HTTP fallback!")] + public async Task throws_with_non_existing_user() { + var group = Fixture.GetGroupName(); + var stream = Fixture.GetStreamName(); + + await Fixture.Subscriptions.CreateToStreamAsync(stream, group, new(), userCredentials: TestCredentials.Root); + + await Assert.ThrowsAsync( + () => Fixture.Subscriptions.ReplayParkedMessagesToStreamAsync(stream, group, userCredentials: TestCredentials.TestBadUser) + ); + } + + [RetryFact] + public async Task throws_with_normal_user_credentials() { + var group = Fixture.GetGroupName(); + var stream = Fixture.GetStreamName(); + var user = Fixture.GetUserCredentials(); + + await Fixture.Users + .CreateUserWithRetry(user.Username!, user.Username!, [], user.Password!, TestCredentials.Root) + .WithTimeout(); + + await Assert.ThrowsAsync( + () => + Fixture.Subscriptions.ReplayParkedMessagesToStreamAsync(stream, group, userCredentials: user) + ); + } + + public class CustomFixture() : KurrentPermanentFixture(x => x.WithoutDefaultCredentials()); +} diff --git a/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToStreamTests.cs b/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToStreamTests.cs new file mode 100644 index 000000000..f9cdb68d4 --- /dev/null +++ b/test/EventStore.Client.Tests/PersistentSubscriptions/SubscribeToStreamTests.cs @@ -0,0 +1,743 @@ +using System.Text; +using Grpc.Core; + +namespace EventStore.Client.Tests.PersistentSubscriptions; + +public class SubscribeToStreamTests(ITestOutputHelper output, KurrentPermanentFixture fixture) + : EventStorePermanentTests(output, fixture) { + [RetryFact] + public async Task can_create_duplicate_name_on_different_streams() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(), + userCredentials: TestCredentials.Root + ); + + await Fixture.Subscriptions.CreateToStreamAsync( + "someother" + stream, + group, + new(), + userCredentials: TestCredentials.Root + ); + } + + [RetryFact] + public async Task connect_to_existing_with_max_one_client() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(maxSubscriberCount: 1), + userCredentials: TestCredentials.Root + ); + + var ex = await Assert.ThrowsAsync(() => Task.WhenAll(Subscribe().WithTimeout(), Subscribe().WithTimeout())); + + Assert.Equal(stream, ex.StreamName); + Assert.Equal(group, ex.GroupName); + return; + + async Task Subscribe() { + await using var subscription = Fixture.Subscriptions.SubscribeToStream(stream, group, userCredentials: TestCredentials.Root); + await subscription.Messages.AnyAsync(); + } + } + + [RetryFact] + public async Task connect_to_existing_with_permissions() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToStreamAsync(stream, group, new(), userCredentials: TestCredentials.Root); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream(stream, group, userCredentials: TestCredentials.Root); + + Assert.True(await subscription.Messages.FirstAsync().AsTask().WithTimeout() is PersistentSubscriptionMessage.SubscriptionConfirmation); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_beginning_and_events_in_it() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + var events = Fixture.CreateTestEvents(10).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(startFrom: StreamPosition.Start), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream(stream, group, userCredentials: TestCredentials.Root); + var resolvedEvent = await subscription.Messages.OfType() + .Select(e => e.ResolvedEvent) + .FirstOrDefaultAsync().AsTask().WithTimeout(); + + Assert.Equal(StreamPosition.Start, resolvedEvent.Event.EventNumber); + Assert.Equal(events[0].EventId, resolvedEvent.Event.EventId); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_beginning_and_no_stream() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + var events = Fixture.CreateTestEvents().ToArray(); + var eventId = events.Single().EventId; + + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream(stream, group, userCredentials: TestCredentials.Root); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + + var resolvedEvent = await subscription!.Messages.OfType() + .Select(e => e.ResolvedEvent) + .FirstOrDefaultAsync().AsTask().WithTimeout(); + + Assert.Equal(StreamPosition.Start, resolvedEvent.Event.EventNumber); + Assert.Equal(eventId, resolvedEvent.Event.EventId); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_beginning_and_no_streamconnect_to_existing_with_start_from_not_set_and_events_in_it() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + var events = Fixture.CreateTestEvents(10).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream( + stream, + group, + userCredentials: TestCredentials.Root + ); + + await Assert.ThrowsAsync( + () => subscription.Messages.AnyAsync(message => message is PersistentSubscriptionMessage.Event).AsTask().WithTimeout(TimeSpan.FromMilliseconds(250)) + ); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_not_set_and_events_in_it_then_event_written() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + var events = Fixture.CreateTestEvents(11).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(10)); + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream( + stream, + group, + userCredentials: TestCredentials.Root + ); + + await Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(9), events.Skip(10)); + + var resolvedEvent = await subscription.Messages.OfType() + .Select(e => e.ResolvedEvent) + .FirstOrDefaultAsync().AsTask().WithTimeout(); + + Assert.Equal(new(10), resolvedEvent.Event.EventNumber); + Assert.Equal(events.Last().EventId, resolvedEvent.Event.EventId); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_set_to_end_position_and_events_in_it() { + var events = Fixture.CreateTestEvents(10).ToArray(); + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(startFrom: StreamPosition.End), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream( + stream, + group, + userCredentials: TestCredentials.Root + ); + + await Assert.ThrowsAsync( + () => subscription.Messages.AnyAsync(message => message is PersistentSubscriptionMessage.Event).AsTask().WithTimeout(TimeSpan.FromMilliseconds(250)) + ); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_then_event_written() { + var events = Fixture.CreateTestEvents(11).ToArray(); + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(10)); + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(startFrom: StreamPosition.End), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream(stream, group, userCredentials: TestCredentials.TestUser1); + + await Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(9), events.Skip(10)); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_two_and_no_stream() { + var events = Fixture.CreateTestEvents(3).ToArray(); + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + var eventId = events.Last().EventId; + + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(startFrom: new StreamPosition(2)), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream( + stream, + group, + userCredentials: TestCredentials.Root + ); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + + var resolvedEvent = await subscription.Messages.OfType() + .Select(e => e.ResolvedEvent) + .FirstOrDefaultAsync().AsTask().WithTimeout(); + + Assert.Equal(new(2), resolvedEvent.Event.EventNumber); + Assert.Equal(eventId, resolvedEvent.Event.EventId); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_x_set_and_events_in_it() { + var events = Fixture.CreateTestEvents(10).ToArray(); + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(10)); + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(startFrom: new StreamPosition(4)), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream( + stream, + group, + userCredentials: TestCredentials.Root + ); + + await Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(9), events.Skip(10)); + + var resolvedEvent = await subscription.Messages + .OfType() + .Select(e => e.ResolvedEvent) + .FirstOrDefaultAsync().AsTask().WithTimeout(); + + Assert.Equal(new(4), resolvedEvent.Event.EventNumber); + Assert.Equal(events.Skip(4).First().EventId, resolvedEvent.Event.EventId); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_x_set_and_events_in_it_then_event_written() { + var events = Fixture.CreateTestEvents(11).ToArray(); + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(10)); + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(startFrom: new StreamPosition(10)), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream( + stream, + group, + userCredentials: TestCredentials.Root + ); + + await Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(9), events.Skip(10)); + + var resolvedEvent = await subscription.Messages.OfType() + .Select(e => e.ResolvedEvent) + .FirstOrDefaultAsync().AsTask().WithTimeout(); + + Assert.Equal(new(10), resolvedEvent.Event.EventNumber); + Assert.Equal(events.Last().EventId, resolvedEvent.Event.EventId); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_x_set_higher_than_x_and_events_in_it_then_event_written() { + var events = Fixture.CreateTestEvents(12).ToArray(); + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(11)); + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(startFrom: new StreamPosition(11)), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream( + stream, + group, + userCredentials: TestCredentials.Root + ); + + await Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(10), events.Skip(11)); + + var resolvedEvent = await subscription.Messages.OfType() + .Select(e => e.ResolvedEvent) + .FirstOrDefaultAsync().AsTask().WithTimeout(); + + Assert.Equal(new(11), resolvedEvent.Event.EventNumber); + Assert.Equal(events.Last().EventId, resolvedEvent.Event.EventId); + } + + [RetryFact] + public async Task connect_to_non_existing_with_permissions() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream(stream, group, userCredentials: TestCredentials.Root); + Assert.True( + await subscription.Messages.OfType() + .AnyAsync() + .AsTask() + .WithTimeout() + ); + } + + [RetryFact] + public async Task connect_with_retries() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + var events = Fixture.CreateTestEvents().ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(startFrom: StreamPosition.Start), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream(stream, group, userCredentials: TestCredentials.Root); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + var retryCount = await subscription.Messages.OfType() + .SelectAwait( + async e => { + if (e.RetryCount > 4) { + await subscription.Ack(e.ResolvedEvent); + } else { + await subscription.Nack( + PersistentSubscriptionNakEventAction.Retry, + "Not yet tried enough times", + e.ResolvedEvent + ); + } + + return e.RetryCount; + } + ) + .Where(retryCount => retryCount > 4) + .FirstOrDefaultAsync() + .AsTask() + .WithTimeout(); + + Assert.Equal(5, retryCount); + } + + [RetryFact] + public async Task connecting_to_a_persistent_subscription() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + var events = Fixture.CreateTestEvents(12).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(11)); + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(startFrom: new StreamPosition(11)), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream(stream, group, userCredentials: TestCredentials.Root); + + await Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(10), events.Skip(11)); + + var resolvedEvent = await subscription.Messages.OfType() + .Select(e => e.ResolvedEvent) + .FirstOrDefaultAsync().AsTask().WithTimeout(); + + Assert.Equal(new(11), resolvedEvent.Event.EventNumber); + Assert.Equal(events.Last().EventId, resolvedEvent.Event.EventId); + } + + [RetryFact] + public async Task create_after_deleting_the_same() { + var stream = Fixture.GetStreamName(); + var group = $"existing-{Fixture.GetGroupName()}"; + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, Fixture.CreateTestEvents()); + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(), + userCredentials: TestCredentials.Root + ); + + await Fixture.Subscriptions.DeleteToStreamAsync( + stream, + group, + userCredentials: TestCredentials.Root + ); + } + + [RetryFact] + public async Task create_duplicate() { + var stream = Fixture.GetStreamName(); + var group = $"duplicate-{Fixture.GetGroupName()}"; + + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(), + userCredentials: TestCredentials.Root + ); + + var ex = await Assert.ThrowsAsync( + () => Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(), + userCredentials: TestCredentials.Root + ) + ); + + Assert.Equal(StatusCode.AlreadyExists, ex.StatusCode); + } + + [RetryFact] + public async Task create_on_existing_stream() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, Fixture.CreateTestEvents()); + + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(), + userCredentials: TestCredentials.Root + ); + } + + [RetryFact] + public async Task create_on_non_existing_stream() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(), + userCredentials: TestCredentials.Root + ); + } + + [RetryFact] + public async Task create_with_dont_timeout() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(messageTimeout: TimeSpan.Zero), + userCredentials: TestCredentials.Root + ); + } + + [RetryFact] + public async Task deleting_existing_with_permissions() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToStreamAsync(stream, group, new(), userCredentials: TestCredentials.Root); + await Fixture.Subscriptions.DeleteToStreamAsync(stream, group, userCredentials: TestCredentials.Root); + } + + [RetryFact] + public async Task deleting_existing_with_subscriber() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToStreamAsync(stream, group, new(), userCredentials: TestCredentials.Root); + + await Fixture.Subscriptions.DeleteToStreamAsync(stream, group, userCredentials: TestCredentials.Root); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream(stream, group, userCredentials: TestCredentials.Root); + + Assert.True( + await subscription.Messages.OfType().AnyAsync() + .AsTask() + .WithTimeout() + ); + } + + [RetryFact] + public async Task deleting_nonexistent() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Assert.ThrowsAsync( + () => Fixture.Subscriptions.DeleteToStreamAsync(stream, group, userCredentials: TestCredentials.Root) + ); + } + + [RetryFact] + public async Task happy_case_catching_up_to_link_to_events_manual_ack() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + const int bufferCount = 10; + const int eventWriteCount = bufferCount * 2; + + var events = Fixture.CreateTestEvents(eventWriteCount) + .Select( + (e, i) => new EventData( + e.EventId, + SystemEventTypes.LinkTo, + Encoding.UTF8.GetBytes($"{i}@{stream}"), + contentType: Constants.Metadata.ContentTypes.ApplicationOctetStream + ) + ).ToArray(); + + foreach (var e in events) + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, [e]); + + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(startFrom: StreamPosition.Start, resolveLinkTos: true), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream( + stream, + group, + bufferSize: bufferCount, + userCredentials: TestCredentials.Root + ); + + await subscription!.Messages.OfType() + .Take(events.Length) + .ForEachAwaitAsync(e => subscription.Ack(e.ResolvedEvent)) + .WithTimeout(); + } + + [RetryFact] + public async Task happy_case_catching_up_to_normal_events_manual_ack() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + const int bufferCount = 10; + const int eventWriteCount = bufferCount * 2; + + var events = Fixture.CreateTestEvents(eventWriteCount).ToArray(); + + foreach (var e in events) + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, new[] { e }); + + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(startFrom: StreamPosition.Start, resolveLinkTos: true), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream( + stream, + group, + bufferSize: bufferCount, + userCredentials: TestCredentials.Root + ); + + await subscription!.Messages.OfType() + .Take(events.Length) + .ForEachAwaitAsync(e => subscription.Ack(e.ResolvedEvent)) + .WithTimeout(); + } + + [RetryFact] + public async Task happy_case_writing_and_subscribing_to_normal_events_manual_ack() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + const int bufferCount = 10; + const int eventWriteCount = bufferCount * 2; + + var events = Fixture.CreateTestEvents(eventWriteCount).ToArray(); + + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(startFrom: StreamPosition.End, resolveLinkTos: true), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream( + stream, + group, + bufferSize: bufferCount, + userCredentials: TestCredentials.Root + ); + + foreach (var e in events) + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, [e]); + + await subscription.Messages.OfType() + .Take(events.Length) + .ForEachAwaitAsync(e => subscription.Ack(e.ResolvedEvent)) + .WithTimeout(); + } + + [RetryFact] + public async Task list_without_persistent_subscriptions_should_throw() { + var stream = Fixture.GetStreamName(); + + await Assert.ThrowsAsync( + async () => + await Fixture.Subscriptions.ListToStreamAsync(stream, userCredentials: TestCredentials.Root) + ); + } + + [RetryFact] + public async Task update_existing() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents()); + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(), + userCredentials: TestCredentials.Root + ); + + await Fixture.Subscriptions.UpdateToStreamAsync(stream, group, new(), userCredentials: TestCredentials.Root); + } + + [RetryFact] + public async Task update_existing_with_subscribers() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents()); + await Fixture.Subscriptions.CreateToStreamAsync(stream, group, new(), userCredentials: TestCredentials.Root); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream(stream, group, userCredentials: TestCredentials.Root); + await using var enumerator = subscription.Messages.GetAsyncEnumerator(); + + await enumerator.MoveNextAsync(); + + await Fixture.Subscriptions.UpdateToStreamAsync(stream, group, new(), userCredentials: TestCredentials.Root); + + var ex = await Assert.ThrowsAsync( + async () => { + while (await enumerator.MoveNextAsync()) { } + } + ).WithTimeout(); + + Assert.Equal(stream, ex.StreamName); + Assert.Equal(group, ex.GroupName); + } + + [Regression.Fact(21, "20.x returns the wrong exception")] + public async Task update_non_existent() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Assert.ThrowsAsync( + () => Fixture.Subscriptions.UpdateToStreamAsync( + stream, + group, + new(), + userCredentials: TestCredentials.Root + ) + ); + } + + [RetryFact] + public async Task when_writing_and_subscribing_to_normal_events_manual_nack() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + const int bufferCount = 10; + const int eventWriteCount = bufferCount * 2; + + var events = Fixture.CreateTestEvents(eventWriteCount).ToArray(); + + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(startFrom: StreamPosition.Start, resolveLinkTos: true), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream(stream, group, bufferSize: bufferCount, userCredentials: TestCredentials.Root); + + foreach (var e in events) + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, [e]); + + await subscription.Messages.OfType() + .Take(1) + .ForEachAwaitAsync( + async message => + await subscription.Nack( + PersistentSubscriptionNakEventAction.Park, + "fail", + message.ResolvedEvent + ) + ) + .WithTimeout(); + } +} diff --git a/test/EventStore.Client.Tests/PositionTests.cs b/test/EventStore.Client.Tests/PositionTests.cs index b68748af8..b9657a2c5 100644 --- a/test/EventStore.Client.Tests/PositionTests.cs +++ b/test/EventStore.Client.Tests/PositionTests.cs @@ -5,7 +5,7 @@ namespace EventStore.Client.Tests; public class PositionTests : ValueObjectTests { public PositionTests() : base(new ScenarioFixture()) { } - [Fact] + [RetryFact] public void IsComparable() => Assert.IsAssignableFrom>(_fixture.Create()); [Theory] @@ -16,7 +16,7 @@ public PositionTests() : base(new ScenarioFixture()) { } [AutoScenarioData(typeof(ScenarioFixture))] public void LiveIsGreaterThanAll(Position other) => Assert.True(Position.End > other); - [Fact] + [RetryFact] public void ToStringReturnsExpectedResult() { var sut = _fixture.Create(); Assert.Equal($"C:{sut.CommitPosition}/P:{sut.PreparePosition}", sut.ToString()); @@ -60,4 +60,4 @@ public void TryParse(string s, bool success, Position? expected) { class ScenarioFixture : Fixture { public ScenarioFixture() => Customize(composer => composer.FromFactory(value => new(value, value))); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests/PrefixFilterExpressionTests.cs b/test/EventStore.Client.Tests/PrefixFilterExpressionTests.cs deleted file mode 100644 index ae2cbdcd6..000000000 --- a/test/EventStore.Client.Tests/PrefixFilterExpressionTests.cs +++ /dev/null @@ -1,11 +0,0 @@ -using AutoFixture; - -namespace EventStore.Client.Tests; - -public class PrefixFilterExpressionTests : ValueObjectTests { - public PrefixFilterExpressionTests() : base(new ScenarioFixture()) { } - - class ScenarioFixture : Fixture { - public ScenarioFixture() => Customize(composer => composer.FromFactory(value => new(value))); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.Tests/ProjectionManagementTests.cs b/test/EventStore.Client.Tests/ProjectionManagementTests.cs new file mode 100644 index 000000000..e119ff3cd --- /dev/null +++ b/test/EventStore.Client.Tests/ProjectionManagementTests.cs @@ -0,0 +1,205 @@ +// ReSharper disable InconsistentNaming +// ReSharper disable ClassNeverInstantiated.Local + +using EventStore.Client.Tests.TestNode; +using EventStore.Client.Tests; + +namespace EventStore.Client.Tests; + +public class ProjectionManagementTests(ITestOutputHelper output, ProjectionManagementTests.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [Fact] + public async Task status_is_aborted() { + var name = Names.First(); + await Fixture.Projections.AbortAsync(name, userCredentials: TestCredentials.Root); + var result = await Fixture.Projections.GetStatusAsync(name, userCredentials: TestCredentials.Root); + Assert.NotNull(result); + Assert.Contains(["Aborted/Stopped", "Stopped"], x => x == result.Status); + } + + [Fact] + public async Task one_time() => + await Fixture.Projections.CreateOneTimeAsync("fromAll().when({$init: function (state, ev) {return {};}});", userCredentials: TestCredentials.Root); + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task continuous(bool trackEmittedStreams) { + var name = Fixture.GetProjectionName(); + + await Fixture.Projections.CreateContinuousAsync( + name, + "fromAll().when({$init: function (state, ev) {return {};}});", + trackEmittedStreams, + userCredentials: TestCredentials.Root + ); + } + + [Fact] + public async Task transient() { + var name = Fixture.GetProjectionName(); + + await Fixture.Projections.CreateTransientAsync( + name, + "fromAll().when({$init: function (state, ev) {return {};}});", + userCredentials: TestCredentials.Root + ); + } + + [Fact] + public async Task disable_projection() { + var name = Names.First(); + await Fixture.Projections.DisableAsync(name, userCredentials: TestCredentials.Root); + var result = await Fixture.Projections.GetStatusAsync(name, userCredentials: TestCredentials.Root); + Assert.NotNull(result); + Assert.Contains(["Aborted/Stopped", "Stopped"], x => x == result!.Status); + } + + [Fact] + public async Task enable_projection() { + var name = Names.First(); + await Fixture.Projections.EnableAsync(name, userCredentials: TestCredentials.Root); + var result = await Fixture.Projections.GetStatusAsync(name, userCredentials: TestCredentials.Root); + Assert.NotNull(result); + Assert.Equal("Running", result.Status); + } + + [Fact] + public async Task get_result() { + var name = Fixture.GetProjectionName(); + Result? result = null; + + var projection = $$""" + fromStream('{{name}}').when({ + "$init": function() { return { Count: 0 }; }, + "$any": function(s, e) { s.Count++; return s; } + }); + """; + + await Fixture.Projections.CreateContinuousAsync( + name, + projection, + userCredentials: TestCredentials.Root + ); + + await Fixture.Streams.AppendToStreamAsync( + name, + StreamState.NoStream, + Fixture.CreateTestEvents() + ); + + await AssertEx.IsOrBecomesTrue( + async () => { + result = await Fixture.Projections.GetResultAsync(name, userCredentials: TestCredentials.Root); + return result.Count > 0; + } + ); + + Assert.NotNull(result); + Assert.Equal(1, result!.Count); + } + + [Fact] + public async Task get_state() { + var name = Fixture.GetProjectionName(); + + var projection = $$""" + fromStream('{{name}}').when({ + "$init": function() { return { Count: 0 }; }, + "$any": function(s, e) { s.Count++; return s; } + }); + """; + + Result? result = null; + + await Fixture.Projections.CreateContinuousAsync( + name, + projection, + userCredentials: TestCredentials.Root + ); + + await Fixture.Streams.AppendToStreamAsync( + name, + StreamState.NoStream, + Fixture.CreateTestEvents() + ); + + await AssertEx.IsOrBecomesTrue( + async () => { + result = await Fixture.Projections.GetStateAsync(name, userCredentials: TestCredentials.Root); + return result.Count > 0; + } + ); + + Assert.NotNull(result); + Assert.Equal(1, result!.Count); + } + + [Fact] + public async Task get_status() { + var name = Names.First(); + var result = await Fixture.Projections.GetStatusAsync(name, userCredentials: TestCredentials.Root); + + Assert.NotNull(result); + Assert.Equal(name, result.Name); + } + + [Fact] + public async Task restart_subsystem_does_not_throw() => + await Fixture.Projections.RestartSubsystemAsync(userCredentials: TestCredentials.Root); + + [Fact] + public async Task restart_subsystem_throws_when_given_no_credentials() => + await Assert.ThrowsAsync(() => Fixture.Projections.RestartSubsystemAsync(userCredentials: TestCredentials.TestUser1)); + + [Theory] + [InlineData(true)] + [InlineData(false)] + [InlineData(null)] + public async Task update_projection(bool? emitEnabled) { + var name = Fixture.GetProjectionName(); + await Fixture.Projections.CreateContinuousAsync( + name, + "fromAll().when({$init: function (state, ev) {return {};}});", + userCredentials: TestCredentials.Root + ); + + await Fixture.Projections.UpdateAsync( + name, + "fromAll().when({$init: function (s, e) {return {};}});", + emitEnabled, + userCredentials: TestCredentials.Root + ); + } + + [Fact] + public async Task list_one_time_projections() { + await Fixture.Projections.CreateOneTimeAsync("fromAll().when({$init: function (state, ev) {return {};}});", userCredentials: TestCredentials.Root); + + var result = await Fixture.Projections.ListOneTimeAsync(userCredentials: TestCredentials.Root) + .ToArrayAsync(); + + var details = Assert.Single(result); + Assert.Equal("OneTime", details.Mode); + } + + [Fact] + public async Task reset_projection() { + var name = Names.First(); + await Fixture.Projections.ResetAsync(name, userCredentials: TestCredentials.Root); + var result = await Fixture.Projections.GetStatusAsync(name, userCredentials: TestCredentials.Root); + + Assert.NotNull(result); + Assert.Equal("Running", result.Status); + } + + static readonly string[] Names = ["$streams", "$stream_by_category", "$by_category", "$by_event_type", "$by_correlation_id"]; + + record Result { + public int Count { get; set; } + } + + public class CustomFixture : KurrentTemporaryFixture { + public CustomFixture() : base(x => x.RunProjections()) { } + } +} diff --git a/test/EventStore.Client.Tests/RegularFilterExpressionTests.cs b/test/EventStore.Client.Tests/RegularFilterExpressionTests.cs index 481e5cb46..67bd40039 100644 --- a/test/EventStore.Client.Tests/RegularFilterExpressionTests.cs +++ b/test/EventStore.Client.Tests/RegularFilterExpressionTests.cs @@ -9,4 +9,4 @@ public RegularFilterExpressionTests() : base(new ScenarioFixture()) { } class ScenarioFixture : Fixture { public ScenarioFixture() => Customize(composer => composer.FromFactory(value => new(value))); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Streams.Tests/Security/all_stream_with_no_acl_security.cs b/test/EventStore.Client.Tests/Security/AllStreamWithNoAclSecurityTests.cs similarity index 90% rename from test/EventStore.Client.Streams.Tests/Security/all_stream_with_no_acl_security.cs rename to test/EventStore.Client.Tests/Security/AllStreamWithNoAclSecurityTests.cs index 215e0f05d..b404c7357 100644 --- a/test/EventStore.Client.Streams.Tests/Security/all_stream_with_no_acl_security.cs +++ b/test/EventStore.Client.Tests/Security/AllStreamWithNoAclSecurityTests.cs @@ -1,7 +1,11 @@ -namespace EventStore.Client.Streams.Tests; +using EventStore.Client.Tests.TestNode; +using EventStore.Client.Tests; + +namespace EventStore.Client.Tests; [Trait("Category", "Security")] -public class all_stream_with_no_acl_security(ITestOutputHelper output, all_stream_with_no_acl_security.CustomFixture fixture) : EventStoreTests(output, fixture) { +public class AllStreamWithNoAclSecurityTests(ITestOutputHelper output, AllStreamWithNoAclSecurityTests.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { [Fact] public async Task write_to_all_is_never_allowed() { await Assert.ThrowsAsync(() => Fixture.AppendStream(SecurityFixture.AllStream)); @@ -59,4 +63,4 @@ protected override async Task Given() { await Streams.SetStreamMetadataAsync(AllStream, StreamState.Any, new(), userCredentials: TestCredentials.Root); } } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Streams.Tests/Security/delete_stream_security.cs b/test/EventStore.Client.Tests/Security/DeleteStreamSecurityTests.cs similarity index 87% rename from test/EventStore.Client.Streams.Tests/Security/delete_stream_security.cs rename to test/EventStore.Client.Tests/Security/DeleteStreamSecurityTests.cs index 61e6253ce..7e661bf9f 100644 --- a/test/EventStore.Client.Streams.Tests/Security/delete_stream_security.cs +++ b/test/EventStore.Client.Tests/Security/DeleteStreamSecurityTests.cs @@ -1,7 +1,10 @@ -namespace EventStore.Client.Streams.Tests; +using EventStore.Client.Tests.TestNode; +using EventStore.Client.Tests; + +namespace EventStore.Client.Tests; [Trait("Category", "Security")] -public class delete_stream_security(ITestOutputHelper output, SecurityFixture fixture) : EventStoreTests(output, fixture) { +public class DeleteStreamSecurityTests(ITestOutputHelper output, SecurityFixture fixture) : KurrentTemporaryTests(output, fixture) { [Fact] public async Task delete_of_all_is_never_allowed() { await Assert.ThrowsAsync(() => Fixture.DeleteStream(SecurityFixture.AllStream)); @@ -113,7 +116,7 @@ public async Task deleting_normal_all_stream_with_admin_user_is_allowed() { public async Task deleting_system_no_acl_stream_with_no_user_is_not_allowed() { var streamId = await Fixture.CreateStreamWithMeta( streamId: $"${Fixture.GetStreamName()}", - metadata: new() + metadataPermanent: new() ); await Assert.ThrowsAsync(() => Fixture.DeleteStream(streamId)); @@ -123,7 +126,7 @@ public async Task deleting_system_no_acl_stream_with_no_user_is_not_allowed() { public async Task deleting_system_no_acl_stream_with_existing_user_is_not_allowed() { var streamId = await Fixture.CreateStreamWithMeta( streamId: $"${Fixture.GetStreamName()}", - metadata: new() + metadataPermanent: new() ); await Assert.ThrowsAsync(() => Fixture.DeleteStream(streamId, TestCredentials.TestUser1)); @@ -133,7 +136,7 @@ public async Task deleting_system_no_acl_stream_with_existing_user_is_not_allowe public async Task deleting_system_no_acl_stream_with_admin_user_is_allowed() { var streamId = await Fixture.CreateStreamWithMeta( streamId: $"${Fixture.GetStreamName()}", - metadata: new() + metadataPermanent: new() ); await Fixture.DeleteStream(streamId, TestCredentials.TestAdmin); @@ -143,7 +146,7 @@ public async Task deleting_system_no_acl_stream_with_admin_user_is_allowed() { public async Task deleting_system_user_stream_with_no_user_is_not_allowed() { var streamId = await Fixture.CreateStreamWithMeta( streamId: $"${Fixture.GetStreamName()}", - metadata: new(acl: new(deleteRole: TestCredentials.TestUser1.Username)) + metadataPermanent: new(acl: new(deleteRole: TestCredentials.TestUser1.Username)) ); await Assert.ThrowsAsync(() => Fixture.DeleteStream(streamId)); @@ -153,7 +156,7 @@ public async Task deleting_system_user_stream_with_no_user_is_not_allowed() { public async Task deleting_system_user_stream_with_not_authorized_user_is_not_allowed() { var streamId = await Fixture.CreateStreamWithMeta( streamId: $"${Fixture.GetStreamName()}", - metadata: new(acl: new(deleteRole: TestCredentials.TestUser1.Username)) + metadataPermanent: new(acl: new(deleteRole: TestCredentials.TestUser1.Username)) ); await Assert.ThrowsAsync(() => Fixture.DeleteStream(streamId, TestCredentials.TestUser2)); @@ -163,7 +166,7 @@ public async Task deleting_system_user_stream_with_not_authorized_user_is_not_al public async Task deleting_system_user_stream_with_authorized_user_is_allowed() { var streamId = await Fixture.CreateStreamWithMeta( streamId: $"${Fixture.GetStreamName()}", - metadata: new(acl: new(deleteRole: TestCredentials.TestUser1.Username)) + metadataPermanent: new(acl: new(deleteRole: TestCredentials.TestUser1.Username)) ); await Fixture.DeleteStream(streamId, TestCredentials.TestUser1); @@ -173,7 +176,7 @@ public async Task deleting_system_user_stream_with_authorized_user_is_allowed() public async Task deleting_system_user_stream_with_admin_user_is_allowed() { var streamId = await Fixture.CreateStreamWithMeta( streamId: $"${Fixture.GetStreamName()}", - metadata: new(acl: new(deleteRole: TestCredentials.TestUser1.Username)) + metadataPermanent: new(acl: new(deleteRole: TestCredentials.TestUser1.Username)) ); await Fixture.DeleteStream(streamId, TestCredentials.TestAdmin); @@ -183,7 +186,7 @@ public async Task deleting_system_user_stream_with_admin_user_is_allowed() { public async Task deleting_system_admin_stream_with_no_user_is_not_allowed() { var streamId = await Fixture.CreateStreamWithMeta( streamId: $"${Fixture.GetStreamName()}", - metadata: new(acl: new(deleteRole: SystemRoles.Admins)) + metadataPermanent: new(acl: new(deleteRole: SystemRoles.Admins)) ); await Assert.ThrowsAsync(() => Fixture.DeleteStream(streamId)); @@ -193,7 +196,7 @@ public async Task deleting_system_admin_stream_with_no_user_is_not_allowed() { public async Task deleting_system_admin_stream_with_existing_user_is_not_allowed() { var streamId = await Fixture.CreateStreamWithMeta( streamId: $"${Fixture.GetStreamName()}", - metadata: new(acl: new(deleteRole: SystemRoles.Admins)) + metadataPermanent: new(acl: new(deleteRole: SystemRoles.Admins)) ); await Assert.ThrowsAsync(() => Fixture.DeleteStream(streamId, TestCredentials.TestUser1)); @@ -203,7 +206,7 @@ public async Task deleting_system_admin_stream_with_existing_user_is_not_allowed public async Task deleting_system_admin_stream_with_admin_user_is_allowed() { var streamId = await Fixture.CreateStreamWithMeta( streamId: $"${Fixture.GetStreamName()}", - metadata: new(acl: new(deleteRole: SystemRoles.Admins)) + metadataPermanent: new(acl: new(deleteRole: SystemRoles.Admins)) ); await Fixture.DeleteStream(streamId, TestCredentials.TestAdmin); @@ -213,7 +216,7 @@ public async Task deleting_system_admin_stream_with_admin_user_is_allowed() { public async Task deleting_system_all_stream_with_no_user_is_allowed() { var streamId = await Fixture.CreateStreamWithMeta( streamId: $"${Fixture.GetStreamName()}", - metadata: new(acl: new(deleteRole: SystemRoles.All)) + metadataPermanent: new(acl: new(deleteRole: SystemRoles.All)) ); await Fixture.DeleteStream(streamId); @@ -223,7 +226,7 @@ public async Task deleting_system_all_stream_with_no_user_is_allowed() { public async Task deleting_system_all_stream_with_existing_user_is_allowed() { var streamId = await Fixture.CreateStreamWithMeta( streamId: $"${Fixture.GetStreamName()}", - metadata: new(acl: new(deleteRole: SystemRoles.All)) + metadataPermanent: new(acl: new(deleteRole: SystemRoles.All)) ); await Fixture.DeleteStream(streamId, TestCredentials.TestUser1); @@ -233,9 +236,9 @@ public async Task deleting_system_all_stream_with_existing_user_is_allowed() { public async Task deleting_system_all_stream_with_admin_user_is_allowed() { var streamId = await Fixture.CreateStreamWithMeta( streamId: $"${Fixture.GetStreamName()}", - metadata: new(acl: new(deleteRole: SystemRoles.All)) + metadataPermanent: new(acl: new(deleteRole: SystemRoles.All)) ); await Fixture.DeleteStream(streamId, TestCredentials.TestAdmin); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Streams.Tests/Security/multiple_role_security.cs b/test/EventStore.Client.Tests/Security/MultipleRoleSecurityTests.cs similarity index 83% rename from test/EventStore.Client.Streams.Tests/Security/multiple_role_security.cs rename to test/EventStore.Client.Tests/Security/MultipleRoleSecurityTests.cs index 3195c22df..3a5a0c78a 100644 --- a/test/EventStore.Client.Streams.Tests/Security/multiple_role_security.cs +++ b/test/EventStore.Client.Tests/Security/MultipleRoleSecurityTests.cs @@ -1,7 +1,11 @@ -namespace EventStore.Client.Streams.Tests; +using EventStore.Client.Tests.TestNode; +using EventStore.Client.Tests; + +namespace EventStore.Client.Tests; [Trait("Category", "Security")] -public class multiple_role_security(ITestOutputHelper output, multiple_role_security.CustomFixture fixture) : EventStoreTests(output, fixture) { +public class MultipleRoleSecurityTests(ITestOutputHelper output, MultipleRoleSecurityTests.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { [Fact] public async Task multiple_roles_are_handled_correctly() { await Assert.ThrowsAsync(() => Fixture.ReadEvent("usr-stream")); @@ -20,7 +24,7 @@ public async Task multiple_roles_are_handled_correctly() { } [AnonymousAccess.Fact] - public async Task multiple_roles_are_handled_correctly_without_authentication() => + public async Task multiple_roles_are_handled_correctly_without_authentication() => await Fixture.DeleteStream("usr-stream1"); public class CustomFixture : SecurityFixture { @@ -36,4 +40,4 @@ protected override async Task When() { await Streams.SetSystemSettingsAsync(settings, userCredentials: TestCredentials.TestAdmin); } } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Streams.Tests/Security/overriden_system_stream_security_for_all.cs b/test/EventStore.Client.Tests/Security/OverridenSystemStreamSecurityForAllTests.cs similarity index 86% rename from test/EventStore.Client.Streams.Tests/Security/overriden_system_stream_security_for_all.cs rename to test/EventStore.Client.Tests/Security/OverridenSystemStreamSecurityForAllTests.cs index 2364717bb..dd4057df0 100644 --- a/test/EventStore.Client.Streams.Tests/Security/overriden_system_stream_security_for_all.cs +++ b/test/EventStore.Client.Tests/Security/OverridenSystemStreamSecurityForAllTests.cs @@ -1,7 +1,11 @@ -namespace EventStore.Client.Streams.Tests; +using EventStore.Client.Tests.TestNode; +using EventStore.Client.Tests; + +namespace EventStore.Client.Tests; [Trait("Category", "Security")] -public class overriden_system_stream_security_for_all(ITestOutputHelper output, overriden_system_stream_security_for_all.CustomFixture fixture) : EventStoreTests(output, fixture) { +public class OverridenSystemStreamSecurityForAllTests(ITestOutputHelper output, OverridenSystemStreamSecurityForAllTests.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { [Fact] public async Task operations_on_system_stream_succeeds_for_user() { var stream = $"${Fixture.GetStreamName()}"; diff --git a/test/EventStore.Client.Streams.Tests/Security/overriden_system_stream_security.cs b/test/EventStore.Client.Tests/Security/OverridenSystemStreamSecurityTests.cs similarity index 91% rename from test/EventStore.Client.Streams.Tests/Security/overriden_system_stream_security.cs rename to test/EventStore.Client.Tests/Security/OverridenSystemStreamSecurityTests.cs index fcdaec541..deedbb33d 100644 --- a/test/EventStore.Client.Streams.Tests/Security/overriden_system_stream_security.cs +++ b/test/EventStore.Client.Tests/Security/OverridenSystemStreamSecurityTests.cs @@ -1,7 +1,11 @@ -namespace EventStore.Client.Streams.Tests; +using EventStore.Client.Tests.TestNode; +using EventStore.Client.Tests; + +namespace EventStore.Client.Tests; [Trait("Category", "Security")] -public class overriden_system_stream_security(ITestOutputHelper output, overriden_system_stream_security.CustomFixture fixture) : EventStoreTests(output, fixture) { +public class OverridenSystemStreamSecurityTests(ITestOutputHelper output, OverridenSystemStreamSecurityTests.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { [Fact] public async Task operations_on_system_stream_succeed_for_authorized_user() { var stream = $"${Fixture.GetStreamName()}"; diff --git a/test/EventStore.Client.Streams.Tests/Security/overriden_user_stream_security.cs b/test/EventStore.Client.Tests/Security/OverridenUserStreamSecurityTests.cs similarity index 91% rename from test/EventStore.Client.Streams.Tests/Security/overriden_user_stream_security.cs rename to test/EventStore.Client.Tests/Security/OverridenUserStreamSecurityTests.cs index 287d5a64f..f5da17028 100644 --- a/test/EventStore.Client.Streams.Tests/Security/overriden_user_stream_security.cs +++ b/test/EventStore.Client.Tests/Security/OverridenUserStreamSecurityTests.cs @@ -1,7 +1,11 @@ -namespace EventStore.Client.Streams.Tests; +using EventStore.Client.Tests.TestNode; +using EventStore.Client.Tests; + +namespace EventStore.Client.Tests; [Trait("Category", "Security")] -public class overriden_user_stream_security(ITestOutputHelper output, overriden_user_stream_security.CustomFixture fixture) : EventStoreTests(output, fixture) { +public class OverridenUserStreamSecurityTests(ITestOutputHelper output, OverridenUserStreamSecurityTests.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { [Fact] public async Task operations_on_user_stream_succeeds_for_authorized_user() { var stream = Fixture.GetStreamName(); diff --git a/test/EventStore.Client.Streams.Tests/Security/read_all_security.cs b/test/EventStore.Client.Tests/Security/ReadAllSecurityTests.cs similarity index 83% rename from test/EventStore.Client.Streams.Tests/Security/read_all_security.cs rename to test/EventStore.Client.Tests/Security/ReadAllSecurityTests.cs index 01089db2e..b1a88b7a4 100644 --- a/test/EventStore.Client.Streams.Tests/Security/read_all_security.cs +++ b/test/EventStore.Client.Tests/Security/ReadAllSecurityTests.cs @@ -1,7 +1,10 @@ -namespace EventStore.Client.Streams.Tests; +using EventStore.Client.Tests.TestNode; +using EventStore.Client.Tests; + +namespace EventStore.Client.Tests; [Trait("Category", "Security")] -public class read_all_security(ITestOutputHelper output, SecurityFixture fixture) : EventStoreTests(output, fixture) { +public class ReadAllSecurityTests(ITestOutputHelper output, SecurityFixture fixture) : KurrentTemporaryTests(output, fixture) { [Fact] public async Task reading_all_with_not_existing_credentials_is_not_authenticated() { await Assert.ThrowsAsync(() => Fixture.ReadAllForward(TestCredentials.TestBadUser)); @@ -31,4 +34,4 @@ public async Task reading_all_with_admin_credentials_succeeds() { await Fixture.ReadAllForward(TestCredentials.TestAdmin); await Fixture.ReadAllBackward(TestCredentials.TestAdmin); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Streams.Tests/Security/read_stream_meta_security.cs b/test/EventStore.Client.Tests/Security/ReadStreamMetaSecurityTests.cs similarity index 74% rename from test/EventStore.Client.Streams.Tests/Security/read_stream_meta_security.cs rename to test/EventStore.Client.Tests/Security/ReadStreamMetaSecurityTests.cs index b3a7e7afa..b3c966977 100644 --- a/test/EventStore.Client.Streams.Tests/Security/read_stream_meta_security.cs +++ b/test/EventStore.Client.Tests/Security/ReadStreamMetaSecurityTests.cs @@ -1,12 +1,13 @@ -namespace EventStore.Client.Streams.Tests; +using EventStore.Client.Tests.TestNode; +using EventStore.Client.Tests; + +namespace EventStore.Client.Tests; [Trait("Category", "Security")] -public class read_stream_meta_security(ITestOutputHelper output, SecurityFixture fixture) : EventStoreTests(output, fixture) { +public class ReadStreamMetaSecurityTests(ITestOutputHelper output, SecurityFixture fixture) : KurrentTemporaryTests(output, fixture) { [Fact] public async Task reading_stream_meta_with_not_existing_credentials_is_not_authenticated() => - await Assert.ThrowsAsync( - () => Fixture.ReadMeta(SecurityFixture.MetaReadStream, TestCredentials.TestBadUser) - ); + await Assert.ThrowsAsync(() => Fixture.ReadMeta(SecurityFixture.MetaReadStream, TestCredentials.TestBadUser)); [Fact] public async Task reading_stream_meta_with_no_credentials_is_denied() => @@ -14,9 +15,7 @@ public async Task reading_stream_meta_with_no_credentials_is_denied() => [Fact] public async Task reading_stream_meta_with_not_authorized_user_credentials_is_denied() => - await Assert.ThrowsAsync( - () => Fixture.ReadMeta(SecurityFixture.MetaReadStream, TestCredentials.TestUser2) - ); + await Assert.ThrowsAsync(() => Fixture.ReadMeta(SecurityFixture.MetaReadStream, TestCredentials.TestUser2)); [Fact] public async Task reading_stream_meta_with_authorized_user_credentials_succeeds() => @@ -31,9 +30,7 @@ public async Task reading_stream_meta_with_admin_user_credentials_succeeds() => [Fact] public async Task reading_no_acl_stream_meta_is_not_authenticated_when_not_existing_credentials_are_passed() => - await Assert.ThrowsAsync( - () => Fixture.ReadMeta(SecurityFixture.NoAclStream, TestCredentials.TestBadUser) - ); + await Assert.ThrowsAsync(() => Fixture.ReadMeta(SecurityFixture.NoAclStream, TestCredentials.TestBadUser)); [Fact] public async Task reading_no_acl_stream_meta_succeeds_when_any_existing_user_credentials_are_passed() { @@ -52,9 +49,7 @@ public async Task reading_all_access_normal_stream_meta_succeeds_when_no_credent [Fact] public async Task reading_all_access_normal_stream_meta_is_not_authenticated_when_not_existing_credentials_are_passed() => - await Assert.ThrowsAsync( - () => Fixture.ReadMeta(SecurityFixture.NormalAllStream, TestCredentials.TestBadUser) - ); + await Assert.ThrowsAsync(() => Fixture.ReadMeta(SecurityFixture.NormalAllStream, TestCredentials.TestBadUser)); [Fact] public async Task @@ -66,4 +61,4 @@ public async Task [Fact] public async Task reading_all_access_normal_stream_meta_succeeds_when_admin_user_credentials_are_passed() => await Fixture.ReadMeta(SecurityFixture.NormalAllStream, TestCredentials.TestAdmin); -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Streams.Tests/Security/read_stream_security.cs b/test/EventStore.Client.Tests/Security/ReadStreamSecurityTests.cs similarity index 96% rename from test/EventStore.Client.Streams.Tests/Security/read_stream_security.cs rename to test/EventStore.Client.Tests/Security/ReadStreamSecurityTests.cs index 206627128..a26d7e797 100644 --- a/test/EventStore.Client.Streams.Tests/Security/read_stream_security.cs +++ b/test/EventStore.Client.Tests/Security/ReadStreamSecurityTests.cs @@ -1,7 +1,10 @@ -namespace EventStore.Client.Streams.Tests; +using EventStore.Client.Tests.TestNode; +using EventStore.Client.Tests; + +namespace EventStore.Client.Tests; [Trait("Category", "Security")] -public class read_stream_security(ITestOutputHelper output, SecurityFixture fixture) : EventStoreTests(output, fixture) { +public class ReadStreamSecurityTests(ITestOutputHelper output, SecurityFixture fixture) : KurrentTemporaryTests(output, fixture) { [Fact] public async Task reading_stream_with_not_existing_credentials_is_not_authenticated() { await Assert.ThrowsAsync(() => Fixture.ReadEvent(SecurityFixture.ReadStream, TestCredentials.TestBadUser)); @@ -26,7 +29,7 @@ public async Task reading_stream_with_not_authorized_user_credentials_is_denied( [Fact] public async Task reading_stream_with_authorized_user_credentials_succeeds() { await Fixture.AppendStream(SecurityFixture.ReadStream, TestCredentials.TestUser1); - + await Fixture.ReadEvent(SecurityFixture.ReadStream, TestCredentials.TestUser1); await Fixture.ReadStreamForward(SecurityFixture.ReadStream, TestCredentials.TestUser1); await Fixture.ReadStreamBackward(SecurityFixture.ReadStream, TestCredentials.TestUser1); @@ -110,4 +113,4 @@ public async Task reading_all_access_normal_stream_succeeds_when_admin_user_cred await Fixture.ReadStreamForward(SecurityFixture.NormalAllStream, TestCredentials.TestAdmin); await Fixture.ReadStreamBackward(SecurityFixture.NormalAllStream, TestCredentials.TestAdmin); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Streams.Tests/Security/SecurityFixture.cs b/test/EventStore.Client.Tests/Security/SecurityFixture.cs similarity index 97% rename from test/EventStore.Client.Streams.Tests/Security/SecurityFixture.cs rename to test/EventStore.Client.Tests/Security/SecurityFixture.cs index 2ffc0b73c..43edb97b6 100644 --- a/test/EventStore.Client.Streams.Tests/Security/SecurityFixture.cs +++ b/test/EventStore.Client.Tests/Security/SecurityFixture.cs @@ -1,8 +1,9 @@ using System.Runtime.CompilerServices; +using EventStore.Client; +using EventStore.Client.Tests.TestNode; +using EventStore.Client.Tests; -namespace EventStore.Client.Streams.Tests; - -public class SecurityFixture : EventStoreFixture { +public class SecurityFixture : KurrentTemporaryFixture { public const string NoAclStream = nameof(NoAclStream); public const string ReadStream = nameof(ReadStream); public const string WriteStream = nameof(WriteStream); @@ -41,7 +42,7 @@ await Users.CreateUserWithRetry( TestCredentials.TestAdmin.Password!, TestCredentials.Root ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - + await Given(); await When(); }; @@ -245,6 +246,7 @@ public Task WriteMeta(string streamId, UserCredentials? userCreden public async Task SubscribeToStream(string streamId, UserCredentials? userCredentials = default) { await using var subscription = Streams.SubscribeToStream(streamId, FromStream.Start, userCredentials: userCredentials); + await subscription .Messages.OfType().AnyAsync().AsTask() .WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); @@ -253,16 +255,17 @@ await subscription public async Task SubscribeToAll(UserCredentials? userCredentials = default) { await using var subscription = Streams.SubscribeToAll(FromAll.Start, userCredentials: userCredentials); + await subscription .Messages.OfType().AnyAsync().AsTask() .WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); } - - public async Task CreateStreamWithMeta(StreamMetadata metadata, [CallerMemberName] string streamId = "") { + + public async Task CreateStreamWithMeta(StreamMetadata metadataPermanent, [CallerMemberName] string streamId = "") { await Streams.SetStreamMetadataAsync( streamId, StreamState.NoStream, - metadata, + metadataPermanent, userCredentials: TestCredentials.TestAdmin ) .WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); diff --git a/test/EventStore.Client.Streams.Tests/Security/stream_security_inheritance.cs b/test/EventStore.Client.Tests/Security/StreamSecurityInheritanceTests.cs similarity index 95% rename from test/EventStore.Client.Streams.Tests/Security/stream_security_inheritance.cs rename to test/EventStore.Client.Tests/Security/StreamSecurityInheritanceTests.cs index 1e1221e16..247da1a3e 100644 --- a/test/EventStore.Client.Streams.Tests/Security/stream_security_inheritance.cs +++ b/test/EventStore.Client.Tests/Security/StreamSecurityInheritanceTests.cs @@ -1,8 +1,12 @@ -namespace EventStore.Client.Streams.Tests; +using EventStore.Client.Tests.TestNode; +using EventStore.Client.Tests; + +namespace EventStore.Client.Tests; [Trait("Category", "Security")] -public class stream_security_inheritance(ITestOutputHelper output, stream_security_inheritance.CustomFixture fixture) : EventStoreTests(output, fixture) { - [Fact] +public class StreamSecurityInheritanceTests(ITestOutputHelper output, StreamSecurityInheritanceTests.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryFact] public async Task acl_inheritance_is_working_properly_on_user_streams() { await Assert.ThrowsAsync(() => Fixture.AppendStream("user-no-acl")); await Fixture.AppendStream("user-no-acl", TestCredentials.TestUser1); @@ -54,7 +58,7 @@ public async Task acl_inheritance_is_working_properly_on_user_streams_when_not_a await Fixture.ReadEvent("user-no-acl"); } - [Fact] + [RetryFact] public async Task acl_inheritance_is_working_properly_on_system_streams() { await Assert.ThrowsAsync(() => Fixture.AppendStream("$sys-no-acl")); await Fixture.AppendStream("$sys-no-acl", TestCredentials.TestUser1); @@ -181,4 +185,4 @@ await Streams.SetStreamMetadataAsync( ); } } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Streams.Tests/Security/subscribe_to_all_security.cs b/test/EventStore.Client.Tests/Security/SubscribeToAllSecurityTests.cs similarity index 77% rename from test/EventStore.Client.Streams.Tests/Security/subscribe_to_all_security.cs rename to test/EventStore.Client.Tests/Security/SubscribeToAllSecurityTests.cs index 48b62a52d..c42e552f0 100644 --- a/test/EventStore.Client.Streams.Tests/Security/subscribe_to_all_security.cs +++ b/test/EventStore.Client.Tests/Security/SubscribeToAllSecurityTests.cs @@ -1,7 +1,10 @@ -namespace EventStore.Client.Streams.Tests; +using EventStore.Client.Tests.TestNode; +using EventStore.Client.Tests; + +namespace EventStore.Client.Tests; [Trait("Category", "Security")] -public class subscribe_to_all_security(ITestOutputHelper output, SecurityFixture fixture) : EventStoreTests(output, fixture) { +public class SubscribeToAllSecurityTests(ITestOutputHelper output, SecurityFixture fixture) : KurrentTemporaryTests(output, fixture) { [Fact] public async Task subscribing_to_all_with_not_existing_credentials_is_not_authenticated() => await Assert.ThrowsAsync(() => Fixture.SubscribeToAll(TestCredentials.TestBadUser)); @@ -18,4 +21,4 @@ public async Task subscribing_to_all_with_not_authorized_user_credentials_is_den [Fact] public async Task subscribing_to_all_with_admin_user_credentials_succeeds() => await Fixture.SubscribeToAll(TestCredentials.TestAdmin); -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Streams.Tests/Security/subscribe_to_stream_security.cs b/test/EventStore.Client.Tests/Security/SubscribeToStreamSecurityTests.cs similarity index 78% rename from test/EventStore.Client.Streams.Tests/Security/subscribe_to_stream_security.cs rename to test/EventStore.Client.Tests/Security/SubscribeToStreamSecurityTests.cs index 0af3f8da9..6e34a6144 100644 --- a/test/EventStore.Client.Streams.Tests/Security/subscribe_to_stream_security.cs +++ b/test/EventStore.Client.Tests/Security/SubscribeToStreamSecurityTests.cs @@ -1,13 +1,14 @@ -namespace EventStore.Client.Streams.Tests; +using EventStore.Client.Tests.TestNode; +using EventStore.Client.Tests; + +namespace EventStore.Client.Tests; [Trait("Category", "Security")] -public class subscribe_to_stream_security(ITestOutputHelper output, SecurityFixture fixture) - : EventStoreTests(output, fixture) { +public class SubscribeToStreamSecurityTests(ITestOutputHelper output, SecurityFixture fixture) + : KurrentTemporaryTests(output, fixture) { [Fact] public async Task subscribing_to_stream_with_not_existing_credentials_is_not_authenticated() => - await Assert.ThrowsAsync( - () => Fixture.SubscribeToStream(SecurityFixture.ReadStream, TestCredentials.TestBadUser) - ); + await Assert.ThrowsAsync(() => Fixture.SubscribeToStream(SecurityFixture.ReadStream, TestCredentials.TestBadUser)); [Fact] public async Task subscribing_to_stream_with_no_credentials_is_denied() => @@ -15,9 +16,7 @@ public async Task subscribing_to_stream_with_no_credentials_is_denied() => [Fact] public async Task subscribing_to_stream_with_not_authorized_user_credentials_is_denied() => - await Assert.ThrowsAsync( - () => Fixture.SubscribeToStream(SecurityFixture.ReadStream, TestCredentials.TestUser2) - ); + await Assert.ThrowsAsync(() => Fixture.SubscribeToStream(SecurityFixture.ReadStream, TestCredentials.TestUser2)); [Fact] public async Task reading_stream_with_authorized_user_credentials_succeeds() { @@ -39,9 +38,7 @@ public async Task subscribing_to_no_acl_stream_succeeds_when_no_credentials_are_ [Fact] public async Task subscribing_to_no_acl_stream_is_not_authenticated_when_not_existing_credentials_are_passed() => - await Assert.ThrowsAsync( - () => Fixture.SubscribeToStream(SecurityFixture.NoAclStream, TestCredentials.TestBadUser) - ); + await Assert.ThrowsAsync(() => Fixture.SubscribeToStream(SecurityFixture.NoAclStream, TestCredentials.TestBadUser)); [Fact] public async Task subscribing_to_no_acl_stream_succeeds_when_any_existing_user_credentials_are_passed() { @@ -65,9 +62,7 @@ public async Task subscribing_to_all_access_normal_stream_succeeds_when_no_crede [Fact] public async Task subscribing_to_all_access_normal_stream_is_not_authenticated_when_not_existing_credentials_are_passed() => - await Assert.ThrowsAsync( - () => Fixture.SubscribeToStream(SecurityFixture.NormalAllStream, TestCredentials.TestBadUser) - ); + await Assert.ThrowsAsync(() => Fixture.SubscribeToStream(SecurityFixture.NormalAllStream, TestCredentials.TestBadUser)); [Fact] public async Task subscribing_to_all_access_normal_stream_succeeds_when_any_existing_user_credentials_are_passed() { diff --git a/test/EventStore.Client.Streams.Tests/Security/system_stream_security.cs b/test/EventStore.Client.Tests/Security/SystemStreamSecurityTests.cs similarity index 94% rename from test/EventStore.Client.Streams.Tests/Security/system_stream_security.cs rename to test/EventStore.Client.Tests/Security/SystemStreamSecurityTests.cs index c4e001b4a..f5ed68732 100644 --- a/test/EventStore.Client.Streams.Tests/Security/system_stream_security.cs +++ b/test/EventStore.Client.Tests/Security/SystemStreamSecurityTests.cs @@ -1,7 +1,10 @@ -namespace EventStore.Client.Streams.Tests; +using EventStore.Client.Tests.TestNode; +using EventStore.Client.Tests; + +namespace EventStore.Client.Tests; [Trait("Category", "Security")] -public class system_stream_security(ITestOutputHelper output, SecurityFixture fixture) : EventStoreTests(output, fixture) { +public class SystemStreamSecurityTests(ITestOutputHelper output, SecurityFixture fixture) : KurrentTemporaryTests(output, fixture) { [Fact] public async Task operations_on_system_stream_with_no_acl_set_fail_for_non_admin() { await Assert.ThrowsAsync(() => Fixture.ReadEvent("$system-no-acl", TestCredentials.TestUser1)); @@ -40,7 +43,9 @@ public async Task operations_on_system_stream_with_acl_set_to_usual_user_fail_fo await Assert.ThrowsAsync(() => Fixture.AppendStream(SecurityFixture.SystemAclStream, TestCredentials.TestUser2)); await Assert.ThrowsAsync(() => Fixture.ReadMeta(SecurityFixture.SystemAclStream, TestCredentials.TestUser2)); - await Assert.ThrowsAsync(() => Fixture.WriteMeta(SecurityFixture.SystemAclStream, TestCredentials.TestUser2, TestCredentials.TestUser1.Username)); + await Assert.ThrowsAsync( + () => Fixture.WriteMeta(SecurityFixture.SystemAclStream, TestCredentials.TestUser2, TestCredentials.TestUser1.Username) + ); await Assert.ThrowsAsync(() => Fixture.SubscribeToStream(SecurityFixture.SystemAclStream, TestCredentials.TestUser2)); } diff --git a/test/EventStore.Client.Streams.Tests/Security/write_stream_meta_security.cs b/test/EventStore.Client.Tests/Security/WriteStreamMetaSecurityTests.cs similarity index 86% rename from test/EventStore.Client.Streams.Tests/Security/write_stream_meta_security.cs rename to test/EventStore.Client.Tests/Security/WriteStreamMetaSecurityTests.cs index 9b003795c..d2ace8af4 100644 --- a/test/EventStore.Client.Streams.Tests/Security/write_stream_meta_security.cs +++ b/test/EventStore.Client.Tests/Security/WriteStreamMetaSecurityTests.cs @@ -1,7 +1,10 @@ -namespace EventStore.Client.Streams.Tests; +using EventStore.Client.Tests.TestNode; +using EventStore.Client.Tests; + +namespace EventStore.Client.Tests; [Trait("Category", "Security")] -public class write_stream_meta_security(ITestOutputHelper output, SecurityFixture fixture) : EventStoreTests(output, fixture) { +public class WriteStreamMetaSecurityTests(ITestOutputHelper output, SecurityFixture fixture) : KurrentTemporaryTests(output, fixture) { [Fact] public async Task writing_meta_with_not_existing_credentials_is_not_authenticated() => await Assert.ThrowsAsync( @@ -19,7 +22,8 @@ public async Task writing_meta_to_stream_with_no_credentials_is_denied() => [Fact] public async Task writing_meta_to_stream_with_not_authorized_user_credentials_is_denied() => - await Assert.ThrowsAsync(() => + await Assert.ThrowsAsync( + () => Fixture.WriteMeta( SecurityFixture.MetaWriteStream, TestCredentials.TestUser2, @@ -66,7 +70,9 @@ public async Task writing_meta_to_all_access_normal_stream_succeeds_when_no_cred [Fact] public async Task writing_meta_to_all_access_normal_stream_is_not_authenticated_when_not_existing_credentials_are_passed() => - await Assert.ThrowsAsync(() => Fixture.WriteMeta(SecurityFixture.NormalAllStream, TestCredentials.TestBadUser, SystemRoles.All)); + await Assert.ThrowsAsync( + () => Fixture.WriteMeta(SecurityFixture.NormalAllStream, TestCredentials.TestBadUser, SystemRoles.All) + ); [Fact] public async Task @@ -78,4 +84,4 @@ public async Task [Fact] public async Task writing_meta_to_all_access_normal_stream_succeeds_when_admin_user_credentials_are_passed() => await Fixture.WriteMeta(SecurityFixture.NormalAllStream, TestCredentials.TestAdmin, SystemRoles.All); -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Streams.Tests/Security/write_stream_security.cs b/test/EventStore.Client.Tests/Security/WriteStreamSecurityTests.cs similarity index 93% rename from test/EventStore.Client.Streams.Tests/Security/write_stream_security.cs rename to test/EventStore.Client.Tests/Security/WriteStreamSecurityTests.cs index d002d37c9..aec66866a 100644 --- a/test/EventStore.Client.Streams.Tests/Security/write_stream_security.cs +++ b/test/EventStore.Client.Tests/Security/WriteStreamSecurityTests.cs @@ -1,8 +1,8 @@ -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Tests; [Trait("Category", "Security")] -public class write_stream_security : IClassFixture { - public write_stream_security(ITestOutputHelper output, SecurityFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); +public class WriteStreamSecurityTests : IClassFixture { + public WriteStreamSecurityTests(ITestOutputHelper output, SecurityFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); SecurityFixture Fixture { get; } @@ -67,4 +67,4 @@ public async Task writing_to_all_access_normal_stream_succeeds_when_any_existing [Fact] public async Task writing_to_all_access_normal_stream_succeeds_when_any_admin_user_credentials_are_passed() => await Fixture.AppendStream(SecurityFixture.NormalAllStream, TestCredentials.TestAdmin); -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests/SharingProviderTests.cs b/test/EventStore.Client.Tests/SharingProviderTests.cs index ddb4c9d5f..efebe5b09 100644 --- a/test/EventStore.Client.Tests/SharingProviderTests.cs +++ b/test/EventStore.Client.Tests/SharingProviderTests.cs @@ -3,7 +3,7 @@ namespace EventStore.Client.Tests; public class SharingProviderTests { - [Fact] + [RetryFact] public async Task CanGetCurrent() { using var sut = new SharingProvider( async (x, _) => x + 1, @@ -14,7 +14,7 @@ public async Task CanGetCurrent() { Assert.Equal(6, await sut.CurrentAsync); } - [Fact] + [RetryFact] public async Task CanReset() { var count = 0; using var sut = new SharingProvider( @@ -28,7 +28,7 @@ public async Task CanReset() { Assert.Equal(1, await sut.CurrentAsync); } - [Fact] + [RetryFact] public async Task CanReturnBroken() { Action? onBroken = null; var count = 0; @@ -50,7 +50,7 @@ public async Task CanReturnBroken() { Assert.Equal(2, await sut.CurrentAsync); } - [Fact] + [RetryFact] public async Task CanReturnSameBoxTwice() { Action? onBroken = null; var count = 0; @@ -74,7 +74,7 @@ public async Task CanReturnSameBoxTwice() { Assert.Equal(1, await sut.CurrentAsync); } - [Fact] + [RetryFact] public async Task CanReturnPendingBox() { var trigger = new SemaphoreSlim(0); Action? onBroken = null; @@ -113,7 +113,7 @@ public async Task CanReturnPendingBox() { Assert.Equal(1, count); } - [Fact] + [RetryFact] public async Task FactoryCanThrow() { using var sut = new SharingProvider( (x, _) => throw new($"input {x}"), @@ -130,7 +130,7 @@ public async Task FactoryCanThrow() { // safe to call onBroken before the factory has returned, but it doesn't // do anything because the box is not populated yet. // the factory has to indicate failure by throwing. - [Fact] + [RetryFact] public async Task FactoryCanCallOnBrokenSynchronously() { using var sut = new SharingProvider( async (x, onBroken) => { @@ -147,7 +147,7 @@ public async Task FactoryCanCallOnBrokenSynchronously() { Assert.Equal(0, await sut.CurrentAsync); } - [Fact] + [RetryFact] public async Task FactoryCanCallOnBrokenSynchronouslyAndThrow() { using var sut = new SharingProvider( async (x, onBroken) => { @@ -167,7 +167,7 @@ public async Task FactoryCanCallOnBrokenSynchronouslyAndThrow() { Assert.Equal("input 0", ex.Message); } - [Fact] + [RetryFact] public async Task StopsAfterBeingDisposed() { Action? onBroken = null; var count = 0; @@ -193,7 +193,7 @@ public async Task StopsAfterBeingDisposed() { Assert.Equal(1, count); } - [Fact] + [RetryFact] public async Task ExampleUsage() { // factory waits to be signalled by completeConstruction being released // sometimes the factory succeeds, sometimes it throws. @@ -263,4 +263,4 @@ async Task Factory(int input, Action onBroken) { await constructionCompleted.WaitAsync(); Assert.Equal(0, await sut.CurrentAsync); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests/StreamPositionTests.cs b/test/EventStore.Client.Tests/StreamPositionTests.cs index 22578b548..d70475dd0 100644 --- a/test/EventStore.Client.Tests/StreamPositionTests.cs +++ b/test/EventStore.Client.Tests/StreamPositionTests.cs @@ -5,17 +5,17 @@ namespace EventStore.Client.Tests; public class StreamPositionTests : ValueObjectTests { public StreamPositionTests() : base(new ScenarioFixture()) { } - [Fact] + [RetryFact] public void IsComparable() => Assert.IsAssignableFrom>(_fixture.Create()); - [Fact] + [RetryFact] public void AdditionOperator() { var sut = StreamPosition.Start; Assert.Equal(new(1), sut + 1); Assert.Equal(new(1), 1 + sut); } - [Fact] + [RetryFact] public void NextReturnsExpectedResult() { var sut = StreamPosition.Start; Assert.Equal(sut + 1, sut.Next()); @@ -33,7 +33,7 @@ public void AdditionOutOfBoundsThrows(StreamPosition StreamPosition, ulong opera Assert.Throws(() => operand + StreamPosition); } - [Fact] + [RetryFact] public void SubtractionOperator() { var sut = new StreamPosition(1); Assert.Equal(new(0), sut - 1); @@ -64,17 +64,17 @@ public void ArgumentOutOfRange(ulong value) { Assert.Equal(nameof(value), ex.ParamName); } - [Fact] + [RetryFact] public void FromStreamPositionEndThrows() => Assert.Throws(() => StreamRevision.FromStreamPosition(StreamPosition.End)); - [Fact] + [RetryFact] public void FromStreamPositionReturnsExpectedResult() { var result = StreamPosition.FromStreamRevision(new(0)); Assert.Equal(new(0), result); } - [Fact] + [RetryFact] public void ExplicitConversionToUInt64ReturnsExpectedResult() { const ulong value = 0UL; @@ -82,7 +82,7 @@ public void ExplicitConversionToUInt64ReturnsExpectedResult() { Assert.Equal(value, actual); } - [Fact] + [RetryFact] public void ImplicitConversionToUInt64ReturnsExpectedResult() { const ulong value = 0UL; @@ -90,7 +90,7 @@ public void ImplicitConversionToUInt64ReturnsExpectedResult() { Assert.Equal(value, actual); } - [Fact] + [RetryFact] public void ExplicitConversionToStreamPositionReturnsExpectedResult() { const ulong value = 0UL; @@ -99,7 +99,7 @@ public void ExplicitConversionToStreamPositionReturnsExpectedResult() { Assert.Equal(expected, actual); } - [Fact] + [RetryFact] public void ImplicitConversionToStreamPositionReturnsExpectedResult() { const ulong value = 0UL; @@ -109,14 +109,14 @@ public void ImplicitConversionToStreamPositionReturnsExpectedResult() { Assert.Equal(expected, actual); } - [Fact] + [RetryFact] public void ToStringExpectedResult() { var expected = 0UL.ToString(); Assert.Equal(expected, new StreamPosition(0UL).ToString()); } - [Fact] + [RetryFact] public void ToUInt64ExpectedResult() { var expected = 0UL; @@ -126,4 +126,4 @@ public void ToUInt64ExpectedResult() { class ScenarioFixture : Fixture { public ScenarioFixture() => Customize(composer => composer.FromFactory(value => new(value))); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests/StreamRevisionTests.cs b/test/EventStore.Client.Tests/StreamRevisionTests.cs index e42039946..ddc479251 100644 --- a/test/EventStore.Client.Tests/StreamRevisionTests.cs +++ b/test/EventStore.Client.Tests/StreamRevisionTests.cs @@ -5,17 +5,17 @@ namespace EventStore.Client.Tests; public class StreamRevisionTests : ValueObjectTests { public StreamRevisionTests() : base(new ScenarioFixture()) { } - [Fact] + [RetryFact] public void IsComparable() => Assert.IsAssignableFrom>(_fixture.Create()); - [Fact] + [RetryFact] public void AdditionOperator() { var sut = new StreamRevision(0); Assert.Equal(new(1), sut + 1); Assert.Equal(new(1), 1 + sut); } - [Fact] + [RetryFact] public void NextReturnsExpectedResult() { var sut = new StreamRevision(0); Assert.Equal(sut + 1, sut.Next()); @@ -32,7 +32,7 @@ public void AdditionOutOfBoundsThrows(StreamRevision streamRevision, ulong opera Assert.Throws(() => operand + streamRevision); } - [Fact] + [RetryFact] public void SubtractionOperator() { var sut = new StreamRevision(1); Assert.Equal(new(0), sut - 1); @@ -63,17 +63,17 @@ public void ArgumentOutOfRange(ulong value) { Assert.Equal(nameof(value), ex.ParamName); } - [Fact] + [RetryFact] public void FromStreamPositionEndThrows() => Assert.Throws(() => StreamRevision.FromStreamPosition(StreamPosition.End)); - [Fact] + [RetryFact] public void FromStreamPositionReturnsExpectedResult() { var result = StreamRevision.FromStreamPosition(StreamPosition.Start); Assert.Equal(new(0), result); } - [Fact] + [RetryFact] public void ExplicitConversionToUInt64ReturnsExpectedResult() { const ulong value = 0UL; @@ -82,7 +82,7 @@ public void ExplicitConversionToUInt64ReturnsExpectedResult() { Assert.Equal(value, actual); } - [Fact] + [RetryFact] public void ImplicitConversionToUInt64ReturnsExpectedResult() { const ulong value = 0UL; @@ -91,7 +91,7 @@ public void ImplicitConversionToUInt64ReturnsExpectedResult() { Assert.Equal(value, actual); } - [Fact] + [RetryFact] public void ExplicitConversionToStreamRevisionReturnsExpectedResult() { const ulong value = 0UL; @@ -101,7 +101,7 @@ public void ExplicitConversionToStreamRevisionReturnsExpectedResult() { Assert.Equal(expected, actual); } - [Fact] + [RetryFact] public void ImplicitConversionToStreamRevisionReturnsExpectedResult() { const ulong value = 0UL; @@ -111,14 +111,14 @@ public void ImplicitConversionToStreamRevisionReturnsExpectedResult() { Assert.Equal(expected, actual); } - [Fact] + [RetryFact] public void ToStringExpectedResult() { var expected = 0UL.ToString(); Assert.Equal(expected, new StreamRevision(0UL).ToString()); } - [Fact] + [RetryFact] public void ToUInt64ExpectedResult() { var expected = 0UL; @@ -128,4 +128,4 @@ public void ToUInt64ExpectedResult() { class ScenarioFixture : Fixture { public ScenarioFixture() => Customize(composer => composer.FromFactory(value => new(value))); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests/StreamStateTests.cs b/test/EventStore.Client.Tests/StreamStateTests.cs index b4d0424c6..7bd086099 100644 --- a/test/EventStore.Client.Tests/StreamStateTests.cs +++ b/test/EventStore.Client.Tests/StreamStateTests.cs @@ -7,9 +7,9 @@ public class StreamStateTests : ValueObjectTests { public StreamStateTests() : base(new ScenarioFixture()) { } public static IEnumerable ArgumentOutOfRangeTestCases() { - yield return new object?[] { 0 }; - yield return new object?[] { int.MaxValue }; - yield return new object?[] { -3 }; + yield return [0]; + yield return [int.MaxValue]; + yield return [-3]; } [Theory] @@ -19,23 +19,23 @@ public void ArgumentOutOfRange(int value) { Assert.Equal(nameof(value), ex.ParamName); } - [Fact] + [RetryFact] public void ExplicitConversionExpectedResult() { const int expected = 1; var actual = (int)new StreamState(expected); Assert.Equal(expected, actual); } - [Fact] + [RetryFact] public void ImplicitConversionExpectedResult() { const int expected = 1; Assert.Equal(expected, new StreamState(expected)); } public static IEnumerable ToStringTestCases() { - yield return new object?[] { StreamState.Any, nameof(StreamState.Any) }; - yield return new object?[] { StreamState.NoStream, nameof(StreamState.NoStream) }; - yield return new object?[] { StreamState.StreamExists, nameof(StreamState.StreamExists) }; + yield return [StreamState.Any, nameof(StreamState.Any)]; + yield return [StreamState.NoStream, nameof(StreamState.NoStream)]; + yield return [StreamState.StreamExists, nameof(StreamState.StreamExists)]; } [Theory] @@ -54,4 +54,4 @@ class ScenarioFixture : Fixture { public ScenarioFixture() => Customize(composer => composer.FromFactory(() => Instances[Interlocked.Increment(ref RefCount) % Instances.Length])); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Streams.Tests/Append/append_to_stream.cs b/test/EventStore.Client.Tests/Streams/AppendTests.cs similarity index 55% rename from test/EventStore.Client.Streams.Tests/Append/append_to_stream.cs rename to test/EventStore.Client.Tests/Streams/AppendTests.cs index 6cd5b813d..3b2792b8f 100644 --- a/test/EventStore.Client.Streams.Tests/Append/append_to_stream.cs +++ b/test/EventStore.Client.Tests/Streams/AppendTests.cs @@ -1,19 +1,12 @@ -using System.Text; using Grpc.Core; +using Humanizer; -namespace EventStore.Client.Streams.Tests.Append; +namespace EventStore.Client.Tests.Streams; [Trait("Category", "Target:Stream")] [Trait("Category", "Operation:Append")] -public class append_to_stream(ITestOutputHelper output, EventStoreFixture fixture) - : EventStoreTests(output, fixture) { - public static IEnumerable ExpectedVersionCreateStreamTestCases() { - yield return new object?[] { StreamState.Any }; - yield return new object?[] { StreamState.NoStream }; - } - - [Theory] - [MemberData(nameof(ExpectedVersionCreateStreamTestCases))] +public class AppendTests(ITestOutputHelper output, KurrentPermanentFixture fixture) : EventStorePermanentTests(output, fixture) { + [Theory, ExpectedVersionCreateStreamTestCases] public async Task appending_zero_events(StreamState expectedStreamState) { var stream = $"{Fixture.GetStreamName()}_{expectedStreamState}"; @@ -33,8 +26,7 @@ await Fixture.Streams .ShouldThrowAsync(ex => ex.Stream.ShouldBe(stream)); } - [Theory] - [MemberData(nameof(ExpectedVersionCreateStreamTestCases))] + [Theory, ExpectedVersionCreateStreamTestCases] public async Task appending_zero_events_again(StreamState expectedStreamState) { var stream = $"{Fixture.GetStreamName()}_{expectedStreamState}"; @@ -54,8 +46,7 @@ await Fixture.Streams .ShouldThrowAsync(ex => ex.Stream.ShouldBe(stream)); } - [Theory] - [MemberData(nameof(ExpectedVersionCreateStreamTestCases))] + [Theory, ExpectedVersionCreateStreamTestCases] public async Task create_stream_expected_version_on_first_write_if_does_not_exist(StreamState expectedStreamState) { var stream = $"{Fixture.GetStreamName()}_{expectedStreamState}"; @@ -73,7 +64,7 @@ public async Task create_stream_expected_version_on_first_write_if_does_not_exis Assert.Equal(1, count); } - [Fact] + [RetryFact] public async Task multiple_idempotent_writes() { var stream = Fixture.GetStreamName(); var events = Fixture.CreateTestEvents(4).ToArray(); @@ -85,7 +76,7 @@ public async Task multiple_idempotent_writes() { Assert.Equal(new(3), writeResult.NextExpectedStreamRevision); } - [Fact] + [RetryFact] public async Task multiple_idempotent_writes_with_same_id_bug_case() { var stream = Fixture.GetStreamName(); @@ -97,7 +88,7 @@ public async Task multiple_idempotent_writes_with_same_id_bug_case() { Assert.Equal(new(5), writeResult.NextExpectedStreamRevision); } - [Fact] + [RetryFact] public async Task in_case_where_multiple_writes_of_multiple_events_with_the_same_ids_using_expected_version_any_then_next_expected_version_is_unreliable() { var stream = Fixture.GetStreamName(); @@ -114,7 +105,7 @@ public async Task Assert.Equal(new(0), writeResult.NextExpectedStreamRevision); } - [Fact] + [RetryFact] public async Task in_case_where_multiple_writes_of_multiple_events_with_the_same_ids_using_expected_version_nostream_then_next_expected_version_is_correct() { var stream = Fixture.GetStreamName(); @@ -132,7 +123,7 @@ public async Task Assert.Equal(streamRevision, writeResult.NextExpectedStreamRevision); } - [Fact] + [RetryFact] public async Task writing_with_correct_expected_version_to_deleted_stream_throws_stream_deleted() { var stream = Fixture.GetStreamName(); @@ -143,7 +134,7 @@ await Fixture.Streams .ShouldThrowAsync(); } - [Fact] + [RetryFact] public async Task returns_log_position_when_writing() { var stream = Fixture.GetStreamName(); @@ -157,7 +148,7 @@ public async Task returns_log_position_when_writing() { Assert.True(0 < result.LogPosition.CommitPosition); } - [Fact] + [RetryFact] public async Task writing_with_any_expected_version_to_deleted_stream_throws_stream_deleted() { var stream = Fixture.GetStreamName(); await Fixture.Streams.TombstoneAsync(stream, StreamState.NoStream); @@ -167,7 +158,7 @@ await Fixture.Streams .ShouldThrowAsync(); } - [Fact] + [RetryFact] public async Task writing_with_invalid_expected_version_to_deleted_stream_throws_stream_deleted() { var stream = Fixture.GetStreamName(); @@ -178,7 +169,7 @@ await Fixture.Streams .ShouldThrowAsync(); } - [Fact] + [RetryFact] public async Task append_with_correct_expected_version_to_existing_stream() { var stream = Fixture.GetStreamName(); @@ -197,7 +188,7 @@ public async Task append_with_correct_expected_version_to_existing_stream() { Assert.Equal(new(1), writeResult.NextExpectedStreamRevision); } - [Fact] + [RetryFact] public async Task append_with_any_expected_version_to_existing_stream() { var stream = Fixture.GetStreamName(); @@ -218,7 +209,7 @@ public async Task append_with_any_expected_version_to_existing_stream() { Assert.Equal(new(1), writeResult.NextExpectedStreamRevision); } - [Fact] + [RetryFact] public async Task appending_with_wrong_expected_version_to_existing_stream_throws_wrong_expected_version() { var stream = Fixture.GetStreamName(); @@ -232,7 +223,7 @@ public async Task appending_with_wrong_expected_version_to_existing_stream_throw ex.ExpectedStreamRevision.ShouldBe(new(999)); } - [Fact] + [RetryFact] public async Task appending_with_wrong_expected_version_to_existing_stream_returns_wrong_expected_version() { var stream = Fixture.GetStreamName(); @@ -248,7 +239,7 @@ public async Task appending_with_wrong_expected_version_to_existing_stream_retur Assert.Equal(new(1), wrongExpectedVersionResult.NextExpectedStreamRevision); } - [Fact] + [RetryFact] public async Task append_with_stream_exists_expected_version_to_existing_stream() { var stream = Fixture.GetStreamName(); @@ -261,7 +252,7 @@ await Fixture.Streams.AppendToStreamAsync( ); } - [Fact] + [RetryFact] public async Task append_with_stream_exists_expected_version_to_stream_with_multiple_events() { var stream = Fixture.GetStreamName(); @@ -275,7 +266,7 @@ await Fixture.Streams.AppendToStreamAsync( ); } - [Fact] + [RetryFact] public async Task append_with_stream_exists_expected_version_if_metadata_stream_exists() { var stream = Fixture.GetStreamName(); @@ -292,7 +283,7 @@ await Fixture.Streams.AppendToStreamAsync( ); } - [Fact] + [RetryFact] public async Task appending_with_stream_exists_expected_version_and_stream_does_not_exist_throws_wrong_expected_version() { var stream = Fixture.GetStreamName(); @@ -304,7 +295,7 @@ public async Task ex.ActualStreamRevision.ShouldBe(StreamRevision.None); } - [Fact] + [RetryFact] public async Task appending_with_stream_exists_expected_version_and_stream_does_not_exist_returns_wrong_expected_version() { var stream = Fixture.GetStreamName(); @@ -321,7 +312,7 @@ public async Task Assert.Equal(StreamRevision.None, wrongExpectedVersionResult.NextExpectedStreamRevision); } - [Fact] + [RetryFact] public async Task appending_with_stream_exists_expected_version_to_hard_deleted_stream_throws_stream_deleted() { var stream = Fixture.GetStreamName(); @@ -332,7 +323,7 @@ await Fixture.Streams .ShouldThrowAsync(); } - [Fact] + [RetryFact] public async Task appending_with_stream_exists_expected_version_to_deleted_stream_throws_stream_deleted() { var stream = Fixture.GetStreamName(); @@ -345,7 +336,7 @@ await Fixture.Streams .ShouldThrowAsync(); } - [Fact] + [RetryFact] public async Task can_append_multiple_events_at_once() { var stream = Fixture.GetStreamName(); @@ -358,7 +349,7 @@ public async Task can_append_multiple_events_at_once() { Assert.Equal(new(99), writeResult.NextExpectedStreamRevision); } - [Fact] + [RetryFact] public async Task returns_failure_status_when_conditionally_appending_with_version_mismatch() { var stream = Fixture.GetStreamName(); @@ -374,7 +365,7 @@ public async Task returns_failure_status_when_conditionally_appending_with_versi ); } - [Fact] + [RetryFact] public async Task returns_success_status_when_conditionally_appending_with_matching_version() { var stream = Fixture.GetStreamName(); @@ -390,7 +381,7 @@ public async Task returns_success_status_when_conditionally_appending_with_match ); } - [Fact] + [RetryFact] public async Task returns_failure_status_when_conditionally_appending_to_a_deleted_stream() { var stream = Fixture.GetStreamName(); @@ -407,7 +398,7 @@ public async Task returns_failure_status_when_conditionally_appending_to_a_delet Assert.Equal(ConditionalWriteResult.StreamDeleted, result); } - [Fact] + [RetryFact] public async Task expected_version_no_stream() { var result = await Fixture.Streams.AppendToStreamAsync( Fixture.GetStreamName(), @@ -418,7 +409,7 @@ public async Task expected_version_no_stream() { Assert.Equal(new(0), result!.NextExpectedStreamRevision); } - [Fact] + [RetryFact] public async Task expected_version_no_stream_returns_position() { var result = await Fixture.Streams.AppendToStreamAsync( Fixture.GetStreamName(), @@ -429,7 +420,7 @@ public async Task expected_version_no_stream_returns_position() { Assert.True(result.LogPosition > Position.Start); } - [Fact] + [RetryFact] public async Task with_timeout_any_stream_revision_fails_when_operation_expired() { var stream = Fixture.GetStreamName(); @@ -443,7 +434,7 @@ public async Task with_timeout_any_stream_revision_fails_when_operation_expired( ex.StatusCode.ShouldBe(StatusCode.DeadlineExceeded); } - [Fact] + [RetryFact] public async Task with_timeout_stream_revision_fails_when_operation_expired() { var stream = Fixture.GetStreamName(); @@ -459,7 +450,7 @@ public async Task with_timeout_stream_revision_fails_when_operation_expired() { ex.StatusCode.ShouldBe(StatusCode.DeadlineExceeded); } - [Fact] + [RetryFact] public async Task when_events_enumerator_throws_the_write_does_not_succeed() { var streamName = Fixture.GetStreamName(); @@ -477,4 +468,317 @@ await Fixture.Streams state.ShouldBe(ReadState.StreamNotFound); } + + [RetryFact] + public async Task succeeds_when_size_is_less_than_max_append_size() { + // Arrange + var maxAppendSize = (uint)100.Kilobytes().Bytes; + var stream = Fixture.GetStreamName(); + + // Act + var (events, size) = Fixture.CreateTestEventsUpToMaxSize(maxAppendSize - 1); + + // Assert + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + } + + [RetryFact] + public async Task fails_when_size_exceeds_max_append_size() { + // Arrange + var maxAppendSize = (uint)100.Kilobytes().Bytes; + var stream = Fixture.GetStreamName(); + var eventsAppendSize = maxAppendSize * 2; + + // Act + var (events, size) = Fixture.CreateTestEventsUpToMaxSize(eventsAppendSize); + + // Assert + size.ShouldBeGreaterThan(maxAppendSize); + + var ex = await Fixture.Streams + .AppendToStreamAsync(stream, StreamState.NoStream, events) + .ShouldThrowAsync(); + + ex.MaxAppendSize.ShouldBe(maxAppendSize); + } + + [RetryFact] + public async Task sequence_0em1_1e0_2e1_3e2_4e3_5e4_0em1_idempotent() { + var stream = Fixture.GetStreamName(); + + var events = Fixture.CreateTestEvents(6).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(1)); + + var count = await Fixture.Streams + .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); + + Assert.Equal(events.Length, count); + } + + [RetryFact] + public async Task sequence_0em1_1e0_2e1_3e2_4e3_4e4_0any_idempotent() { + var stream = Fixture.GetStreamName(); + + var events = Fixture.CreateTestEvents(6).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, events.Take(1)); + + var count = await Fixture.Streams + .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); + + Assert.Equal(events.Length, count); + } + + [RetryFact] + public async Task sequence_0em1_1e0_2e1_3e2_4e3_5e4_0e5_non_idempotent() { + var stream = Fixture.GetStreamName(); + + var events = Fixture.CreateTestEvents(6).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(5), events.Take(1)); + + var count = await Fixture.Streams + .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 2).CountAsync(); + + Assert.Equal(events.Length + 1, count); + } + + [RetryFact] + public async Task sequence_0em1_1e0_2e1_3e2_4e3_5e4_0e6_throws_wev() { + var stream = Fixture.GetStreamName(); + + var events = Fixture.CreateTestEvents(6).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + + await Assert.ThrowsAsync(() => Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(6), events.Take(1))); + } + + [RetryFact] + public async Task sequence_0em1_1e0_2e1_3e2_4e3_5e4_0e6_returns_wev() { + var stream = Fixture.GetStreamName(); + + var events = Fixture.CreateTestEvents(6).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + + var writeResult = await Fixture.Streams.AppendToStreamAsync( + stream, + new StreamRevision(6), + events.Take(1), + options => options.ThrowOnAppendFailure = false + ); + + Assert.IsType(writeResult); + } + + [RetryFact] + public async Task sequence_0em1_1e0_2e1_3e2_4e3_5e4_0e4_throws_wev() { + var stream = Fixture.GetStreamName(); + + var events = Fixture.CreateTestEvents(6).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + + await Assert.ThrowsAsync(() => Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(4), events.Take(1))); + } + + [RetryFact] + public async Task sequence_0em1_1e0_2e1_3e2_4e3_5e4_0e4_returns_wev() { + var stream = Fixture.GetStreamName(); + + var events = Fixture.CreateTestEvents(6).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + + var writeResult = await Fixture.Streams.AppendToStreamAsync( + stream, + new StreamRevision(4), + events.Take(1), + options => options.ThrowOnAppendFailure = false + ); + + Assert.IsType(writeResult); + } + + [RetryFact] + public async Task sequence_0em1_0e0_non_idempotent() { + var stream = Fixture.GetStreamName(); + + var events = Fixture.CreateTestEvents().ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(0), events.Take(1)); + + var count = await Fixture.Streams + .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 2).CountAsync(); + + Assert.Equal(events.Length + 1, count); + } + + [RetryFact] + public async Task sequence_0em1_0any_idempotent() { + var stream = Fixture.GetStreamName(); + + var events = Fixture.CreateTestEvents().ToArray(); + + await Task.Delay(TimeSpan.FromSeconds(30)); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, events.Take(1)); + + var count = await Fixture.Streams + .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); + + Assert.Equal(events.Length, count); + } + + [RetryFact] + public async Task sequence_0em1_0em1_idempotent() { + var stream = Fixture.GetStreamName(); + + var events = Fixture.CreateTestEvents().ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(1)); + + var count = await Fixture.Streams + .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); + + Assert.Equal(events.Length, count); + } + + [RetryFact] + public async Task sequence_0em1_1e0_2e1_1any_1any_idempotent() { + var stream = Fixture.GetStreamName(); + + var events = Fixture.CreateTestEvents(3).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, events.Skip(1).Take(1)); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, events.Skip(1).Take(1)); + + var count = await Fixture.Streams + .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); + + Assert.Equal(events.Length, count); + } + + [RetryFact] + public async Task sequence_S_0em1_1em1_E_S_0em1_E_idempotent() { + var stream = Fixture.GetStreamName(); + + var events = Fixture.CreateTestEvents(2).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(1)); + + var count = await Fixture.Streams + .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); + + Assert.Equal(events.Length, count); + } + + [RetryFact] + public async Task sequence_S_0em1_1em1_E_S_0any_E_idempotent() { + var stream = Fixture.GetStreamName(); + + var events = Fixture.CreateTestEvents(2).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, events.Take(1)); + + var count = await Fixture.Streams + .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); + + Assert.Equal(events.Length, count); + } + + [RetryFact] + public async Task sequence_S_0em1_1em1_E_S_1e0_E_idempotent() { + var stream = Fixture.GetStreamName(); + + var events = Fixture.CreateTestEvents(2).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + + await Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(0), events.Skip(1)); + + var count = await Fixture.Streams + .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); + + Assert.Equal(events.Length, count); + } + + [RetryFact] + public async Task sequence_S_0em1_1em1_E_S_1any_E_idempotent() { + var stream = Fixture.GetStreamName(); + + var events = Fixture.CreateTestEvents(2).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, events.Skip(1).Take(1)); + + var count = await Fixture.Streams + .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); + + Assert.Equal(events.Length, count); + } + + [RetryFact] + public async Task sequence_S_0em1_1em1_E_S_0em1_1em1_2em1_E_idempotancy_fail_throws() { + var stream = Fixture.GetStreamName(); + + var events = Fixture.CreateTestEvents(3).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(2)); + + await Assert.ThrowsAsync( + () => Fixture.Streams.AppendToStreamAsync( + stream, + StreamState.NoStream, + events + ) + ); + } + + [RetryFact] + public async Task sequence_S_0em1_1em1_E_S_0em1_1em1_2em1_E_idempotancy_fail_returns() { + var stream = Fixture.GetStreamName(); + + var events = Fixture.CreateTestEvents(3).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(2)); + + var writeResult = await Fixture.Streams.AppendToStreamAsync( + stream, + StreamState.NoStream, + events, + options => options.ThrowOnAppendFailure = false + ); + + Assert.IsType(writeResult); + } + + // [Fact] + // public async Task sending_and_receiving_large_messages_over_the_hard_limit() { + // uint maxAppendSize = 16 * 1024 * 1024 - 10000; + // var streamName = Fixture.GetStreamName(); + // var largeEvent = Fixture.CreateTestEvents() + // .Select(e => new EventData(e.EventId, "-", new byte[maxAppendSize + 1])); + // + // var ex = await Assert.ThrowsAsync(() => Fixture.Streams.AppendToStreamAsync(streamName, StreamState.NoStream, largeEvent)); + // + // Assert.Equal(StatusCode.ResourceExhausted, ex.StatusCode); + // } + + class ExpectedVersionCreateStreamTestCases : TestCaseGenerator { + protected override IEnumerable Data() { + yield return [StreamState.Any]; + yield return [StreamState.NoStream]; + } + } } diff --git a/test/EventStore.Client.Streams.Tests/Bugs/Obsolete/Issue_104.cs b/test/EventStore.Client.Tests/Streams/Bugs/Obsolete/Issue104.cs similarity index 89% rename from test/EventStore.Client.Streams.Tests/Bugs/Obsolete/Issue_104.cs rename to test/EventStore.Client.Tests/Streams/Bugs/Obsolete/Issue104.cs index 922414820..47386e105 100644 --- a/test/EventStore.Client.Streams.Tests/Bugs/Obsolete/Issue_104.cs +++ b/test/EventStore.Client.Tests/Streams/Bugs/Obsolete/Issue104.cs @@ -1,8 +1,8 @@ -namespace EventStore.Client.Streams.Tests.Bugs.Obsolete; +namespace EventStore.Client.Tests.Bugs.Obsolete; [Trait("Category", "Bug")] [Obsolete("Tests will be removed in future release when older subscriptions APIs are removed from the client")] -public class Issue_104(ITestOutputHelper output, EventStoreFixture fixture) : EventStoreTests(output, fixture) { +public class Issue104(ITestOutputHelper output, KurrentPermanentFixture fixture) : EventStorePermanentTests(output, fixture) { [Fact] public async Task subscription_does_not_send_checkpoint_reached_after_disposal() { var streamName = Fixture.GetStreamName(); diff --git a/test/EventStore.Client.Streams.Tests/Bugs/Obsolete/Issue_2544.cs b/test/EventStore.Client.Tests/Streams/Bugs/Obsolete/Issue2544.cs similarity index 82% rename from test/EventStore.Client.Streams.Tests/Bugs/Obsolete/Issue_2544.cs rename to test/EventStore.Client.Tests/Streams/Bugs/Obsolete/Issue2544.cs index 3d65b01ec..e2353090e 100644 --- a/test/EventStore.Client.Streams.Tests/Bugs/Obsolete/Issue_2544.cs +++ b/test/EventStore.Client.Tests/Streams/Bugs/Obsolete/Issue2544.cs @@ -1,30 +1,29 @@ -#pragma warning disable 1998 +// ReSharper disable InconsistentNaming -namespace EventStore.Client.Streams.Tests.Bugs.Obsolete; +namespace EventStore.Client.Tests.Bugs.Obsolete; [Trait("Category", "Bug")] [Obsolete("Tests will be removed in future release when older subscriptions APIs are removed from the client")] -public class Issue_2544 : IClassFixture { - public Issue_2544(ITestOutputHelper output, EventStoreFixture fixture) { +public class Issue2544 : IClassFixture { + public Issue2544(ITestOutputHelper output, KurrentPermanentFixture fixture) { Fixture = fixture.With(x => x.CaptureTestRun(output)); - - _seen = Enumerable.Range(0, 1 + Batches * BatchSize) + + Seen = Enumerable.Range(0, 1 + Batches * BatchSize) .Select(i => new StreamPosition((ulong)i)) .ToDictionary(r => r, _ => false); - _completed = new(); + Completed = new(); } - EventStoreFixture Fixture { get; } + KurrentPermanentFixture Fixture { get; } const int BatchSize = 18; const int Batches = 4; - - readonly TaskCompletionSource _completed; - readonly Dictionary _seen; - public static IEnumerable TestCases() => - Enumerable.Range(0, 5).Select(i => new object[] { i }); + readonly TaskCompletionSource Completed; + readonly Dictionary Seen; + + public static IEnumerable TestCases() => Enumerable.Range(0, 5).Select(i => new object[] { i }); [Theory] [MemberData(nameof(TestCases))] @@ -46,7 +45,7 @@ await Fixture.Streams await AppendEvents(streamName); - await _completed.Task.WithTimeout(); + await Completed.Task.WithTimeout(); } [Theory] @@ -68,7 +67,7 @@ await Fixture.Streams await AppendEvents(streamName); - await _completed.Task.WithTimeout(); + await Completed.Task.WithTimeout(); } [Theory] @@ -91,7 +90,7 @@ await Fixture.Streams await AppendEvents(streamName); - await _completed.Task.WithTimeout(); + await Completed.Task.WithTimeout(); } async Task AppendEvents(string streamName) { @@ -108,8 +107,7 @@ async Task AppendEvents(string streamName) { ); expectedRevision = result.NextExpectedStreamRevision; - } - else { + } else { var result = await Fixture.Streams.AppendToStreamAsync( streamName, expectedRevision, @@ -143,7 +141,7 @@ Func> resubscribe return; } - _completed.TrySetException(ex); + Completed.TrySetException(ex); } Task EventAppeared(ResolvedEvent e, string streamName, out FromStream startFrom) { @@ -160,12 +158,12 @@ Task EventAppeared(ResolvedEvent e, string streamName) { if (e.OriginalStreamId != streamName) return Task.CompletedTask; - if (_seen[e.Event.EventNumber]) + if (Seen[e.Event.EventNumber]) throw new($"Event {e.Event.EventNumber} was already seen"); - _seen[e.Event.EventNumber] = true; + Seen[e.Event.EventNumber] = true; if (e.Event.EventType == "completed") - _completed.TrySetResult(true); + Completed.TrySetResult(true); return Task.CompletedTask; } diff --git a/test/EventStore.Client.Streams.Tests/Delete/deleting_stream.cs b/test/EventStore.Client.Tests/Streams/DeleteTests.cs similarity index 72% rename from test/EventStore.Client.Streams.Tests/Delete/deleting_stream.cs rename to test/EventStore.Client.Tests/Streams/DeleteTests.cs index 552a8a4b9..69bca6b56 100644 --- a/test/EventStore.Client.Streams.Tests/Delete/deleting_stream.cs +++ b/test/EventStore.Client.Tests/Streams/DeleteTests.cs @@ -1,16 +1,11 @@ using Grpc.Core; -namespace EventStore.Client.Streams.Tests.Delete; +namespace EventStore.Client.Tests.Streams; +[Trait("Category", "Target:Stream")] [Trait("Category", "Operation:Delete")] -public class deleting_stream(ITestOutputHelper output, EventStoreFixture fixture) : EventStoreTests(output, fixture) { - public static IEnumerable ExpectedStreamStateCases() { - yield return new object?[] { StreamState.Any, nameof(StreamState.Any) }; - yield return new object?[] { StreamState.NoStream, nameof(StreamState.NoStream) }; - } - - [Theory] - [MemberData(nameof(ExpectedStreamStateCases))] +public class DeleteTests(ITestOutputHelper output, KurrentPermanentFixture fixture) : EventStorePermanentTests(output, fixture) { + [Theory, ExpectedStreamStateCases] public async Task hard_deleting_a_stream_that_does_not_exist_with_expected_version_does_not_throw(StreamState expectedVersion, string name) { var stream = $"{Fixture.GetStreamName()}_{name}"; @@ -78,14 +73,11 @@ public async Task hard_deleting_a_deleted_stream_should_throw() { await Assert.ThrowsAsync(() => Fixture.Streams.TombstoneAsync(stream, StreamState.NoStream)); } - - + [Fact] public async Task with_timeout_any_stream_revision_delete_fails_when_operation_expired() { - var stream = Fixture.GetStreamName(); - var rpcException = await Assert.ThrowsAsync( - () => Fixture.Streams.DeleteAsync(stream, StreamState.Any, TimeSpan.Zero) - ); + var stream = Fixture.GetStreamName(); + var rpcException = await Assert.ThrowsAsync(() => Fixture.Streams.DeleteAsync(stream, StreamState.Any, TimeSpan.Zero)); Assert.Equal(StatusCode.DeadlineExceeded, rpcException.StatusCode); } @@ -94,19 +86,15 @@ public async Task with_timeout_any_stream_revision_delete_fails_when_operation_e public async Task with_timeout_stream_revision_delete_fails_when_operation_expired() { var stream = Fixture.GetStreamName(); - var rpcException = await Assert.ThrowsAsync( - () => Fixture.Streams.DeleteAsync(stream, new StreamRevision(0), TimeSpan.Zero) - ); + var rpcException = await Assert.ThrowsAsync(() => Fixture.Streams.DeleteAsync(stream, new StreamRevision(0), TimeSpan.Zero)); Assert.Equal(StatusCode.DeadlineExceeded, rpcException.StatusCode); } [Fact] public async Task with_timeout_any_stream_revision_tombstoning_fails_when_operation_expired() { - var stream = Fixture.GetStreamName(); - var rpcException = await Assert.ThrowsAsync( - () => Fixture.Streams.TombstoneAsync(stream, StreamState.Any, TimeSpan.Zero) - ); + var stream = Fixture.GetStreamName(); + var rpcException = await Assert.ThrowsAsync(() => Fixture.Streams.TombstoneAsync(stream, StreamState.Any, TimeSpan.Zero)); Assert.Equal(StatusCode.DeadlineExceeded, rpcException.StatusCode); } @@ -115,10 +103,15 @@ public async Task with_timeout_any_stream_revision_tombstoning_fails_when_operat public async Task with_timeout_stream_revision_tombstoning_fails_when_operation_expired() { var stream = Fixture.GetStreamName(); - var rpcException = await Assert.ThrowsAsync( - () => Fixture.Streams.TombstoneAsync(stream, new StreamRevision(0), TimeSpan.Zero) - ); + var rpcException = await Assert.ThrowsAsync(() => Fixture.Streams.TombstoneAsync(stream, new StreamRevision(0), TimeSpan.Zero)); Assert.Equal(StatusCode.DeadlineExceeded, rpcException.StatusCode); } -} \ No newline at end of file + + class ExpectedStreamStateCases : TestCaseGenerator { + protected override IEnumerable Data() { + yield return [StreamState.Any, nameof(StreamState.Any)]; + yield return [StreamState.NoStream, nameof(StreamState.NoStream)]; + } + } +} diff --git a/test/EventStore.Client.Streams.Tests/Read/EventBinaryData.cs b/test/EventStore.Client.Tests/Streams/Read/EventBinaryData.cs similarity index 81% rename from test/EventStore.Client.Streams.Tests/Read/EventBinaryData.cs rename to test/EventStore.Client.Tests/Streams/Read/EventBinaryData.cs index 923a40cd1..53e221b5d 100644 --- a/test/EventStore.Client.Streams.Tests/Read/EventBinaryData.cs +++ b/test/EventStore.Client.Tests/Streams/Read/EventBinaryData.cs @@ -1,33 +1,33 @@ -namespace EventStore.Client.Streams.Tests.Read; +namespace EventStore.Client.Tests; public readonly record struct EventBinaryData(Uuid Id, byte[] Data, byte[] Metadata) { - public bool Equals(EventBinaryData other) => - Id.Equals(other.Id) - && Data.SequenceEqual(other.Data) + public bool Equals(EventBinaryData other) => + Id.Equals(other.Id) + && Data.SequenceEqual(other.Data) && Metadata.SequenceEqual(other.Metadata); public override int GetHashCode() => System.HashCode.Combine(Id, Data, Metadata); } public static class EventBinaryDataConverters { - public static EventBinaryData ToBinaryData(this EventData source) => + public static EventBinaryData ToBinaryData(this EventData source) => new(source.EventId, source.Data.ToArray(), source.Metadata.ToArray()); - public static EventBinaryData ToBinaryData(this EventRecord source) => + public static EventBinaryData ToBinaryData(this EventRecord source) => new(source.EventId, source.Data.ToArray(), source.Metadata.ToArray()); - public static EventBinaryData ToBinaryData(this ResolvedEvent source) => + public static EventBinaryData ToBinaryData(this ResolvedEvent source) => source.Event.ToBinaryData(); - - public static EventBinaryData[] ToBinaryData(this IEnumerable source) => + + public static EventBinaryData[] ToBinaryData(this IEnumerable source) => source.Select(x => x.ToBinaryData()).ToArray(); - - public static EventBinaryData[] ToBinaryData(this IEnumerable source) => + + public static EventBinaryData[] ToBinaryData(this IEnumerable source) => source.Select(x => x.ToBinaryData()).ToArray(); - - public static EventBinaryData[] ToBinaryData(this IEnumerable source) => + + public static EventBinaryData[] ToBinaryData(this IEnumerable source) => source.Select(x => x.ToBinaryData()).ToArray(); public static ValueTask ToBinaryData(this IAsyncEnumerable source) => source.DefaultIfEmpty().Select(x => x.ToBinaryData()).ToArrayAsync(); -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Streams.Tests/Read/EventDataComparer.cs b/test/EventStore.Client.Tests/Streams/Read/EventDataComparer.cs similarity index 91% rename from test/EventStore.Client.Streams.Tests/Read/EventDataComparer.cs rename to test/EventStore.Client.Tests/Streams/Read/EventDataComparer.cs index cd9c6f41a..9ffb2c2bc 100644 --- a/test/EventStore.Client.Streams.Tests/Read/EventDataComparer.cs +++ b/test/EventStore.Client.Tests/Streams/Read/EventDataComparer.cs @@ -1,4 +1,4 @@ -namespace EventStore.Client.Streams.Tests.Read; +namespace EventStore.Client.Tests; static class EventDataComparer { public static bool Equal(EventData expected, EventRecord actual) { @@ -18,4 +18,4 @@ public static bool Equal(EventData[] expected, EventRecord[] actual) { return !expected.Where((t, i) => !Equal(t, actual[i])).Any(); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Streams.Tests/Read/read_all_events_backward.cs b/test/EventStore.Client.Tests/Streams/Read/ReadAllEventsBackwardTests.cs similarity index 87% rename from test/EventStore.Client.Streams.Tests/Read/read_all_events_backward.cs rename to test/EventStore.Client.Tests/Streams/Read/ReadAllEventsBackwardTests.cs index b07f199ef..1620842f9 100644 --- a/test/EventStore.Client.Streams.Tests/Read/read_all_events_backward.cs +++ b/test/EventStore.Client.Tests/Streams/Read/ReadAllEventsBackwardTests.cs @@ -1,12 +1,14 @@ +using EventStore.Client.Tests.TestNode; using Grpc.Core; -namespace EventStore.Client.Streams.Tests.Read; +namespace EventStore.Client.Tests; [Trait("Category", "Target:All")] [Trait("Category", "Operation:Read")] [Trait("Category", "Operation:Read:Backwards")] [Trait("Category", "Database:Dedicated")] -public class read_all_events_backward(ITestOutputHelper output, ReadAllEventsFixture fixture) : EventStoreTests(output, fixture) { +public class ReadAllEventsBackwardTests(ITestOutputHelper output, ReadAllEventsFixture fixture) + : KurrentTemporaryTests(output, fixture) { [Fact] public async Task return_empty_if_reading_from_start() { var result = await Fixture.Streams.ReadAllAsync(Direction.Backwards, Position.Start, 1).CountAsync(); @@ -28,7 +30,7 @@ public async Task return_events_in_reversed_order_compared_to_written() { .ReadAllAsync(Direction.Backwards, Position.End) .Where(x => x.OriginalStreamId == Fixture.ExpectedStreamName) .ToBinaryData(); - + result.ShouldBe(Fixture.ExpectedEventsReversed); } @@ -37,7 +39,7 @@ public async Task return_single_event() { var result = await Fixture.Streams .ReadAllAsync(Direction.Backwards, Position.End, 1) .ToArrayAsync(); - + result.ShouldHaveSingleItem(); } @@ -51,36 +53,36 @@ public async Task max_count_is_respected() { result.Length.ShouldBe(maxCount); } - + [Fact] public async Task stream_found() { var count = await Fixture.Streams .ReadAllAsync(Direction.Backwards, Position.End) .Where(x => x.OriginalStreamId == Fixture.ExpectedStreamName) .CountAsync(); - + count.ShouldBe(Fixture.ExpectedEvents.Length); } - + [Fact] public async Task with_timeout_fails_when_operation_expired() { var ex = await Fixture.Streams .ReadAllAsync(Direction.Backwards, Position.Start, 1, false, TimeSpan.Zero) .ToArrayAsync() .AsTask().ShouldThrowAsync(); - + ex.StatusCode.ShouldBe(StatusCode.DeadlineExceeded); } - + [Fact] public async Task filter_events_by_type() { var result = await Fixture.Streams - .ReadAllAsync(Direction.Backwards, Position.End, EventTypeFilter.Prefix(EventStoreFixture.AnotherTestEventTypePrefix)) + .ReadAllAsync(Direction.Backwards, Position.End, EventTypeFilter.Prefix(KurrentTemporaryFixture.AnotherTestEventTypePrefix)) .ToListAsync(); - - result.ForEach(x => x.Event.EventType.ShouldStartWith(EventStoreFixture.AnotherTestEventTypePrefix)); + + result.ForEach(x => x.Event.EventType.ShouldStartWith(KurrentTemporaryFixture.AnotherTestEventTypePrefix)); } - + [Fact(Skip = "Not Implemented")] public Task be_able_to_read_all_one_by_one_until_end_of_stream() => throw new NotImplementedException(); diff --git a/test/EventStore.Client.Streams.Tests/Read/ReadAllEventsFixture.cs b/test/EventStore.Client.Tests/Streams/Read/ReadAllEventsFixture.cs similarity index 81% rename from test/EventStore.Client.Streams.Tests/Read/ReadAllEventsFixture.cs rename to test/EventStore.Client.Tests/Streams/Read/ReadAllEventsFixture.cs index 197c8a481..979bcccc0 100644 --- a/test/EventStore.Client.Streams.Tests/Read/ReadAllEventsFixture.cs +++ b/test/EventStore.Client.Tests/Streams/Read/ReadAllEventsFixture.cs @@ -1,6 +1,12 @@ -namespace EventStore.Client.Streams.Tests.Read; +using EventStore.Client.Tests.TestNode; +using EventStore.Client.Tests; -public class ReadAllEventsFixture : EventStoreFixture { +namespace EventStore.Client.Tests; + +[Trait("Category", "Target:All")] +[Trait("Category", "Operation:Read")] +[Trait("Category", "Database:Dedicated")] +public class ReadAllEventsFixture : KurrentTemporaryFixture { public ReadAllEventsFixture() { OnSetup = async () => { _ = await Streams.SetStreamMetadataAsync( @@ -36,4 +42,4 @@ public ReadAllEventsFixture() { public EventBinaryData ExpectedFirstEvent { get; private set; } public EventBinaryData ExpectedLastEvent { get; private set; } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Streams.Tests/Read/read_all_events_forward.cs b/test/EventStore.Client.Tests/Streams/Read/ReadAllEventsForwardTests.cs similarity index 91% rename from test/EventStore.Client.Streams.Tests/Read/read_all_events_forward.cs rename to test/EventStore.Client.Tests/Streams/Read/ReadAllEventsForwardTests.cs index fed9629ad..fc927ef11 100644 --- a/test/EventStore.Client.Streams.Tests/Read/read_all_events_forward.cs +++ b/test/EventStore.Client.Tests/Streams/Read/ReadAllEventsForwardTests.cs @@ -1,12 +1,13 @@ using System.Text; +using EventStore.Client.Tests.TestNode; -namespace EventStore.Client.Streams.Tests.Read; +namespace EventStore.Client.Tests; [Trait("Category", "Target:All")] [Trait("Category", "Operation:Read")] [Trait("Category", "Operation:Read:Forwards")] [Trait("Category", "Database:Dedicated")] -public class read_all_events_forward(ITestOutputHelper output, ReadAllEventsFixture fixture) : EventStoreTests(output, fixture) { +public class ReadAllEventsForwardTests(ITestOutputHelper output, ReadAllEventsFixture fixture) : KurrentTemporaryTests(output, fixture) { [Fact] public async Task return_empty_if_reading_from_end() { var result = await Fixture.Streams.ReadAllAsync(Direction.Forwards, Position.End, 1).CountAsync(); @@ -27,7 +28,7 @@ public async Task return_events_in_correct_order_compared_to_written() { .ReadAllAsync(Direction.Forwards, Position.Start) .Where(x => x.OriginalStreamId == Fixture.ExpectedStreamName) .ToBinaryData(); - + result.ShouldBe(Fixture.ExpectedEvents); } @@ -36,7 +37,7 @@ public async Task return_single_event() { var result = await Fixture.Streams .ReadAllAsync(Direction.Forwards, Position.Start, 1) .ToArrayAsync(); - + result.ShouldHaveSingleItem(); } @@ -59,22 +60,22 @@ public async Task reads_all_events_by_default() { Assert.True(count >= Fixture.ExpectedEvents.Length); } - + [Fact] public async Task stream_found() { var count = await Fixture.Streams .ReadAllAsync(Direction.Forwards, Position.Start) .Where(x => x.OriginalStreamId == Fixture.ExpectedStreamName) .CountAsync(); - + count.ShouldBe(Fixture.ExpectedEvents.Length); } - + [Fact] public async Task with_linkto_passed_max_count_one_event_is_read() { const string deletedStream = nameof(deletedStream); const string linkedStream = nameof(linkedStream); - + await Fixture.Streams.AppendToStreamAsync(deletedStream, StreamState.Any, Fixture.CreateTestEvents()); await Fixture.Streams.SetStreamMetadataAsync( deletedStream, @@ -105,10 +106,10 @@ await Fixture.Streams.AppendToStreamAsync( resolveLinkTos: true ) .ToArrayAsync(); - + Assert.Single(events); } - + [Fact] public async Task enumeration_all_referencing_messages_twice_does_not_throw() { var result = Fixture.Streams.ReadAllAsync( @@ -138,16 +139,16 @@ await Assert.ThrowsAsync( await result.Messages.ToArrayAsync() ); } - + [Fact] public async Task filter_events_by_type() { var result = await Fixture.Streams - .ReadAllAsync(Direction.Forwards, Position.Start, EventTypeFilter.Prefix(EventStoreFixture.AnotherTestEventTypePrefix)) + .ReadAllAsync(Direction.Forwards, Position.Start, EventTypeFilter.Prefix(KurrentTemporaryFixture.AnotherTestEventTypePrefix)) .ToListAsync(); - - result.ForEach(x => x.Event.EventType.ShouldStartWith(EventStoreFixture.AnotherTestEventTypePrefix)); + + result.ForEach(x => x.Event.EventType.ShouldStartWith(KurrentTemporaryFixture.AnotherTestEventTypePrefix)); } - + [Fact(Skip = "Not Implemented")] public Task be_able_to_read_all_one_by_one_until_end_of_stream() => throw new NotImplementedException(); diff --git a/test/EventStore.Client.Streams.Tests/Read/read_stream_backward.cs b/test/EventStore.Client.Tests/Streams/Read/ReadStreamBackwardTests.cs similarity index 96% rename from test/EventStore.Client.Streams.Tests/Read/read_stream_backward.cs rename to test/EventStore.Client.Tests/Streams/Read/ReadStreamBackwardTests.cs index ec32888e8..01be08eb7 100644 --- a/test/EventStore.Client.Streams.Tests/Read/read_stream_backward.cs +++ b/test/EventStore.Client.Tests/Streams/Read/ReadStreamBackwardTests.cs @@ -1,11 +1,13 @@ +using EventStore.Client.Tests.TestNode; using Grpc.Core; -namespace EventStore.Client.Streams.Tests.Read; +namespace EventStore.Client.Tests; [Trait("Category", "Target:Stream")] [Trait("Category", "Operation:Read")] [Trait("Category", "Operation:Read:Backwards")] -public class read_stream_backward(ITestOutputHelper output, EventStoreFixture fixture) : EventStoreTests(output, fixture) { +public class ReadStreamBackwardTests(ITestOutputHelper output, KurrentTemporaryFixture fixture) + : KurrentTemporaryTests(output, fixture) { [Theory] [InlineData(0)] public async Task count_le_equal_zero_throws(long maxCount) { @@ -165,7 +167,7 @@ await Fixture.Streams.AppendToStreamAsync( [Fact] public async Task populates_log_position_of_event() { - if (EventStoreTestServer.Version.Major < 22) + if (KurrentTemporaryTestNode.Version.Major < 22) return; var stream = Fixture.GetStreamName(); @@ -181,7 +183,7 @@ public async Task populates_log_position_of_event() { Assert.Equal(writeResult.LogPosition.PreparePosition, writeResult.LogPosition.CommitPosition); Assert.Equal(writeResult.LogPosition, actual.First().Position); } - + [Fact] public async Task with_timeout_fails_when_operation_expired() { var stream = Fixture.GetStreamName(); @@ -203,7 +205,7 @@ public async Task with_timeout_fails_when_operation_expired() { Assert.Equal(StatusCode.DeadlineExceeded, rpcException.StatusCode); } - + [Fact] public async Task enumeration_referencing_messages_twice_does_not_throw() { var result = Fixture.Streams.ReadStreamAsync( @@ -235,7 +237,7 @@ await Assert.ThrowsAsync( await result.Messages.ToArrayAsync() ); } - + [Fact] public async Task stream_not_found() { var result = await Fixture.Streams.ReadStreamAsync( @@ -250,7 +252,7 @@ public async Task stream_not_found() { [Fact] public async Task stream_found() { const int eventCount = 32; - + var events = Fixture.CreateTestEvents(eventCount).ToArray(); var streamName = Fixture.GetStreamName(); @@ -274,4 +276,4 @@ public async Task stream_found() { if (Fixture.EventStoreHasLastStreamPosition) Assert.Equal(new StreamMessage.LastStreamPosition(new(31)), result[^1]); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Streams.Tests/Read/read_stream_events_linked_to_deleted_stream.cs b/test/EventStore.Client.Tests/Streams/Read/ReadStreamEventsLinkedToDeletedStreamTests.cs similarity index 70% rename from test/EventStore.Client.Streams.Tests/Read/read_stream_events_linked_to_deleted_stream.cs rename to test/EventStore.Client.Tests/Streams/Read/ReadStreamEventsLinkedToDeletedStreamTests.cs index ba11b75f0..a96e82ab5 100644 --- a/test/EventStore.Client.Streams.Tests/Read/read_stream_events_linked_to_deleted_stream.cs +++ b/test/EventStore.Client.Tests/Streams/Read/ReadStreamEventsLinkedToDeletedStreamTests.cs @@ -1,13 +1,17 @@ using System.Text; +using EventStore.Client.Tests.TestNode; +using EventStore.Client.Tests; -namespace EventStore.Client.Streams.Tests.Read; +// ReSharper disable ClassNeverInstantiated.Global + +namespace EventStore.Client.Tests; [Trait("Category", "Target:Stream")] -public abstract class read_stream_events_linked_to_deleted_stream(ReadEventsLinkedToDeletedStreamFixture fixture) { +public abstract class ReadStreamEventsLinkedToDeletedStreamTests(ReadEventsLinkedToDeletedStreamFixture fixture) { ReadEventsLinkedToDeletedStreamFixture Fixture { get; } = fixture; [Fact] - public void one_event_is_read() => Assert.Single(Fixture.Events ?? Array.Empty()); + public void one_event_is_read() => Assert.Single(Fixture.Events ?? []); [Fact] public void the_linked_event_is_not_resolved() => Assert.Null(Fixture.Events![0].Event); @@ -17,32 +21,30 @@ public abstract class read_stream_events_linked_to_deleted_stream(ReadEventsLink [Fact] public void the_event_is_not_resolved() => Assert.False(Fixture.Events![0].IsResolved); - + + [UsedImplicitly] [Trait("Category", "Operation:Read")] [Trait("Category", "Operation:Read:Forwards")] - public class @forwards(forwards.CustomFixture fixture) - : read_stream_events_linked_to_deleted_stream(fixture), IClassFixture { - + public class Forwards(Forwards.CustomFixture fixture) : ReadStreamEventsLinkedToDeletedStreamTests(fixture), IClassFixture { public class CustomFixture() : ReadEventsLinkedToDeletedStreamFixture(Direction.Forwards); } - + + [UsedImplicitly] [Trait("Category", "Operation:Read")] [Trait("Category", "Operation:Read:Backwards")] - public class @backwards(backwards.CustomFixture fixture) - : read_stream_events_linked_to_deleted_stream(fixture), IClassFixture { - + public class Backwards(Backwards.CustomFixture fixture) : ReadStreamEventsLinkedToDeletedStreamTests(fixture), IClassFixture { public class CustomFixture() : ReadEventsLinkedToDeletedStreamFixture(Direction.Backwards); } } -public abstract class ReadEventsLinkedToDeletedStreamFixture : EventStoreFixture { +public abstract class ReadEventsLinkedToDeletedStreamFixture : KurrentTemporaryFixture { const string DeletedStream = nameof(DeletedStream); const string LinkedStream = nameof(LinkedStream); protected ReadEventsLinkedToDeletedStreamFixture(Direction direction) { OnSetup = async () => { await Streams.AppendToStreamAsync(DeletedStream, StreamState.Any, CreateTestEvents()); - + await Streams.AppendToStreamAsync( LinkedStream, StreamState.Any, @@ -58,7 +60,7 @@ await Streams.AppendToStreamAsync( ); await Streams.DeleteAsync(DeletedStream, StreamState.Any); - + Events = await Streams.ReadStreamAsync( direction, LinkedStream, @@ -70,4 +72,4 @@ await Streams.AppendToStreamAsync( } public ResolvedEvent[]? Events { get; private set; } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Streams.Tests/Read/read_stream_forward.cs b/test/EventStore.Client.Tests/Streams/Read/ReadStreamForwardTests.cs similarity index 96% rename from test/EventStore.Client.Streams.Tests/Read/read_stream_forward.cs rename to test/EventStore.Client.Tests/Streams/Read/ReadStreamForwardTests.cs index 14c08a79c..4100cf010 100644 --- a/test/EventStore.Client.Streams.Tests/Read/read_stream_forward.cs +++ b/test/EventStore.Client.Tests/Streams/Read/ReadStreamForwardTests.cs @@ -1,9 +1,9 @@ -namespace EventStore.Client.Streams.Tests.Read; +namespace EventStore.Client.Tests; [Trait("Category", "Target:Stream")] [Trait("Category", "Operation:Read")] [Trait("Category", "Operation:Read:Forwards")] -public class read_stream_forward(ITestOutputHelper output, EventStoreFixture fixture) : EventStoreTests(output, fixture) { +public class ReadStreamForwardTests(ITestOutputHelper output, KurrentPermanentFixture fixture) : EventStorePermanentTests(output, fixture) { [Theory] [InlineData(0)] public async Task count_le_equal_zero_throws(long maxCount) { @@ -159,7 +159,7 @@ await Fixture.Streams.AppendToStreamAsync( [Fact] public async Task populates_log_position_of_event() { - if (EventStoreTestServer.Version.Major < 22) + if (KurrentPermanentTestNode.Version.Major < 22) return; var stream = Fixture.GetStreamName(); @@ -191,7 +191,7 @@ public async Task stream_not_found() { [Fact] public async Task stream_found() { const int eventCount = 64; - + var events = Fixture.CreateTestEvents(eventCount).ToArray(); var streamName = Fixture.GetStreamName(); @@ -226,7 +226,7 @@ public async Task stream_found() { [Fact] public async Task stream_found_truncated() { const int eventCount = 64; - + var events = Fixture.CreateTestEvents(eventCount).ToArray(); var streamName = Fixture.GetStreamName(); @@ -263,4 +263,4 @@ await Fixture.Streams.SetStreamMetadataAsync( result[^1] ); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Streams.Tests/Read/read_stream_when_having_max_count_set_for_stream.cs b/test/EventStore.Client.Tests/Streams/Read/ReadStreamWhenHavingMaxCountSetForStreamTests.cs similarity index 93% rename from test/EventStore.Client.Streams.Tests/Read/read_stream_when_having_max_count_set_for_stream.cs rename to test/EventStore.Client.Tests/Streams/Read/ReadStreamWhenHavingMaxCountSetForStreamTests.cs index 0142ebd9a..fbd2696f1 100644 --- a/test/EventStore.Client.Streams.Tests/Read/read_stream_when_having_max_count_set_for_stream.cs +++ b/test/EventStore.Client.Tests/Streams/Read/ReadStreamWhenHavingMaxCountSetForStreamTests.cs @@ -1,8 +1,12 @@ -namespace EventStore.Client.Streams.Tests.Read; +using EventStore.Client.Tests.TestNode; +using EventStore.Client.Tests; + +namespace EventStore.Client.Tests; [Trait("Category", "Target:Stream")] [Trait("Category", "Operation:Read")] -public class read_stream_when_having_max_count_set_for_stream (ITestOutputHelper output, EventStoreFixture fixture) : EventStoreTests(output, fixture) { +public class ReadStreamWhenHavingMaxCountSetForStreamTests(ITestOutputHelper output, KurrentTemporaryFixture fixture) + : KurrentTemporaryTests(output, fixture) { [Fact] public async Task read_stream_forwards_respects_max_count() { var stream = Fixture.GetStreamName(); @@ -118,4 +122,4 @@ public async Task after_setting_more_strict_max_count_read_stream_backwards_read Assert.Equal(2, actual.Length); Assert.True(EventDataComparer.Equal(expected.Skip(3).Reverse().ToArray(), actual)); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Streams.Tests/Delete/soft_deleted_stream.cs b/test/EventStore.Client.Tests/Streams/SoftDeleteTests.cs similarity index 94% rename from test/EventStore.Client.Streams.Tests/Delete/soft_deleted_stream.cs rename to test/EventStore.Client.Tests/Streams/SoftDeleteTests.cs index 25877d2ee..7560167b8 100644 --- a/test/EventStore.Client.Streams.Tests/Delete/soft_deleted_stream.cs +++ b/test/EventStore.Client.Tests/Streams/SoftDeleteTests.cs @@ -1,12 +1,13 @@ using System.Text.Json; -namespace EventStore.Client.Streams.Tests.Delete; +namespace EventStore.Client.Tests.Streams; +[Trait("Category", "Target:Stream")] [Trait("Category", "Operation:Delete")] -public class deleted_stream(ITestOutputHelper output, EventStoreFixture fixture) : EventStoreTests(output, fixture) { +public class SoftDeleteTests(ITestOutputHelper output, KurrentPermanentFixture fixture) : EventStorePermanentTests(output, fixture) { static JsonDocument CustomMetadata { get; } - static deleted_stream() { + static SoftDeleteTests() { var customMetadata = new Dictionary { ["key1"] = true, ["key2"] = 17, @@ -15,7 +16,7 @@ static deleted_stream() { CustomMetadata = JsonDocument.Parse(JsonSerializer.Serialize(customMetadata)); } - + [Fact] public async Task reading_throws() { var stream = Fixture.GetStreamName(); @@ -36,13 +37,7 @@ await Assert.ThrowsAsync( ); } - public static IEnumerable RecreatingTestCases() { - yield return new object?[] { StreamState.Any, nameof(StreamState.Any) }; - yield return new object?[] { StreamState.NoStream, nameof(StreamState.NoStream) }; - } - - [Theory] - [MemberData(nameof(RecreatingTestCases))] + [Theory, RecreatingTestCases] public async Task recreated_with_any_expected_version(StreamState expectedState, string name) { var stream = $"{Fixture.GetStreamName()}_{name}"; @@ -124,7 +119,7 @@ public async Task recreated_with_expected_version() { [Fact] public async Task recreated_preserves_metadata_except_truncate_before() { - const int count = 2; + const int count = 2; var stream = Fixture.GetStreamName(); @@ -213,9 +208,7 @@ await Fixture.Streams.AppendToStreamAsync( Assert.Equal(SystemStreams.MetastreamOf(stream), ex.Stream); - await Assert.ThrowsAsync( - () => Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, Fixture.CreateTestEvents()) - ); + await Assert.ThrowsAsync(() => Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, Fixture.CreateTestEvents())); } [Fact] @@ -366,7 +359,7 @@ await Assert.ThrowsAsync( [Fact] public async Task recreated_on_non_empty_when_metadata_set() { - const int count = 2; + const int count = 2; var stream = Fixture.GetStreamName(); @@ -420,4 +413,11 @@ public async Task recreated_on_non_empty_when_metadata_set() { Assert.Equal(expected, metadataResult.Metadata); } -} \ No newline at end of file + + class RecreatingTestCases : TestCaseGenerator { + protected override IEnumerable Data() { + yield return [StreamState.Any, nameof(StreamState.Any)]; + yield return [StreamState.NoStream, nameof(StreamState.NoStream)]; + } + } +} diff --git a/test/EventStore.Client.Streams.Tests/Metadata/stream_metadata.cs b/test/EventStore.Client.Tests/Streams/StreamMetadataTests.cs similarity index 92% rename from test/EventStore.Client.Streams.Tests/Metadata/stream_metadata.cs rename to test/EventStore.Client.Tests/Streams/StreamMetadataTests.cs index 706d5e2b6..5ba987732 100644 --- a/test/EventStore.Client.Streams.Tests/Metadata/stream_metadata.cs +++ b/test/EventStore.Client.Tests/Streams/StreamMetadataTests.cs @@ -1,10 +1,11 @@ using System.Text.Json; using Grpc.Core; -namespace EventStore.Client.Streams.Tests.Metadata; +namespace EventStore.Client.Tests.Streams; -[Trait("Category", "Metadata")] -public class stream_metadata(ITestOutputHelper output, EventStoreFixture fixture) : EventStoreTests(output, fixture) { +[Trait("Category", "Target:Stream")] +[Trait("Category", "Operation:Metadata")] +public class StreamMetadataTests(ITestOutputHelper output, KurrentPermanentFixture fixture) : EventStorePermanentTests(output, fixture) { [Fact] public async Task getting_for_an_existing_stream_and_no_metadata_exists() { var stream = Fixture.GetStreamName(); @@ -150,7 +151,7 @@ public async Task latest_metadata_returned_stream_revision_any() { Assert.Equal(expected.CacheControl, actual.Metadata.CacheControl); Assert.Equal(expected.Acl, actual.Metadata.Acl); } - + [Fact] public async Task with_timeout_set_with_any_stream_revision_fails_when_operation_expired() { var stream = Fixture.GetStreamName(); @@ -186,9 +187,7 @@ public async Task with_timeout_set_with_stream_revision_fails_when_operation_exp [Fact] public async Task with_timeout_get_fails_when_operation_expired() { - var stream = Fixture.GetStreamName(); - var rpcException = await Assert.ThrowsAsync( - () => Fixture.Streams.GetStreamMetadataAsync(stream, TimeSpan.Zero) - ); + var stream = Fixture.GetStreamName(); + var rpcException = await Assert.ThrowsAsync(() => Fixture.Streams.GetStreamMetadataAsync(stream, TimeSpan.Zero)); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream.cs b/test/EventStore.Client.Tests/Streams/SubscribeToStreamTests.cs similarity index 80% rename from test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream.cs rename to test/EventStore.Client.Tests/Streams/SubscribeToStreamTests.cs index d38391e8f..00d38e1e5 100644 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream.cs +++ b/test/EventStore.Client.Tests/Streams/SubscribeToStreamTests.cs @@ -1,10 +1,10 @@ -namespace EventStore.Client.Streams.Tests.Subscriptions; +namespace EventStore.Client.Tests.Streams; [Trait("Category", "Subscriptions")] [Trait("Category", "Target:Stream")] -public class subscribe_to_stream(ITestOutputHelper output, SubscriptionsFixture fixture) - : EventStoreTests(output, fixture) { - [Fact] +public class SubscribeToStreamTests(ITestOutputHelper output, SubscribeToStreamTests.CustomFixture fixture) + : EventStorePermanentTests(output, fixture) { + [RetryFact] public async Task receives_all_events_from_start() { var streamName = Fixture.GetStreamName(); @@ -43,7 +43,7 @@ async Task Subscribe() { } } - [Fact] + [RetryFact] public async Task receives_all_events_from_position() { var streamName = Fixture.GetStreamName(); @@ -91,7 +91,7 @@ async Task Subscribe() { } } - [Fact] + [RetryFact] public async Task receives_all_events_from_non_existing_stream() { var streamName = Fixture.GetStreamName(); @@ -127,7 +127,7 @@ async Task Subscribe() { } } - [Fact] + [RetryFact] public async Task allow_multiple_subscriptions_to_same_stream() { var streamName = Fixture.GetStreamName(); @@ -170,7 +170,7 @@ async Task Subscribe(IAsyncEnumerator subscription) { } } - [Fact] + [RetryFact] public async Task drops_when_stream_tombstoned() { var streamName = Fixture.GetStreamName(); @@ -193,41 +193,18 @@ public async Task drops_when_stream_tombstoned() { ex.ShouldBeOfType().Stream.ShouldBe(streamName); } - [Fact] - public async Task receives_all_events_with_resolved_links() { - var streamName = Fixture.GetStreamName(); - - var seedEvents = Fixture.CreateTestEvents(3).ToArray(); - var availableEvents = new HashSet(seedEvents.Select(x => x.EventId)); - - await Fixture.Streams.AppendToStreamAsync(streamName, StreamState.NoStream, seedEvents); - - await using var subscription = - Fixture.Streams.SubscribeToStream($"$et-{EventStoreFixture.TestEventType}", FromStream.Start, true); - - await using var enumerator = subscription.Messages.GetAsyncEnumerator(); - - Assert.True(await enumerator.MoveNextAsync()); - - Assert.IsType(enumerator.Current); - - await Subscribe().WithTimeout(); - - return; - - async Task Subscribe() { - while (await enumerator.MoveNextAsync()) { - if (enumerator.Current is not StreamMessage.Event(var resolvedEvent) || - !resolvedEvent.OriginalEvent.EventStreamId.StartsWith($"$et-{EventStoreFixture.TestEventType}")) { - continue; - } - - availableEvents.Remove(resolvedEvent.Event.EventId); - - if (availableEvents.Count == 0) { - return; - } - } + public class CustomFixture : KurrentPermanentFixture { + public CustomFixture() { + OnSetup = async () => { + await Streams.SetStreamMetadataAsync( + SystemStreams.AllStream, + StreamState.Any, + new(acl: new(SystemRoles.All)), + userCredentials: TestCredentials.Root + ); + + await Streams.AppendToStreamAsync($"SubscriptionsFixture-Noise-{Guid.NewGuid():N}", StreamState.NoStream, CreateTestEvents(10)); + }; } } } diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionFilter.cs b/test/EventStore.Client.Tests/Streams/SubscriptionFilter.cs similarity index 92% rename from test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionFilter.cs rename to test/EventStore.Client.Tests/Streams/SubscriptionFilter.cs index e670b69c9..937f7d1a2 100644 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionFilter.cs +++ b/test/EventStore.Client.Tests/Streams/SubscriptionFilter.cs @@ -1,8 +1,9 @@ -namespace EventStore.Client.Streams.Tests.Subscriptions; +// ReSharper disable InconsistentNaming +namespace EventStore.Client.Tests.Streams; public record SubscriptionFilter(string Name, Func Create, Func PrepareEvent) { public override string ToString() => Name; - + static readonly SubscriptionFilter StreamNamePrefix = new(nameof(StreamNamePrefix), StreamFilter.Prefix, (_, evt) => evt); static readonly SubscriptionFilter StreamNameRegex = new(nameof(StreamNameRegex), f => StreamFilter.RegularExpression(f), (_, evt) => evt); static readonly SubscriptionFilter EventTypePrefix = new(nameof(EventTypePrefix), EventTypeFilter.Prefix, (term, evt) => new(evt.EventId, term, evt.Data, evt.Metadata, evt.ContentType)); @@ -15,10 +16,10 @@ static SubscriptionFilter() { EventTypePrefix, EventTypeRegex }; - + TestCases = All.Select(x => new object[] { x }); } public static SubscriptionFilter[] All { get; } public static IEnumerable TestCases { get; } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests/UuidTests.cs b/test/EventStore.Client.Tests/UuidTests.cs index 35d833096..4533e5416 100644 --- a/test/EventStore.Client.Tests/UuidTests.cs +++ b/test/EventStore.Client.Tests/UuidTests.cs @@ -5,7 +5,7 @@ namespace EventStore.Client.Tests; public class UuidTests : ValueObjectTests { public UuidTests() : base(new ScenarioFixture()) { } - [Fact] + [RetryFact] public void ToGuidReturnsExpectedResult() { var guid = Guid.NewGuid(); var sut = Uuid.FromGuid(guid); @@ -13,21 +13,21 @@ public void ToGuidReturnsExpectedResult() { Assert.Equal(sut.ToGuid(), guid); } - [Fact] + [RetryFact] public void ToStringProducesExpectedResult() { var sut = Uuid.NewUuid(); Assert.Equal(sut.ToGuid().ToString(), sut.ToString()); } - [Fact] + [RetryFact] public void ToFormattedStringProducesExpectedResult() { var sut = Uuid.NewUuid(); Assert.Equal(sut.ToGuid().ToString("n"), sut.ToString("n")); } - [Fact] + [RetryFact] public void ToDtoReturnsExpectedResult() { var msb = GetRandomInt64(); var lsb = GetRandomInt64(); @@ -41,7 +41,7 @@ public void ToDtoReturnsExpectedResult() { Assert.Equal(msb, result.Structured.MostSignificantBits); } - [Fact] + [RetryFact] public void ParseReturnsExpectedResult() { var guid = Guid.NewGuid(); @@ -50,7 +50,7 @@ public void ParseReturnsExpectedResult() { Assert.Equal(Uuid.FromGuid(guid), sut); } - [Fact] + [RetryFact] public void FromInt64ReturnsExpectedResult() { var guid = Guid.Parse("65678f9b-d139-4786-8305-b9166922b378"); var sut = Uuid.FromInt64(7306966819824813958L, -9005588373953137800L); @@ -70,4 +70,4 @@ static long GetRandomInt64() { class ScenarioFixture : Fixture { public ScenarioFixture() => Customize(composer => composer.FromFactory(Uuid.FromGuid)); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests/ValueObjectTests.cs b/test/EventStore.Client.Tests/ValueObjectTests.cs index cce2526f7..c70b5f7d6 100644 --- a/test/EventStore.Client.Tests/ValueObjectTests.cs +++ b/test/EventStore.Client.Tests/ValueObjectTests.cs @@ -7,9 +7,9 @@ public abstract class ValueObjectTests { protected ValueObjectTests(Fixture fixture) => _fixture = fixture; - [Fact] + [RetryFact] public void ValueObjectIsWellBehaved() => _fixture.Create().Verify(typeof(T)); - [Fact] + [RetryFact] public void ValueObjectIsEquatable() => Assert.IsAssignableFrom>(_fixture.Create()); -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests/X509CertificatesTests.cs b/test/EventStore.Client.Tests/X509CertificatesTests.cs index dd32aabb0..5d70fdb89 100644 --- a/test/EventStore.Client.Tests/X509CertificatesTests.cs +++ b/test/EventStore.Client.Tests/X509CertificatesTests.cs @@ -3,30 +3,38 @@ namespace EventStore.Client.Tests; public class X509CertificatesTests { - [Fact] + [RetryFact] public void create_from_pem_file() { const string certPemFilePath = "certs/ca/ca.crt"; const string keyPemFilePath = "certs/ca/ca.key"; var rsa = X509Certificates.CreateFromPemFile(certPemFilePath, keyPemFilePath); +#if NET9_0_OR_GREATER + var cert = X509CertificateLoader.LoadCertificateFromFile(certPemFilePath); +#else var cert = new X509Certificate2(certPemFilePath); +#endif rsa.Issuer.ShouldBe(cert.Issuer); rsa.SerialNumber.ShouldBe(cert.SerialNumber); } - [Fact] + [RetryFact] public void create_from_pem_file_() { const string certPemFilePath = "certs/user-admin/user-admin.crt"; const string keyPemFilePath = "certs/user-admin/user-admin.key"; var rsa = X509Certificates.CreateFromPemFile(certPemFilePath, keyPemFilePath); +#if NET9_0_OR_GREATER + var cert = X509CertificateLoader.LoadCertificateFromFile(certPemFilePath); +#else var cert = new X509Certificate2(certPemFilePath); +#endif rsa.Issuer.ShouldBe(cert.Issuer); rsa.Subject.ShouldBe(cert.Subject); rsa.SerialNumber.ShouldBe(cert.SerialNumber); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.UserManagement.Tests/AssemblyInfo.cs b/test/EventStore.Client.UserManagement.Tests/AssemblyInfo.cs deleted file mode 100644 index b0b47aa73..000000000 --- a/test/EventStore.Client.UserManagement.Tests/AssemblyInfo.cs +++ /dev/null @@ -1 +0,0 @@ -[assembly: CollectionBehavior(DisableTestParallelization = true)] \ No newline at end of file diff --git a/test/EventStore.Client.UserManagement.Tests/EventStore.Client.UserManagement.Tests.csproj b/test/EventStore.Client.UserManagement.Tests/EventStore.Client.UserManagement.Tests.csproj deleted file mode 100644 index d4b52e67f..000000000 --- a/test/EventStore.Client.UserManagement.Tests/EventStore.Client.UserManagement.Tests.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - - EventStore.Client.Tests - - - - - - - - \ No newline at end of file diff --git a/test/EventStore.Client.UserManagement.Tests/EventStore.Client.UserManagement.Tests.csproj.DotSettings b/test/EventStore.Client.UserManagement.Tests/EventStore.Client.UserManagement.Tests.csproj.DotSettings deleted file mode 100644 index 1183b3a73..000000000 --- a/test/EventStore.Client.UserManagement.Tests/EventStore.Client.UserManagement.Tests.csproj.DotSettings +++ /dev/null @@ -1,2 +0,0 @@ - - True \ No newline at end of file diff --git a/test/EventStore.Client.UserManagement.Tests/InvalidCredentialsTestCases.cs b/test/EventStore.Client.UserManagement.Tests/InvalidCredentialsTestCases.cs deleted file mode 100644 index e32a340bd..000000000 --- a/test/EventStore.Client.UserManagement.Tests/InvalidCredentialsTestCases.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Collections; - -namespace EventStore.Client.Tests; - -public abstract record InvalidCredentialsTestCase(TestUser User, Type ExpectedException); - -public class InvalidCredentialsTestCases : IEnumerable { - public IEnumerator GetEnumerator() { - yield return new object?[] { new MissingCredentials() }; - yield return new object?[] { new WrongUsername() }; - yield return new object?[] { new WrongPassword() }; - } - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - public record MissingCredentials() - : InvalidCredentialsTestCase(Fakers.Users.WithNoCredentials(), typeof(AccessDeniedException)) { - public override string ToString() => nameof(MissingCredentials); - } - - public record WrongUsername() - : InvalidCredentialsTestCase(Fakers.Users.WithInvalidCredentials(false), typeof(NotAuthenticatedException)) { - public override string ToString() => nameof(WrongUsername); - } - - public record WrongPassword() - : InvalidCredentialsTestCase(Fakers.Users.WithInvalidCredentials(wrongPassword: false), typeof(NotAuthenticatedException)) { - public override string ToString() => nameof(WrongPassword); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.UserManagement.Tests/UserCredentialsTests.cs b/test/EventStore.Client.UserManagement.Tests/UserCredentialsTests.cs deleted file mode 100644 index c8eb0a570..000000000 --- a/test/EventStore.Client.UserManagement.Tests/UserCredentialsTests.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System.Net.Http.Headers; -using System.Text; -using static System.Convert; - -namespace EventStore.Client.Tests; - -public class UserCredentialsTests { - const string JwtToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9." - + "eyJzdWIiOiI5OSIsIm5hbWUiOiJKb2huIFdpY2siLCJpYXQiOjE1MTYyMzkwMjJ9." - + "MEdv44JIdlLh-GgqxOTZD7DHq28xJowhQFmDnT3NDIE"; - - static readonly UTF8Encoding Utf8NoBom = new(false); - - static string EncodeCredentials(string username, string password) => ToBase64String(Utf8NoBom.GetBytes($"{username}:{password}")); - - [Fact] - public void from_username_and_password() { - var user = Fakers.Users.WithNonAsciiPassword(); - - var value = new AuthenticationHeaderValue( - Constants.Headers.BasicScheme, - EncodeCredentials(user.LoginName, user.Password) - ); - - var basicAuthInfo = value.ToString(); - - var credentials = new UserCredentials(user.LoginName, user.Password); - - credentials.Username.ShouldBe(user.LoginName); - credentials.Password.ShouldBe(user.Password); - credentials.ToString().ShouldBe(basicAuthInfo); - } - - [Fact] - public void from_bearer_token() { - var credentials = new UserCredentials(JwtToken); - - credentials.Username.ShouldBeNull(); - credentials.Password.ShouldBeNull(); - credentials.ToString().ShouldBe($"Bearer {JwtToken}"); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.UserManagement.Tests/changing_user_password.cs b/test/EventStore.Client.UserManagement.Tests/changing_user_password.cs deleted file mode 100644 index d3931c1ea..000000000 --- a/test/EventStore.Client.UserManagement.Tests/changing_user_password.cs +++ /dev/null @@ -1,76 +0,0 @@ -namespace EventStore.Client.Tests; - -public class changing_user_password : IClassFixture { - public changing_user_password(ITestOutputHelper output, EventStoreFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); - - EventStoreFixture Fixture { get; } - - public static IEnumerable NullInputCases() { - yield return Fakers.Users.Generate().WithResult(x => new object?[] { null, x.Password, x.Password, "loginName" }); - yield return Fakers.Users.Generate().WithResult(x => new object?[] { x.LoginName, null, x.Password, "currentPassword" }); - yield return Fakers.Users.Generate().WithResult(x => new object?[] { x.LoginName, x.Password, null, "newPassword" }); - } - - [Theory] - [MemberData(nameof(NullInputCases))] - public async Task with_null_input_throws(string loginName, string currentPassword, string newPassword, string paramName) { - var ex = await Fixture.Users - .ChangePasswordAsync(loginName, currentPassword, newPassword, userCredentials: TestCredentials.Root) - .ShouldThrowAsync(); - - ex.ParamName.ShouldBe(paramName); - } - - public static IEnumerable EmptyInputCases() { - yield return Fakers.Users.Generate().WithResult(x => new object?[] { string.Empty, x.Password, x.Password, "loginName" }); - yield return Fakers.Users.Generate().WithResult(x => new object?[] { x.LoginName, string.Empty, x.Password, "currentPassword" }); - yield return Fakers.Users.Generate().WithResult(x => new object?[] { x.LoginName, x.Password, string.Empty, "newPassword" }); - } - - [Theory] - [MemberData(nameof(EmptyInputCases))] - public async Task with_empty_input_throws(string loginName, string currentPassword, string newPassword, string paramName) { - var ex = await Fixture.Users - .ChangePasswordAsync(loginName, currentPassword, newPassword, userCredentials: TestCredentials.Root) - .ShouldThrowAsync(); - - ex.ParamName.ShouldBe(paramName); - } - - [Theory(Skip = "This can't be right")] - [ClassData(typeof(InvalidCredentialsTestCases))] - public async Task with_user_with_insufficient_credentials_throws(string loginName, UserCredentials userCredentials) { - await Fixture.Users.CreateUserAsync(loginName, "Full Name", Array.Empty(), "password", userCredentials: TestCredentials.Root); - - await Fixture.Users - .ChangePasswordAsync(loginName, "password", "newPassword", userCredentials: userCredentials) - .ShouldThrowAsync(); - } - - [Fact] - public async Task when_the_current_password_is_wrong_throws() { - var user = await Fixture.CreateTestUser(); - - await Fixture.Users - .ChangePasswordAsync(user.LoginName, "wrong-password", "new-password", userCredentials: TestCredentials.Root) - .ShouldThrowAsync(); - } - - [Fact] - public async Task with_correct_credentials() { - var user = await Fixture.CreateTestUser(); - - await Fixture.Users - .ChangePasswordAsync(user.LoginName, user.Password, "new-password", userCredentials: TestCredentials.Root) - .ShouldNotThrowAsync(); - } - - [Fact] - public async Task with_own_credentials() { - var user = await Fixture.CreateTestUser(); - - await Fixture.Users - .ChangePasswordAsync(user.LoginName, user.Password, "new-password", userCredentials: user.Credentials) - .ShouldNotThrowAsync(); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.UserManagement.Tests/creating_a_user.cs b/test/EventStore.Client.UserManagement.Tests/creating_a_user.cs deleted file mode 100644 index abd37bab1..000000000 --- a/test/EventStore.Client.UserManagement.Tests/creating_a_user.cs +++ /dev/null @@ -1,84 +0,0 @@ -namespace EventStore.Client.Tests; - -public class creating_a_user : IClassFixture { - public creating_a_user(ITestOutputHelper outputHelper, InsecureClientTestFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(outputHelper)); - - InsecureClientTestFixture Fixture { get; } - - public static IEnumerable NullInputCases() { - yield return Fakers.Users.Generate().WithResult(x => new object?[] { null, x.FullName, x.Groups, x.Password, "loginName" }); - yield return Fakers.Users.Generate().WithResult(x => new object?[] { x.LoginName, null, x.Groups, x.Password, "fullName" }); - yield return Fakers.Users.Generate().WithResult(x => new object?[] { x.LoginName, x.FullName, null, x.Password, "groups" }); - yield return Fakers.Users.Generate().WithResult(x => new object?[] { x.LoginName, x.FullName, x.Groups, null, "password" }); - } - - [Theory] - [MemberData(nameof(NullInputCases))] - public async Task with_null_input_throws(string loginName, string fullName, string[] groups, string password, string paramName) { - var ex = await Fixture.Users - .CreateUserAsync(loginName, fullName, groups, password, userCredentials: TestCredentials.Root) - .ShouldThrowAsync(); - - ex.ParamName.ShouldBe(paramName); - } - - public static IEnumerable EmptyInputCases() { - yield return Fakers.Users.Generate().WithResult(x => new object?[] { string.Empty, x.FullName, x.Groups, x.Password, "loginName" }); - yield return Fakers.Users.Generate().WithResult(x => new object?[] { x.LoginName, string.Empty, x.Groups, x.Password, "fullName" }); - yield return Fakers.Users.Generate().WithResult(x => new object?[] { x.LoginName, x.FullName, x.Groups, string.Empty, "password" }); - } - - [Theory] - [MemberData(nameof(EmptyInputCases))] - public async Task with_empty_input_throws(string loginName, string fullName, string[] groups, string password, string paramName) { - var ex = await Fixture.Users - .CreateUserAsync(loginName, fullName, groups, password, userCredentials: TestCredentials.Root) - .ShouldThrowAsync(); - - ex.ParamName.ShouldBe(paramName); - } - - [Fact] - public async Task with_password_containing_ascii_chars() { - var user = Fakers.Users.Generate(); - - await Fixture.Users - .CreateUserAsync(user.LoginName, user.FullName, user.Groups, user.Password, userCredentials: TestCredentials.Root) - .ShouldNotThrowAsync(); - } - - [Theory] - [ClassData(typeof(InvalidCredentialsTestCases))] - public async Task with_user_with_insufficient_credentials_throws(InvalidCredentialsTestCase testCase) => - await Fixture.Users - .CreateUserAsync(testCase.User.LoginName, testCase.User.FullName, testCase.User.Groups, testCase.User.Password, userCredentials: testCase.User.Credentials) - .ShouldThrowAsync(testCase.ExpectedException); - - [Fact] - public async Task can_be_read() { - var user = Fakers.Users.Generate(); - - await Fixture.Users - .CreateUserAsync( - user.LoginName, - user.FullName, - user.Groups, - user.Password, - userCredentials: TestCredentials.Root - ) - .ShouldNotThrowAsync(); - - var actual = await Fixture.Users.GetUserAsync(user.LoginName, userCredentials: TestCredentials.Root); - - var expected = new UserDetails( - user.Details.LoginName, - user.Details.FullName, - user.Details.Groups, - user.Details.Disabled, - actual.DateLastUpdated - ); - - actual.ShouldBeEquivalentTo(expected); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.UserManagement.Tests/deleting_a_user.cs b/test/EventStore.Client.UserManagement.Tests/deleting_a_user.cs deleted file mode 100644 index 9f5948fb6..000000000 --- a/test/EventStore.Client.UserManagement.Tests/deleting_a_user.cs +++ /dev/null @@ -1,68 +0,0 @@ -namespace EventStore.Client.Tests; - -public class deleting_a_user : IClassFixture { - public deleting_a_user(ITestOutputHelper output, InsecureClientTestFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - InsecureClientTestFixture Fixture { get; } - - [Fact] - public async Task with_null_input_throws() { - var ex = await Fixture.Users - .DeleteUserAsync(null!, userCredentials: TestCredentials.Root) - .ShouldThrowAsync(); - - ex.ParamName.ShouldBe("loginName"); - } - - [Fact] - public async Task with_empty_input_throws() { - var ex = await Fixture.Users - .DeleteUserAsync(string.Empty, userCredentials: TestCredentials.Root) - .ShouldThrowAsync(); - - ex.ParamName.ShouldBe("loginName"); - } - - [Theory] - [ClassData(typeof(InvalidCredentialsTestCases))] - public async Task with_user_with_insufficient_credentials_throws(InvalidCredentialsTestCase testCase) { - await Fixture.Users.CreateUserAsync( - testCase.User.LoginName, - testCase.User.FullName, - testCase.User.Groups, - testCase.User.Password, - userCredentials: TestCredentials.Root - ); - - await Fixture.Users - .DeleteUserAsync(testCase.User.LoginName, userCredentials: testCase.User.Credentials) - .ShouldThrowAsync(testCase.ExpectedException); - } - - [Fact] - public async Task cannot_be_read() { - var user = await Fixture.CreateTestUser(); - - await Fixture.Users.DeleteUserAsync(user.LoginName, userCredentials: TestCredentials.Root); - - var ex = await Fixture.Users - .GetUserAsync(user.LoginName, userCredentials: TestCredentials.Root) - .ShouldThrowAsync(); - - ex.LoginName.ShouldBe(user.LoginName); - } - - [Fact] - public async Task a_second_time_throws() { - var user = await Fixture.CreateTestUser(); - - await Fixture.Users.DeleteUserAsync(user.LoginName, userCredentials: TestCredentials.Root); - - var ex = await Fixture.Users - .DeleteUserAsync(user.LoginName, userCredentials: TestCredentials.Root) - .ShouldThrowAsync(); - - ex.LoginName.ShouldBe(user.LoginName); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.UserManagement.Tests/disabling_a_user.cs b/test/EventStore.Client.UserManagement.Tests/disabling_a_user.cs deleted file mode 100644 index c72ab0295..000000000 --- a/test/EventStore.Client.UserManagement.Tests/disabling_a_user.cs +++ /dev/null @@ -1,64 +0,0 @@ -namespace EventStore.Client.Tests; - -public class disabling_a_user : IClassFixture { - public disabling_a_user(ITestOutputHelper output, InsecureClientTestFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); - - InsecureClientTestFixture Fixture { get; } - - [Fact] - public async Task with_null_input_throws() { - var ex = await Fixture.Users - .DisableUserAsync(null!, userCredentials: TestCredentials.Root) - .ShouldThrowAsync(); - - // must fix since it is returning value instead of param name - //ex.ParamName.ShouldBe("loginName"); - } - - [Fact] - public async Task with_empty_input_throws() { - var ex = await Fixture.Users - .DisableUserAsync(string.Empty, userCredentials: TestCredentials.Root) - .ShouldThrowAsync(); - - ex.ParamName.ShouldBe("loginName"); - } - - [Theory] - [ClassData(typeof(InvalidCredentialsTestCases))] - public async Task with_user_with_insufficient_credentials_throws(InvalidCredentialsTestCase testCase) { - await Fixture.Users.CreateUserAsync( - testCase.User.LoginName, - testCase.User.FullName, - testCase.User.Groups, - testCase.User.Password, - userCredentials: TestCredentials.Root - ); - - await Fixture.Users - .DisableUserAsync(testCase.User.LoginName, userCredentials: testCase.User.Credentials) - .ShouldThrowAsync(testCase.ExpectedException); - } - - [Fact] - public async Task that_was_disabled() { - var user = await Fixture.CreateTestUser(); - - await Fixture.Users - .DisableUserAsync(user.LoginName, userCredentials: TestCredentials.Root) - .ShouldNotThrowAsync(); - - await Fixture.Users - .DisableUserAsync(user.LoginName, userCredentials: TestCredentials.Root) - .ShouldNotThrowAsync(); - } - - [Fact] - public async Task that_is_enabled() { - var user = await Fixture.CreateTestUser(); - - await Fixture.Users - .DisableUserAsync(user.LoginName, userCredentials: TestCredentials.Root) - .ShouldNotThrowAsync(); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.UserManagement.Tests/enabling_a_user.cs b/test/EventStore.Client.UserManagement.Tests/enabling_a_user.cs deleted file mode 100644 index 79755e891..000000000 --- a/test/EventStore.Client.UserManagement.Tests/enabling_a_user.cs +++ /dev/null @@ -1,62 +0,0 @@ -namespace EventStore.Client.Tests; - -public class enabling_a_user : IClassFixture { - public enabling_a_user(ITestOutputHelper output, InsecureClientTestFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - InsecureClientTestFixture Fixture { get; } - - [Fact] - public async Task with_null_input_throws() { - var ex = await Fixture.Users - .EnableUserAsync(null!, userCredentials: TestCredentials.Root) - .ShouldThrowAsync(); - - ex.ParamName.ShouldBe("loginName"); - } - - [Fact] - public async Task with_empty_input_throws() { - var ex = await Fixture.Users - .EnableUserAsync(string.Empty, userCredentials: TestCredentials.Root) - .ShouldThrowAsync(); - - ex.ParamName.ShouldBe("loginName"); - } - - [Theory] - [ClassData(typeof(InvalidCredentialsTestCases))] - public async Task with_user_with_insufficient_credentials_throws(InvalidCredentialsTestCase testCase) { - await Fixture.Users.CreateUserAsync( - testCase.User.LoginName, - testCase.User.FullName, - testCase.User.Groups, - testCase.User.Password, - userCredentials: TestCredentials.Root - ); - - await Fixture.Users - .EnableUserAsync(testCase.User.LoginName, userCredentials: testCase.User.Credentials) - .ShouldThrowAsync(testCase.ExpectedException); - } - - [Fact] - public async Task that_was_disabled() { - var user = await Fixture.CreateTestUser(); - - await Fixture.Users.DisableUserAsync(user.LoginName, userCredentials: TestCredentials.Root); - - await Fixture.Users - .EnableUserAsync(user.LoginName, userCredentials: TestCredentials.Root) - .ShouldNotThrowAsync(); - } - - [Fact] - public async Task that_is_enabled() { - var user = await Fixture.CreateTestUser(); - - await Fixture.Users - .EnableUserAsync(user.LoginName, userCredentials: TestCredentials.Root) - .ShouldNotThrowAsync(); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.UserManagement.Tests/getting_current_user.cs b/test/EventStore.Client.UserManagement.Tests/getting_current_user.cs deleted file mode 100644 index b0cb3af2d..000000000 --- a/test/EventStore.Client.UserManagement.Tests/getting_current_user.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace EventStore.Client.Tests; - -public class getting_current_user : IClassFixture { - public getting_current_user(ITestOutputHelper output, EventStoreFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - EventStoreFixture Fixture { get; } - - [Fact] - public async Task returns_the_current_user() { - var user = await Fixture.Users.GetCurrentUserAsync(TestCredentials.Root); - user.LoginName.ShouldBe(TestCredentials.Root.Username); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.UserManagement.Tests/listing_users.cs b/test/EventStore.Client.UserManagement.Tests/listing_users.cs deleted file mode 100644 index 4760e7898..000000000 --- a/test/EventStore.Client.UserManagement.Tests/listing_users.cs +++ /dev/null @@ -1,42 +0,0 @@ -namespace EventStore.Client.Tests; - -public class listing_users : IClassFixture { - public listing_users(ITestOutputHelper output, EventStoreFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - EventStoreFixture Fixture { get; } - - [Fact] - public async Task returns_all_created_users() { - var seed = await Fixture.CreateTestUsers(); - - var admin = new UserDetails("admin", "Event Store Administrator", new[] { "$admins" }, false, default); - var ops = new UserDetails("ops", "Event Store Operations", new[] { "$ops" }, false, default); - - var expected = new[] { admin, ops } - .Concat(seed.Select(user => user.Details)) - .ToArray(); - - var actual = await Fixture.Users - .ListAllAsync(userCredentials: TestCredentials.Root) - .Select(user => new UserDetails(user.LoginName, user.FullName, user.Groups, user.Disabled, default)) - .ToArrayAsync(); - - expected.ShouldBeSubsetOf(actual); - } - - [Fact] - public async Task returns_all_system_users() { - var admin = new UserDetails("admin", "Event Store Administrator", new[] { "$admins" }, false, default); - var ops = new UserDetails("ops", "Event Store Operations", new[] { "$ops" }, false, default); - - var expected = new[] { admin, ops }; - - var actual = await Fixture.Users - .ListAllAsync(userCredentials: TestCredentials.Root) - .Select(user => new UserDetails(user.LoginName, user.FullName, user.Groups, user.Disabled, default)) - .ToArrayAsync(); - - expected.ShouldBeSubsetOf(actual); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.UserManagement.Tests/resetting_user_password.cs b/test/EventStore.Client.UserManagement.Tests/resetting_user_password.cs deleted file mode 100644 index 549e7119b..000000000 --- a/test/EventStore.Client.UserManagement.Tests/resetting_user_password.cs +++ /dev/null @@ -1,80 +0,0 @@ -namespace EventStore.Client.Tests; - -public class resetting_user_password : IClassFixture { - public resetting_user_password(ITestOutputHelper output, InsecureClientTestFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - InsecureClientTestFixture Fixture { get; } - - public static IEnumerable NullInputCases() { - yield return Fakers.Users.Generate().WithResult(x => new object?[] { null, x.Password, "loginName" }); - yield return Fakers.Users.Generate().WithResult(x => new object?[] { x.LoginName, null, "newPassword" }); - } - - [Theory] - [MemberData(nameof(NullInputCases))] - public async Task with_null_input_throws(string loginName, string newPassword, string paramName) { - var ex = await Fixture.Users - .ResetPasswordAsync(loginName, newPassword, userCredentials: TestCredentials.Root) - .ShouldThrowAsync(); - - ex.ParamName.ShouldBe(paramName); - } - - public static IEnumerable EmptyInputCases() { - yield return Fakers.Users.Generate().WithResult(x => new object?[] { string.Empty, x.Password, "loginName" }); - yield return Fakers.Users.Generate().WithResult(x => new object?[] { x.LoginName, string.Empty, "newPassword" }); - } - - [Theory] - [MemberData(nameof(EmptyInputCases))] - public async Task with_empty_input_throws(string loginName, string newPassword, string paramName) { - var ex = await Fixture.Users - .ResetPasswordAsync(loginName, newPassword, userCredentials: TestCredentials.Root) - .ShouldThrowAsync(); - - ex.ParamName.ShouldBe(paramName); - } - - [Theory] - [ClassData(typeof(InvalidCredentialsTestCases))] - public async Task with_user_with_insufficient_credentials_throws(InvalidCredentialsTestCase testCase) { - await Fixture.Users.CreateUserAsync( - testCase.User.LoginName, - testCase.User.FullName, - testCase.User.Groups, - testCase.User.Password, - userCredentials: TestCredentials.Root - ); - - await Fixture.Users - .ResetPasswordAsync(testCase.User.LoginName, "newPassword", userCredentials: testCase.User.Credentials) - .ShouldThrowAsync(testCase.ExpectedException); - } - - [Fact] - public async Task with_correct_credentials() { - var user = Fakers.Users.Generate(); - - await Fixture.Users.CreateUserAsync( - user.LoginName, - user.FullName, - user.Groups, - user.Password, - userCredentials: TestCredentials.Root - ); - - await Fixture.Users - .ResetPasswordAsync(user.LoginName, "new-password", userCredentials: TestCredentials.Root) - .ShouldNotThrowAsync(); - } - - [Fact] - public async Task with_own_credentials_throws() { - var user = await Fixture.CreateTestUser(); - - await Fixture.Users - .ResetPasswordAsync(user.LoginName, "new-password", userCredentials: user.Credentials) - .ShouldThrowAsync(); - } -} \ No newline at end of file