From d4e714ecdf8e4056fde90ceddc677c37f436bf79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Silveira?= Date: Wed, 29 Nov 2023 16:03:37 +0100 Subject: [PATCH 01/22] removed net 5.0 added net 8.0 updated test nuget packages updated ci workflows updated samples a bit --- .github/workflows/base.yml | 4 +- .github/workflows/ci.yml | 4 +- .github/workflows/publish.yml | 16 +- Directory.Build.props | 3 +- EventStore.Client.sln.DotSettings | 8 +- samples/.dockerignore | 25 + samples/Directory.Build.props | 7 +- samples/Samples.sln.DotSettings | 1 + samples/appending-events/Program.cs | 310 +++---- samples/connecting-to-a-cluster/Program.cs | 65 +- .../DemoInterceptor.cs | 43 +- .../connecting-to-a-single-node/Program.cs | 147 ++-- samples/persistent-subscriptions/Program.cs | 482 +++++------ samples/projection-management/Program.cs | 755 ++++++++++-------- samples/quick-start/Program.cs | 146 ++-- samples/quick-start/docker-compose.yml | 2 +- samples/reading-events/Program.cs | 562 ++++++------- samples/secure-with-tls/Program.cs | 109 ++- samples/secure-with-tls/docker-compose.yml | 4 +- samples/server-side-filtering/Program.cs | 326 ++++---- .../Controllers/EventStoreController.cs | 4 +- .../Program.cs | 28 +- .../Startup.cs | 61 +- samples/subscribing-to-streams/Program.cs | 316 ++++---- test/Directory.Build.props | 6 +- .../EventStore.Client.Tests.Common.csproj | 15 +- .../EventStore.Client.Tests.csproj | 8 +- 27 files changed, 1788 insertions(+), 1669 deletions(-) create mode 100644 samples/.dockerignore diff --git a/.github/workflows/base.yml b/.github/workflows/base.yml index b9b042301..c0c57f739 100644 --- a/.github/workflows/base.yml +++ b/.github/workflows/base.yml @@ -13,7 +13,7 @@ jobs: strategy: fail-fast: false matrix: - framework: [ net5.0, net6.0, net7.0 ] + framework: [ net6.0, net7.0, net8.0 ] os: [ ubuntu-latest ] test: [ Streams, PersistentSubscriptions, Operations, UserManagement, ProjectionManagement ] configuration: [ release ] @@ -33,9 +33,9 @@ jobs: uses: actions/setup-dotnet@v3 with: dotnet-version: | - 5.0.x 6.0.x 7.0.x + 8.0.x - name: Compile shell: bash run: | diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 16e37e13d..31add45a8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,9 +4,9 @@ on: pull_request: push: branches: - - master + - master tags: - - v* + - v* jobs: test: diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index f3d7df4f9..02f79aa37 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -14,7 +14,7 @@ jobs: strategy: fail-fast: false matrix: - framework: [ net5.0, net6.0, net7.0 ] + framework: [ net6.0, net7.0, net8.0 ] os: [ ubuntu-latest, windows-latest ] runs-on: ${{ matrix.os }} name: scan-vulnerabilities/${{ matrix.os }}/${{ matrix.framework }} @@ -25,9 +25,9 @@ jobs: uses: actions/setup-dotnet@v3 with: dotnet-version: | - 5.0.x 6.0.x 7.0.x + 8.0.x - name: Scan for Vulnerabilities shell: bash run: | @@ -43,7 +43,7 @@ jobs: strategy: fail-fast: false matrix: - framework: [ net5.0, net6.0, net7.0 ] + framework: [ net8.0 ] services: esdb: image: ghcr.io/eventstore/eventstore:lts @@ -62,9 +62,7 @@ jobs: uses: actions/setup-dotnet@v3 with: dotnet-version: | - 5.0.x - 6.0.x - 7.0.x + 8.0.x - name: Compile shell: bash run: | @@ -79,7 +77,7 @@ jobs: strategy: fail-fast: false matrix: - framework: [ net5.0, net6.0, net7.0 ] + framework: [ net6.0, net7.0, net8.0 ] os: [ ubuntu-latest, windows-latest ] configuration: [ release ] runs-on: ${{ matrix.os }} @@ -94,9 +92,9 @@ jobs: uses: actions/setup-dotnet@v3 with: dotnet-version: | - 5.0.x 6.0.x 7.0.x + 8.0.x - name: Compile shell: bash run: | @@ -132,9 +130,9 @@ jobs: uses: actions/setup-dotnet@v3 with: dotnet-version: | - 5.0.x 6.0.x 7.0.x + 8.0.x - name: Dotnet Pack shell: bash run: | diff --git a/Directory.Build.props b/Directory.Build.props index 3ed57a184..2e2b7fb3b 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,6 @@ - net5.0;net6.0;net7.0; - x64 + net6.0;net7.0;net8.0 true enable enable diff --git a/EventStore.Client.sln.DotSettings b/EventStore.Client.sln.DotSettings index 16d970453..671c31c8a 100644 --- a/EventStore.Client.sln.DotSettings +++ b/EventStore.Client.sln.DotSettings @@ -26,16 +26,16 @@ &lt;inspection_tool class="UnnecessaryReturnJS" enabled="false" level="WARNING" enabled_by_default="false" /&gt; &lt;/profile&gt;</IDEA_SETTINGS><RIDER_SETTINGS>&lt;profile&gt; &lt;Language id="CSS"&gt; - &lt;Rearrange&gt;true&lt;/Rearrange&gt; &lt;Reformat&gt;true&lt;/Reformat&gt; + &lt;Rearrange&gt;true&lt;/Rearrange&gt; &lt;/Language&gt; &lt;Language id="EditorConfig"&gt; &lt;Reformat&gt;true&lt;/Reformat&gt; &lt;/Language&gt; &lt;Language id="HTML"&gt; + &lt;Reformat&gt;true&lt;/Reformat&gt; &lt;OptimizeImports&gt;false&lt;/OptimizeImports&gt; &lt;Rearrange&gt;true&lt;/Rearrange&gt; - &lt;Reformat&gt;true&lt;/Reformat&gt; &lt;/Language&gt; &lt;Language id="HTTP Request"&gt; &lt;Reformat&gt;true&lt;/Reformat&gt; @@ -53,9 +53,9 @@ &lt;Reformat&gt;true&lt;/Reformat&gt; &lt;/Language&gt; &lt;Language id="JavaScript"&gt; + &lt;Reformat&gt;true&lt;/Reformat&gt; &lt;OptimizeImports&gt;false&lt;/OptimizeImports&gt; &lt;Rearrange&gt;true&lt;/Rearrange&gt; - &lt;Reformat&gt;true&lt;/Reformat&gt; &lt;/Language&gt; &lt;Language id="Markdown"&gt; &lt;Reformat&gt;true&lt;/Reformat&gt; @@ -73,9 +73,9 @@ &lt;Reformat&gt;true&lt;/Reformat&gt; &lt;/Language&gt; &lt;Language id="XML"&gt; + &lt;Reformat&gt;true&lt;/Reformat&gt; &lt;OptimizeImports&gt;false&lt;/OptimizeImports&gt; &lt;Rearrange&gt;true&lt;/Rearrange&gt; - &lt;Reformat&gt;true&lt;/Reformat&gt; &lt;/Language&gt; &lt;Language id="yaml"&gt; &lt;Reformat&gt;true&lt;/Reformat&gt; diff --git a/samples/.dockerignore b/samples/.dockerignore new file mode 100644 index 000000000..cd967fc3a --- /dev/null +++ b/samples/.dockerignore @@ -0,0 +1,25 @@ +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/.idea +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md \ No newline at end of file diff --git a/samples/Directory.Build.props b/samples/Directory.Build.props index a3644b0a7..7c4e1140e 100644 --- a/samples/Directory.Build.props +++ b/samples/Directory.Build.props @@ -1,10 +1,15 @@ - net5.0;net6.0;net7.0 + net6.0;net7.0;net8.0 enable enable true Exe preview + + + + + \ No newline at end of file diff --git a/samples/Samples.sln.DotSettings b/samples/Samples.sln.DotSettings index 16d970453..c341e4095 100644 --- a/samples/Samples.sln.DotSettings +++ b/samples/Samples.sln.DotSettings @@ -399,6 +399,7 @@ True True True + True True True True diff --git a/samples/appending-events/Program.cs b/samples/appending-events/Program.cs index 4a908a3d1..72ba2a1ec 100644 --- a/samples/appending-events/Program.cs +++ b/samples/appending-events/Program.cs @@ -1,161 +1,169 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net.Http; -using System.Text; -using System.Text.Json; -using System.Threading; -using System.Threading.Tasks; -using EventStore.Client; - -namespace appending_events { - class Program { - static async Task Main(string[] args) { - var settings = EventStoreClientSettings.Create("esdb://localhost:2113?tls=false"); - settings.OperationOptions.ThrowOnAppendFailure = false; - await using var client = new EventStoreClient( - settings - ); - await AppendToStream(client); - await AppendWithConcurrencyCheck(client); - await AppendWithNoStream(client); - await AppendWithSameId(client); - - return 0; - } +#pragma warning disable CS8321 // Local function is declared but never used + +var settings = EventStoreClientSettings.Create("esdb://localhost:2113?tls=false"); + +settings.OperationOptions.ThrowOnAppendFailure = false; + +await using var client = new EventStoreClient(settings); + +await AppendToStream(client); +await AppendWithConcurrencyCheck(client); +await AppendWithNoStream(client); +await AppendWithSameId(client); + +return; - private static async Task AppendToStream(EventStoreClient client) { - #region append-to-stream - var eventData = new EventData( - Uuid.NewUuid(), - "some-event", - Encoding.UTF8.GetBytes("{\"id\": \"1\" \"value\": \"some value\"}") - ); - - await client.AppendToStreamAsync( - "some-stream", - StreamState.NoStream, - new List { - eventData - }); - #endregion append-to-stream +static async Task AppendToStream(EventStoreClient client) { + #region append-to-stream + + var eventData = new EventData( + Uuid.NewUuid(), + "some-event", + Encoding.UTF8.GetBytes("{\"id\": \"1\" \"value\": \"some value\"}") + ); + + await client.AppendToStreamAsync( + "some-stream", + StreamState.NoStream, + new List { + eventData } + ); + + #endregion append-to-stream +} + +static async Task AppendWithSameId(EventStoreClient client) { + #region append-duplicate-event + + var eventData = new EventData( + Uuid.NewUuid(), + "some-event", + Encoding.UTF8.GetBytes("{\"id\": \"1\" \"value\": \"some value\"}") + ); - private static async Task AppendWithSameId(EventStoreClient client) { - #region append-duplicate-event - var eventData = new EventData( - Uuid.NewUuid(), - "some-event", - Encoding.UTF8.GetBytes("{\"id\": \"1\" \"value\": \"some value\"}") - ); - - await client.AppendToStreamAsync( - "same-event-stream", - StreamState.Any, - new List { - eventData - }); - - // attempt to append the same event again - await client.AppendToStreamAsync( - "same-event-stream", - StreamState.Any, - new List { - eventData - }); - #endregion append-duplicate-event + await client.AppendToStreamAsync( + "same-event-stream", + StreamState.Any, + new List { + eventData } + ); + + // attempt to append the same event again + await client.AppendToStreamAsync( + "same-event-stream", + StreamState.Any, + new List { + eventData + } + ); + + #endregion append-duplicate-event +} - private static async Task AppendWithNoStream(EventStoreClient client) { - #region append-with-no-stream - var eventDataOne = new EventData( - Uuid.NewUuid(), - "some-event", - Encoding.UTF8.GetBytes("{\"id\": \"1\" \"value\": \"some value\"}") - ); - - var eventDataTwo = new EventData( - Uuid.NewUuid(), - "some-event", - Encoding.UTF8.GetBytes("{\"id\": \"2\" \"value\": \"some other value\"}") - ); - - await client.AppendToStreamAsync( - "no-stream-stream", - StreamState.NoStream, - new List { - eventDataOne - }); - - // attempt to append the same event again - await client.AppendToStreamAsync( - "no-stream-stream", - StreamState.NoStream, - new List { - eventDataTwo - }); - #endregion append-with-no-stream +static async Task AppendWithNoStream(EventStoreClient client) { + #region append-with-no-stream + + var eventDataOne = new EventData( + Uuid.NewUuid(), + "some-event", + Encoding.UTF8.GetBytes("{\"id\": \"1\" \"value\": \"some value\"}") + ); + + var eventDataTwo = new EventData( + Uuid.NewUuid(), + "some-event", + Encoding.UTF8.GetBytes("{\"id\": \"2\" \"value\": \"some other value\"}") + ); + + await client.AppendToStreamAsync( + "no-stream-stream", + StreamState.NoStream, + new List { + eventDataOne } + ); + + // attempt to append the same event again + await client.AppendToStreamAsync( + "no-stream-stream", + StreamState.NoStream, + new List { + eventDataTwo + } + ); + + #endregion append-with-no-stream +} - private static async Task AppendWithConcurrencyCheck(EventStoreClient client) { - await client.AppendToStreamAsync("concurrency-stream", StreamRevision.None, - new[] {new EventData(Uuid.NewUuid(), "-", ReadOnlyMemory.Empty)}); - #region append-with-concurrency-check - - var clientOneRead = client.ReadStreamAsync( - Direction.Forwards, - "concurrency-stream", - StreamPosition.Start); - var clientOneRevision = (await clientOneRead.LastAsync()).Event.EventNumber.ToUInt64(); - - var clientTwoRead = client.ReadStreamAsync(Direction.Forwards, "concurrency-stream", StreamPosition.Start); - var clientTwoRevision = (await clientTwoRead.LastAsync()).Event.EventNumber.ToUInt64(); - - var clientOneData = new EventData( - Uuid.NewUuid(), - "some-event", - Encoding.UTF8.GetBytes("{\"id\": \"1\" \"value\": \"clientOne\"}") - ); - - await client.AppendToStreamAsync( - "no-stream-stream", - clientOneRevision, - new List { - clientOneData - }); - - var clientTwoData = new EventData( - Uuid.NewUuid(), - "some-event", - Encoding.UTF8.GetBytes("{\"id\": \"2\" \"value\": \"clientTwo\"}") - ); - - await client.AppendToStreamAsync( - "no-stream-stream", - clientTwoRevision, - new List { - clientTwoData - }); - #endregion append-with-concurrency-check +static async Task AppendWithConcurrencyCheck(EventStoreClient client) { + await client.AppendToStreamAsync( + "concurrency-stream", + StreamRevision.None, + new[] { new EventData(Uuid.NewUuid(), "-", ReadOnlyMemory.Empty) } + ); + + #region append-with-concurrency-check + + var clientOneRead = client.ReadStreamAsync( + Direction.Forwards, + "concurrency-stream", + StreamPosition.Start + ); + + var clientOneRevision = (await clientOneRead.LastAsync()).Event.EventNumber.ToUInt64(); + + var clientTwoRead = client.ReadStreamAsync(Direction.Forwards, "concurrency-stream", StreamPosition.Start); + var clientTwoRevision = (await clientTwoRead.LastAsync()).Event.EventNumber.ToUInt64(); + + var clientOneData = new EventData( + Uuid.NewUuid(), + "some-event", + Encoding.UTF8.GetBytes("{\"id\": \"1\" \"value\": \"clientOne\"}") + ); + + await client.AppendToStreamAsync( + "no-stream-stream", + clientOneRevision, + new List { + clientOneData } - - protected async Task AppendOverridingUserCredentials(EventStoreClient client, CancellationToken cancellationToken) - { - var eventData = new EventData( - Uuid.NewUuid(), - "TestEvent", - Encoding.UTF8.GetBytes("{\"id\": \"1\" \"value\": \"some value\"}") - ); - - #region overriding-user-credentials - await client.AppendToStreamAsync( - "some-stream", - StreamState.Any, - new[] { eventData }, - userCredentials: new UserCredentials("admin", "changeit"), - cancellationToken: cancellationToken - ); - #endregion overriding-user-credentials + ); + + var clientTwoData = new EventData( + Uuid.NewUuid(), + "some-event", + Encoding.UTF8.GetBytes("{\"id\": \"2\" \"value\": \"clientTwo\"}") + ); + + await client.AppendToStreamAsync( + "no-stream-stream", + clientTwoRevision, + new List { + clientTwoData } - } + ); + + #endregion append-with-concurrency-check +} + +static async Task AppendOverridingUserCredentials(EventStoreClient client, CancellationToken cancellationToken) { + var eventData = new EventData( + Uuid.NewUuid(), + "TestEvent", + "{\"id\": \"1\" \"value\": \"some value\"}"u8.ToArray() + ); + + #region overriding-user-credentials + + await client.AppendToStreamAsync( + "some-stream", + StreamState.Any, + new[] { eventData }, + userCredentials: new UserCredentials("admin", "changeit"), + cancellationToken: cancellationToken + ); + + #endregion overriding-user-credentials } diff --git a/samples/connecting-to-a-cluster/Program.cs b/samples/connecting-to-a-cluster/Program.cs index 67e4fba6d..a31666fc6 100644 --- a/samples/connecting-to-a-cluster/Program.cs +++ b/samples/connecting-to-a-cluster/Program.cs @@ -1,34 +1,33 @@ -using System; -using System.Net; -using EventStore.Client; - -namespace connecting_to_a_cluster { - class Program { - static void Main(string[] args) { - } - - private static void ConnectingToACluster() { - #region connecting-to-a-cluster - using var client = new EventStoreClient( - EventStoreClientSettings.Create("esdb://localhost:1114,localhost:2114,localhost:3114") - ); - #endregion connecting-to-a-cluster - } - - private static void ProvidingDefaultCredentials() { - #region providing-default-credentials - using var client = new EventStoreClient( - EventStoreClientSettings.Create("esdb://admin:changeit@localhost:1114,localhost:2114,localhost:3114") - ); - #endregion providing-default-credentials - } - - private static void ConnectingToAClusterComplex() { - #region connecting-to-a-cluster-complex - using var client = new EventStoreClient( - EventStoreClientSettings.Create("esdb://admin:changeit@localhost:1114,localhost:2114,localhost:3114?DiscoveryInterval=30000;GossipTimeout=10000;NodePreference=leader;MaxDiscoverAttempts=5") - ); - #endregion connecting-to-a-cluster-complex - } - } +#pragma warning disable CS8321 // Local function is declared but never used + +static void ConnectingToACluster() { + #region connecting-to-a-cluster + + using var client = new EventStoreClient( + EventStoreClientSettings.Create("esdb://localhost:1114,localhost:2114,localhost:3114") + ); + + #endregion connecting-to-a-cluster +} + +static void ProvidingDefaultCredentials() { + #region providing-default-credentials + + using var client = new EventStoreClient( + EventStoreClientSettings.Create("esdb://admin:changeit@localhost:1114,localhost:2114,localhost:3114") + ); + + #endregion providing-default-credentials } + +static void ConnectingToAClusterComplex() { + #region connecting-to-a-cluster-complex + + using var client = new EventStoreClient( + EventStoreClientSettings.Create( + "esdb://admin:changeit@localhost:1114,localhost:2114,localhost:3114?DiscoveryInterval=30000;GossipTimeout=10000;NodePreference=leader;MaxDiscoverAttempts=5" + ) + ); + + #endregion connecting-to-a-cluster-complex +} \ No newline at end of file diff --git a/samples/connecting-to-a-single-node/DemoInterceptor.cs b/samples/connecting-to-a-single-node/DemoInterceptor.cs index 6f01bf72a..fc68b70a2 100644 --- a/samples/connecting-to-a-single-node/DemoInterceptor.cs +++ b/samples/connecting-to-a-single-node/DemoInterceptor.cs @@ -1,28 +1,31 @@ -using System; using Grpc.Core; using Grpc.Core.Interceptors; -namespace connecting_to_a_single_node { - #region interceptor - public class DemoInterceptor : Interceptor { - public override AsyncServerStreamingCall - AsyncServerStreamingCall( - TRequest request, - ClientInterceptorContext context, - AsyncServerStreamingCallContinuation continuation) { - Console.WriteLine($"AsyncServerStreamingCall: {context.Method.FullName}"); +namespace connecting_to_a_single_node; - return base.AsyncServerStreamingCall(request, context, continuation); - } +#region interceptor - public override AsyncClientStreamingCall - AsyncClientStreamingCall( - ClientInterceptorContext context, - AsyncClientStreamingCallContinuation continuation) { - Console.WriteLine($"AsyncClientStreamingCall: {context.Method.FullName}"); +public class DemoInterceptor : Interceptor { + public override AsyncServerStreamingCall + AsyncServerStreamingCall( + TRequest request, + ClientInterceptorContext context, + AsyncServerStreamingCallContinuation continuation + ) { + Console.WriteLine($"AsyncServerStreamingCall: {context.Method.FullName}"); - return base.AsyncClientStreamingCall(context, continuation); - } + return base.AsyncServerStreamingCall(request, context, continuation); + } + + public override AsyncClientStreamingCall + AsyncClientStreamingCall( + ClientInterceptorContext context, + AsyncClientStreamingCallContinuation continuation + ) { + Console.WriteLine($"AsyncClientStreamingCall: {context.Method.FullName}"); + + return base.AsyncClientStreamingCall(context, continuation); } - #endregion interceptor } + +#endregion interceptor \ No newline at end of file diff --git a/samples/connecting-to-a-single-node/Program.cs b/samples/connecting-to-a-single-node/Program.cs index 192327ba5..f50e1689f 100644 --- a/samples/connecting-to-a-single-node/Program.cs +++ b/samples/connecting-to-a-single-node/Program.cs @@ -1,80 +1,85 @@ -using System; -using System.Net.Http; -using EventStore.Client; +using connecting_to_a_single_node; -namespace connecting_to_a_single_node { - class Program { - static void Main(string[] args) { - } +#pragma warning disable CS8321 // Local function is declared but never used - private static void SimpleConnection() { - #region creating-simple-connection - using var client = new EventStoreClient( - EventStoreClientSettings.Create("esdb://localhost:2113") - ); - #endregion creating-simple-connection - } +static void SimpleConnection() { + #region creating-simple-connection - private static void ProvidingDefaultCredentials() { - #region providing-default-credentials - using var client = new EventStoreClient( - EventStoreClientSettings.Create("esdb://admin:changeit@localhost:2113") - ); - #endregion providing-default-credentials - } + using var client = new EventStoreClient(EventStoreClientSettings.Create("esdb://localhost:2113")); - private static void SpecifyingAConnectionName() { - #region setting-the-connection-name - using var client = new EventStoreClient( - EventStoreClientSettings.Create("esdb://admin:changeit@localhost:2113?ConnectionName=SomeConnection") - ); - #endregion setting-the-connection-name - } + #endregion creating-simple-connection +} - private static void OverridingTheTimeout() { - #region overriding-timeout - using var client = new EventStoreClient( - EventStoreClientSettings.Create($"esdb://admin:changeit@localhost:2113?OperationTimeout=30000") - ); - #endregion overriding-timeout - } - - private static void CombiningSettings() { - #region overriding-timeout - using var client = new EventStoreClient( - EventStoreClientSettings.Create($"esdb://admin:changeit@localhost:2113?ConnectionName=SomeConnection&OperationTimeout=30000") - ); - #endregion overriding-timeout - } +static void ProvidingDefaultCredentials() { + #region providing-default-credentials - private static void CreatingAnInterceptor() { - #region adding-an-interceptor - var settings = new EventStoreClientSettings { - Interceptors = new[] {new DemoInterceptor()}, - ConnectivitySettings = { - Address = new Uri("https://localhost:2113") - } - }; - #endregion adding-an-interceptor - - var client = new EventStoreClient(settings); - } + using var client = new EventStoreClient(EventStoreClientSettings.Create("esdb://admin:changeit@localhost:2113")); + + #endregion providing-default-credentials +} + +static void SpecifyingAConnectionName() { + #region setting-the-connection-name + + using var client = new EventStoreClient( + EventStoreClientSettings.Create("esdb://admin:changeit@localhost:2113?ConnectionName=SomeConnection") + ); + + #endregion setting-the-connection-name +} + +static void OverridingTheTimeout() { + #region overriding-timeout - private static void CustomHttpMessageHandler() { - #region adding-an-custom-http-message-handler - var settings = new EventStoreClientSettings { - CreateHttpMessageHandler = () => - new HttpClientHandler { - ServerCertificateCustomValidationCallback = - (sender, cert, chain, sslPolicyErrors) => true - }, - ConnectivitySettings = { - Address = new Uri("https://localhost:2113") - } - }; - #endregion adding-an-custom-http-message-handler - - var client = new EventStoreClient(settings); + using var client = new EventStoreClient( + EventStoreClientSettings.Create($"esdb://admin:changeit@localhost:2113?OperationTimeout=30000") + ); + + #endregion overriding-timeout +} + +static void CombiningSettings() { + #region overriding-timeout + + using var client = new EventStoreClient( + EventStoreClientSettings.Create( + $"esdb://admin:changeit@localhost:2113?ConnectionName=SomeConnection&OperationTimeout=30000" + ) + ); + + #endregion overriding-timeout +} + +static void CreatingAnInterceptor() { + #region adding-an-interceptor + + var settings = new EventStoreClientSettings { + Interceptors = new[] { new DemoInterceptor() }, + ConnectivitySettings = { + Address = new Uri("https://localhost:2113") } - } + }; + + #endregion adding-an-interceptor + + var client = new EventStoreClient(settings); } + +static void CustomHttpMessageHandler() { + #region adding-an-custom-http-message-handler + + var settings = new EventStoreClientSettings { + CreateHttpMessageHandler = () => + new HttpClientHandler { + ServerCertificateCustomValidationCallback = + (sender, cert, chain, sslPolicyErrors) => true + }, + ConnectivitySettings = { + Address = new Uri("https://localhost:2113") + } + }; + + #endregion adding-an-custom-http-message-handler + + var client = new EventStoreClient(settings); +} \ No newline at end of file diff --git a/samples/persistent-subscriptions/Program.cs b/samples/persistent-subscriptions/Program.cs index f26348917..e49b6e42d 100644 --- a/samples/persistent-subscriptions/Program.cs +++ b/samples/persistent-subscriptions/Program.cs @@ -1,235 +1,249 @@ -using System; -using System.Threading.Tasks; -using EventStore.Client; - -namespace persistent_subscriptions -{ - class Program - { - static async Task Main(string[] args) { - await using var client = new EventStorePersistentSubscriptionsClient( - EventStoreClientSettings.Create("esdb://localhost:2113?tls=false") - ); - await CreatePersistentSubscription(client); - await UpdatePersistentSubscription(client); - await ConnectToPersistentSubscriptionToStream(client); - await CreatePersistentSubscriptionToAll(client); - await ConnectToPersistentSubscriptionToAll(client); - await ConnectToPersistentSubscriptionWithManualAcks(client); - await GetPersistentSubscriptionToStreamInfo(client); - await GetPersistentSubscriptionToAllInfo(client); - await ReplayParkedToStream(client); - await ReplayParkedToAll(client); - await ListPersistentSubscriptionsToStream(client); - await ListPersistentSubscriptionsToAll(client); - await ListAllPersistentSubscriptions(client); - await RestartPersistentSubscriptionSubsystem(client); - await DeletePersistentSubscription(client); - } - - static async Task CreatePersistentSubscription(EventStorePersistentSubscriptionsClient client) { - #region create-persistent-subscription-to-stream - var userCredentials = new UserCredentials("admin", "changeit"); - - var settings = new PersistentSubscriptionSettings(); - await client.CreateToStreamAsync( - "test-stream", - "subscription-group", - settings, - userCredentials: userCredentials); - #endregion create-persistent-subscription-to-stream - } - - static async Task ConnectToPersistentSubscriptionToStream(EventStorePersistentSubscriptionsClient client) { - #region subscribe-to-persistent-subscription-to-stream - var subscription = await client.SubscribeToStreamAsync( - "test-stream", - "subscription-group", - async (subscription, evnt, retryCount, cancellationToken) => { - await HandleEvent(evnt); - await subscription.Ack(evnt); - }, (subscription, dropReason, exception) => { - Console.WriteLine($"Subscription was dropped due to {dropReason}. {exception}"); - }); - #endregion subscribe-to-persistent-subscription-to-stream - } - - static async Task CreatePersistentSubscriptionToAll(EventStorePersistentSubscriptionsClient client) { - #region create-persistent-subscription-to-all - var userCredentials = new UserCredentials("admin", "changeit"); - var filter = StreamFilter.Prefix("test"); - - var settings = new PersistentSubscriptionSettings(); - await client.CreateToAllAsync( - "subscription-group", - filter, - settings, - userCredentials: userCredentials); - #endregion create-persistent-subscription-to-all - } - - static async Task ConnectToPersistentSubscriptionToAll(EventStorePersistentSubscriptionsClient client) { - #region subscribe-to-persistent-subscription-to-all - await client.SubscribeToAllAsync( - "subscription-group", - async (subscription, evnt, retryCount, cancellationToken) => { - await HandleEvent(evnt); - }, (subscription, dropReason, exception) => { - Console.WriteLine($"Subscription was dropped due to {dropReason}. {exception}"); - }); - #endregion subscribe-to-persistent-subscription-to-all - } - - static async Task ConnectToPersistentSubscriptionWithManualAcks(EventStorePersistentSubscriptionsClient client) { - #region subscribe-to-persistent-subscription-with-manual-acks - var subscription = await client.SubscribeToStreamAsync( - "test-stream", - "subscription-group", - async (subscription, evnt, retryCount, cancellationToken) => { - try { - await HandleEvent(evnt); - await subscription.Ack(evnt); - } catch (UnrecoverableException ex) { - await subscription.Nack(PersistentSubscriptionNakEventAction.Park, ex.Message, evnt); - } - }, (subscription, dropReason, exception) => { - Console.WriteLine($"Subscription was dropped due to {dropReason}. {exception}"); - }); - #endregion subscribe-to-persistent-subscription-with-manual-acks - } - - static async Task UpdatePersistentSubscription(EventStorePersistentSubscriptionsClient client) { - #region update-persistent-subscription - var userCredentials = new UserCredentials("admin", "changeit"); - var settings = new PersistentSubscriptionSettings( - resolveLinkTos: true, - checkPointLowerBound: 20); - - await client.UpdateToStreamAsync( - "test-stream", - "subscription-group", - settings, - userCredentials: userCredentials); - #endregion update-persistent-subscription - } - - static async Task DeletePersistentSubscription(EventStorePersistentSubscriptionsClient client) { - #region delete-persistent-subscription - var userCredentials = new UserCredentials("admin", "changeit"); - await client.DeleteToStreamAsync( - "test-stream", - "subscription-group", - userCredentials: userCredentials); - #endregion delete-persistent-subscription - } - - static async Task GetPersistentSubscriptionToStreamInfo(EventStorePersistentSubscriptionsClient client) { - #region get-persistent-subscription-to-stream-info - - var userCredentials = new UserCredentials("admin", "changeit"); - var info = await client.GetInfoToStreamAsync( - "test-stream", - "subscription-group", - userCredentials: userCredentials); - - Console.WriteLine($"GroupName: {info.GroupName}, EventSource: {info.EventSource}, Status: {info.Status}"); - - #endregion get-persistent-subscription-to-stream-info - } - - static async Task GetPersistentSubscriptionToAllInfo(EventStorePersistentSubscriptionsClient client) { - #region get-persistent-subscription-to-all-info - - var userCredentials = new UserCredentials("admin", "changeit"); - var info = await client.GetInfoToAllAsync( - "subscription-group", - userCredentials: userCredentials); - - Console.WriteLine($"GroupName: {info.GroupName}, EventSource: {info.EventSource}, Status: {info.Status}"); - - #endregion get-persistent-subscription-to-all-info - } - - static async Task ReplayParkedToStream(EventStorePersistentSubscriptionsClient client) { - #region replay-parked-of-persistent-subscription-to-stream - - var userCredentials = new UserCredentials("admin", "changeit"); - await client.ReplayParkedMessagesToStreamAsync( - "test-stream", - "subscription-group", - stopAt: 10, - userCredentials: userCredentials); - - #endregion persistent-subscription-replay-parked-to-stream - } - - static async Task ReplayParkedToAll(EventStorePersistentSubscriptionsClient client) { - #region replay-parked-of-persistent-subscription-to-all - - var userCredentials = new UserCredentials("admin", "changeit"); - await client.ReplayParkedMessagesToAllAsync( - "subscription-group", - stopAt: 10, - userCredentials: userCredentials); - - #endregion replay-parked-of-persistent-subscription-to-all - } - - static async Task ListPersistentSubscriptionsToStream(EventStorePersistentSubscriptionsClient client) { - #region list-persistent-subscriptions-to-stream - - var userCredentials = new UserCredentials("admin", "changeit"); - var subscriptions = await client.ListToStreamAsync( - "test-stream", - userCredentials: userCredentials); - - foreach (var s in subscriptions) { - Console.WriteLine($"GroupName: {s.GroupName}, EventSource: {s.EventSource}, Status: {s.Status}"); - } - - #endregion list-persistent-subscriptions-to-stream - } - - static async Task ListPersistentSubscriptionsToAll(EventStorePersistentSubscriptionsClient client) { - #region list-persistent-subscriptions-to-all - - var userCredentials = new UserCredentials("admin", "changeit"); - var subscriptions = await client.ListToAllAsync(userCredentials: userCredentials); - - foreach (var s in subscriptions) { - Console.WriteLine($"GroupName: {s.GroupName}, EventSource: {s.EventSource}, Status: {s.Status}"); - } - - #endregion list-persistent-subscriptions-to-all - } - - static async Task ListAllPersistentSubscriptions(EventStorePersistentSubscriptionsClient client) { - #region list-persistent-subscriptions - - var userCredentials = new UserCredentials("admin", "changeit"); - var subscriptions = await client.ListAllAsync(userCredentials: userCredentials); - - foreach (var s in subscriptions) { - Console.WriteLine($"GroupName: {s.GroupName}, EventSource: {s.EventSource}, Status: {s.Status}"); - } - - #endregion list-persistent-subscriptions - } - - static async Task RestartPersistentSubscriptionSubsystem(EventStorePersistentSubscriptionsClient client) { - #region restart-persistent-subscription-subsystem - - var userCredentials = new UserCredentials("admin", "changeit"); - await client.RestartSubsystemAsync(userCredentials: userCredentials); - - #endregion restart-persistent-subscription-subsystem - } - - static Task HandleEvent(ResolvedEvent evnt) { - return Task.CompletedTask; - } - - class UnrecoverableException : Exception { - } - } +await using var client = new EventStorePersistentSubscriptionsClient( + EventStoreClientSettings.Create("esdb://localhost:2113?tls=false") +); + +await CreatePersistentSubscription(client); +await UpdatePersistentSubscription(client); +await ConnectToPersistentSubscriptionToStream(client); +await CreatePersistentSubscriptionToAll(client); +await ConnectToPersistentSubscriptionToAll(client); +await ConnectToPersistentSubscriptionWithManualAcks(client); +await GetPersistentSubscriptionToStreamInfo(client); +await GetPersistentSubscriptionToAllInfo(client); +await ReplayParkedToStream(client); +await ReplayParkedToAll(client); +await ListPersistentSubscriptionsToStream(client); +await ListPersistentSubscriptionsToAll(client); +await ListAllPersistentSubscriptions(client); +await RestartPersistentSubscriptionSubsystem(client); +await DeletePersistentSubscription(client); + +return; + +static async Task CreatePersistentSubscription(EventStorePersistentSubscriptionsClient client) { + #region create-persistent-subscription-to-stream + + var userCredentials = new UserCredentials("admin", "changeit"); + + var settings = new PersistentSubscriptionSettings(); + await client.CreateToStreamAsync( + "test-stream", + "subscription-group", + settings, + userCredentials: userCredentials + ); + + #endregion create-persistent-subscription-to-stream } + +static async Task ConnectToPersistentSubscriptionToStream(EventStorePersistentSubscriptionsClient client) { + #region subscribe-to-persistent-subscription-to-stream + + var subscription = await client.SubscribeToStreamAsync( + "test-stream", + "subscription-group", + async (subscription, evnt, retryCount, cancellationToken) => { + await HandleEvent(evnt); + await subscription.Ack(evnt); + }, + (subscription, dropReason, exception) => { + Console.WriteLine($"Subscription was dropped due to {dropReason}. {exception}"); + } + ); + + #endregion subscribe-to-persistent-subscription-to-stream +} + +static async Task CreatePersistentSubscriptionToAll(EventStorePersistentSubscriptionsClient client) { + #region create-persistent-subscription-to-all + + var userCredentials = new UserCredentials("admin", "changeit"); + var filter = StreamFilter.Prefix("test"); + + var settings = new PersistentSubscriptionSettings(); + await client.CreateToAllAsync( + "subscription-group", + filter, + settings, + userCredentials: userCredentials + ); + + #endregion create-persistent-subscription-to-all +} + +static async Task ConnectToPersistentSubscriptionToAll(EventStorePersistentSubscriptionsClient client) { + #region subscribe-to-persistent-subscription-to-all + + await client.SubscribeToAllAsync( + "subscription-group", + async (subscription, evnt, retryCount, cancellationToken) => { await HandleEvent(evnt); }, + (subscription, dropReason, exception) => { + Console.WriteLine($"Subscription was dropped due to {dropReason}. {exception}"); + } + ); + + #endregion subscribe-to-persistent-subscription-to-all +} + +static async Task ConnectToPersistentSubscriptionWithManualAcks(EventStorePersistentSubscriptionsClient client) { + #region subscribe-to-persistent-subscription-with-manual-acks + + var subscription = await client.SubscribeToStreamAsync( + "test-stream", + "subscription-group", + async (subscription, evnt, retryCount, cancellationToken) => { + try { + await HandleEvent(evnt); + await subscription.Ack(evnt); + } + catch (UnrecoverableException ex) { + await subscription.Nack(PersistentSubscriptionNakEventAction.Park, ex.Message, evnt); + } + }, + (subscription, dropReason, exception) => { + Console.WriteLine($"Subscription was dropped due to {dropReason}. {exception}"); + } + ); + + #endregion subscribe-to-persistent-subscription-with-manual-acks +} + +static async Task UpdatePersistentSubscription(EventStorePersistentSubscriptionsClient client) { + #region update-persistent-subscription + + var userCredentials = new UserCredentials("admin", "changeit"); + var settings = new PersistentSubscriptionSettings( + true, + checkPointLowerBound: 20 + ); + + await client.UpdateToStreamAsync( + "test-stream", + "subscription-group", + settings, + userCredentials: userCredentials + ); + + #endregion update-persistent-subscription +} + +static async Task DeletePersistentSubscription(EventStorePersistentSubscriptionsClient client) { + #region delete-persistent-subscription + + var userCredentials = new UserCredentials("admin", "changeit"); + await client.DeleteToStreamAsync( + "test-stream", + "subscription-group", + userCredentials: userCredentials + ); + + #endregion delete-persistent-subscription +} + +static async Task GetPersistentSubscriptionToStreamInfo(EventStorePersistentSubscriptionsClient client) { + #region get-persistent-subscription-to-stream-info + + var userCredentials = new UserCredentials("admin", "changeit"); + var info = await client.GetInfoToStreamAsync( + "test-stream", + "subscription-group", + userCredentials: userCredentials + ); + + Console.WriteLine($"GroupName: {info.GroupName}, EventSource: {info.EventSource}, Status: {info.Status}"); + + #endregion get-persistent-subscription-to-stream-info +} + +static async Task GetPersistentSubscriptionToAllInfo(EventStorePersistentSubscriptionsClient client) { + #region get-persistent-subscription-to-all-info + + var userCredentials = new UserCredentials("admin", "changeit"); + var info = await client.GetInfoToAllAsync( + "subscription-group", + userCredentials: userCredentials + ); + + Console.WriteLine($"GroupName: {info.GroupName}, EventSource: {info.EventSource}, Status: {info.Status}"); + + #endregion get-persistent-subscription-to-all-info +} + +static async Task ReplayParkedToStream(EventStorePersistentSubscriptionsClient client) { + #region replay-parked-of-persistent-subscription-to-stream + + var userCredentials = new UserCredentials("admin", "changeit"); + await client.ReplayParkedMessagesToStreamAsync( + "test-stream", + "subscription-group", + 10, + userCredentials: userCredentials + ); + + #endregion persistent-subscription-replay-parked-to-stream +} + +static async Task ReplayParkedToAll(EventStorePersistentSubscriptionsClient client) { + #region replay-parked-of-persistent-subscription-to-all + + var userCredentials = new UserCredentials("admin", "changeit"); + await client.ReplayParkedMessagesToAllAsync( + "subscription-group", + 10, + userCredentials: userCredentials + ); + + #endregion replay-parked-of-persistent-subscription-to-all +} + +static async Task ListPersistentSubscriptionsToStream(EventStorePersistentSubscriptionsClient client) { + #region list-persistent-subscriptions-to-stream + + var userCredentials = new UserCredentials("admin", "changeit"); + var subscriptions = await client.ListToStreamAsync( + "test-stream", + userCredentials: userCredentials + ); + + foreach (var s in subscriptions) + Console.WriteLine($"GroupName: {s.GroupName}, EventSource: {s.EventSource}, Status: {s.Status}"); + + #endregion list-persistent-subscriptions-to-stream +} + +static async Task ListPersistentSubscriptionsToAll(EventStorePersistentSubscriptionsClient client) { + #region list-persistent-subscriptions-to-all + + var userCredentials = new UserCredentials("admin", "changeit"); + var subscriptions = await client.ListToAllAsync(userCredentials: userCredentials); + + foreach (var s in subscriptions) + Console.WriteLine($"GroupName: {s.GroupName}, EventSource: {s.EventSource}, Status: {s.Status}"); + + #endregion list-persistent-subscriptions-to-all +} + +static async Task ListAllPersistentSubscriptions(EventStorePersistentSubscriptionsClient client) { + #region list-persistent-subscriptions + + var userCredentials = new UserCredentials("admin", "changeit"); + var subscriptions = await client.ListAllAsync(userCredentials: userCredentials); + + foreach (var s in subscriptions) + Console.WriteLine($"GroupName: {s.GroupName}, EventSource: {s.EventSource}, Status: {s.Status}"); + + #endregion list-persistent-subscriptions +} + +static async Task RestartPersistentSubscriptionSubsystem(EventStorePersistentSubscriptionsClient client) { + #region restart-persistent-subscription-subsystem + + var userCredentials = new UserCredentials("admin", "changeit"); + await client.RestartSubsystemAsync(userCredentials: userCredentials); + + #endregion restart-persistent-subscription-subsystem +} + +static Task HandleEvent(ResolvedEvent evnt) => Task.CompletedTask; + +class UnrecoverableException : Exception { } \ No newline at end of file diff --git a/samples/projection-management/Program.cs b/samples/projection-management/Program.cs index e864551dc..0f3d66b70 100644 --- a/samples/projection-management/Program.cs +++ b/samples/projection-management/Program.cs @@ -1,208 +1,235 @@ -using System; -using System.IO; -using System.Linq; -using System.Text; +#pragma warning disable CS8321 // Local function is declared but never used + using System.Text.Json; -using System.Threading.Tasks; -using EventStore.Client; using Grpc.Core; -namespace projection_management { - public static class Program { - - /// - /// This sample demonstrate the projection management features. - /// It will create data in the target database. - /// It will create a series of projections with the following content - /// fromAll() .when({$init:function(){return {count:0};},$any:function(s, e){s.count += 1;}}).outputState(); - /// - private static async Task Main() { - - const string connection = "esdb://localhost:2113?tls=false"; - var managementClient = ManagementClient(connection); - - Console.WriteLine("Populate data"); - await Populate(connection, 100); - Console.WriteLine("RestartSubSystem"); - await RestartSubSystem(managementClient); - await Task.Delay(500); // give time to the subsystem to restart - - Console.WriteLine("Disable"); - await Disable(managementClient); - Console.WriteLine("Disable Not Found"); - await DisableNotFound(managementClient); - - Console.WriteLine("Enable"); - await Enable(managementClient); - Console.WriteLine("Enable Not Found"); - await EnableNotFound(managementClient); - - Console.WriteLine("Delete"); - await Delete(managementClient); - - Console.WriteLine("Abort"); - await Abort(managementClient); - Console.WriteLine("Abort Not Found"); - await Abort_NotFound(managementClient); - - Console.WriteLine("Reset"); - await Reset(managementClient); - Console.WriteLine("Reset Not Found"); - await Reset_NotFound(managementClient); - - Console.WriteLine("CreateContinuous"); - await CreateContinuous(managementClient); - Console.WriteLine("CreateContinuous conflict"); - await CreateContinuous_Conflict(managementClient); - //Console.WriteLine("CreateOneTime"); - //await CreateOneTime(managementClient); - Console.WriteLine("Update"); - await Update(managementClient); - Console.WriteLine("Update_NotFound"); - await Update_NotFound(managementClient); - Console.WriteLine("ListAll"); - await ListAll(managementClient); - Console.WriteLine("ListContinuous"); - await ListContinuous(managementClient); - Console.WriteLine("GetStatus"); - await GetStatus(managementClient); - // Console.WriteLine("GetState"); - // await GetState(managementClient); - Console.WriteLine("GetResult"); - await GetResult(managementClient); - } - - - - private static EventStoreProjectionManagementClient ManagementClient(string connection) { - - #region createClient - var settings = EventStoreClientSettings.Create(connection); - settings.ConnectionName = "Projection management client"; - settings.DefaultCredentials = new UserCredentials("admin", "changeit"); - var managementClient = new EventStoreProjectionManagementClient(settings); - #endregion createClient - - return managementClient; - } - private static async Task RestartSubSystem(EventStoreProjectionManagementClient managementClient) { - #region RestartSubSystem - await managementClient.RestartSubsystemAsync(); - #endregion RestartSubSystem - } - - private static async Task Disable(EventStoreProjectionManagementClient managementClient) { - #region Disable - await managementClient.DisableAsync("$by_category"); - #endregion Disable - } - - private static async Task DisableNotFound(EventStoreProjectionManagementClient managementClient) { - #region DisableNotFound - try { - await managementClient.DisableAsync("projection that does not exists"); - } catch (RpcException e) when (e.StatusCode is StatusCode.NotFound) { - Console.WriteLine(e.Message); - } catch (RpcException e) when (e.Message.Contains("NotFound")) { // will be removed in a future release - Console.WriteLine(e.Message); - } - #endregion DisableNotFound - } - - private static async Task Enable(EventStoreProjectionManagementClient managementClient) { - #region Enable - await managementClient.EnableAsync("$by_category"); - #endregion Enable - } - - private static async Task EnableNotFound(EventStoreProjectionManagementClient managementClient) { - #region EnableNotFound - try { - await managementClient.EnableAsync("projection that does not exists"); - } catch (RpcException e) when (e.StatusCode is StatusCode.NotFound) { - Console.WriteLine(e.Message); - } catch (RpcException e) when (e.Message.Contains("NotFound")) { // will be removed in a future release - Console.WriteLine(e.Message); - } - #endregion EnableNotFound - } - - private static Task Delete(EventStoreProjectionManagementClient managementClient) { - #region Delete - // this is not yet available in the .net grpc client - #endregion Delete - - return Task.CompletedTask; - } - - private static async Task Abort(EventStoreProjectionManagementClient managementClient) { - try { - var js = - "fromAll() .when({$init:function(){return {count:0};},$any:function(s, e){s.count += 1;}}).outputState();"; - await managementClient.CreateContinuousAsync("countEvents_Abort", js); - } catch (RpcException e) when (e.StatusCode is StatusCode.Aborted) { - // ignore was already created in a previous run - } catch (RpcException e) when (e.Message.Contains("Conflict")) { // will be removed in a future release - // ignore was already created in a previous run - } - - #region Abort - // The .net clients prior to version 21.6 had an incorrect behavior: they will save the checkpoint. - await managementClient.AbortAsync("countEvents_Abort"); - #endregion Abort - } - - private static async Task Abort_NotFound(EventStoreProjectionManagementClient managementClient) { - #region Abort_NotFound - try { - await managementClient.AbortAsync("projection that does not exists"); - } catch (RpcException e) when (e.StatusCode is StatusCode.NotFound) { - Console.WriteLine(e.Message); - } catch (RpcException e) when (e.Message.Contains("NotFound")) { // will be removed in a future release - Console.WriteLine(e.Message); - } - #endregion Abort_NotFound - } - - private static async Task Reset(EventStoreProjectionManagementClient managementClient) { - try { - var js = - "fromAll() .when({$init:function(){return {count:0};},$any:function(s, e){s.count += 1;}}).outputState();"; - await managementClient.CreateContinuousAsync("countEvents_Reset", js); - } catch (RpcException e) when (e.StatusCode is StatusCode.Internal) { - // ignore was already created in a previous run - } catch (RpcException e) when (e.Message.Contains("Conflict")) { // will be removed in a future release - // ignore was already created in a previous run - } - - #region Reset - // Checkpoint will be written prior to resetting the projection - await managementClient.ResetAsync("countEvents_Reset"); - #endregion Reset - - } - - private static async Task Reset_NotFound(EventStoreProjectionManagementClient managementClient) { - #region Reset_NotFound - try { - await managementClient.ResetAsync("projection that does not exists"); - } catch (RpcException e) when (e.StatusCode is StatusCode.NotFound) { - Console.WriteLine(e.Message); - } catch (RpcException e) when (e.Message.Contains("NotFound")) { // will be removed in a future release - Console.WriteLine(e.Message); - } - #endregion Reset_NotFound - } - - private static async Task CreateOneTime(EventStoreProjectionManagementClient managementClient) { - const string js = - "fromAll() .when({$init:function(){return {count:0};},$any:function(s, e){s.count += 1;}}).outputState();"; - await managementClient.CreateOneTimeAsync(js); - } - - private static async Task CreateContinuous(EventStoreProjectionManagementClient managementClient) { - #region CreateContinuous - const string js = @"fromAll() +//// This sample demonstrate the projection management features. +//// It will create data in the target database. +//// It will create a series of projections with the following content +//// fromAll() .when({$init:function(){return {count:0};},$any:function(s, e){s.count += 1;}}).outputState(); + +const string connection = "esdb://localhost:2113?tls=false"; + +var managementClient = ManagementClient(connection); + +Console.WriteLine("Populate data"); +await Populate(connection, 100); +Console.WriteLine("RestartSubSystem"); +await RestartSubSystem(managementClient); +await Task.Delay(500); // give time to the subsystem to restart + +Console.WriteLine("Disable"); +await Disable(managementClient); +Console.WriteLine("Disable Not Found"); +await DisableNotFound(managementClient); + +Console.WriteLine("Enable"); +await Enable(managementClient); +Console.WriteLine("Enable Not Found"); +await EnableNotFound(managementClient); + +Console.WriteLine("Delete"); +await Delete(managementClient); + +Console.WriteLine("Abort"); +await Abort(managementClient); +Console.WriteLine("Abort Not Found"); +await Abort_NotFound(managementClient); + +Console.WriteLine("Reset"); +await Reset(managementClient); +Console.WriteLine("Reset Not Found"); +await Reset_NotFound(managementClient); + +Console.WriteLine("CreateContinuous"); +await CreateContinuous(managementClient); +Console.WriteLine("CreateContinuous conflict"); +await CreateContinuous_Conflict(managementClient); +//Console.WriteLine("CreateOneTime"); +//await CreateOneTime(managementClient); +Console.WriteLine("Update"); +await Update(managementClient); +Console.WriteLine("Update_NotFound"); +await Update_NotFound(managementClient); +Console.WriteLine("ListAll"); +await ListAll(managementClient); +Console.WriteLine("ListContinuous"); +await ListContinuous(managementClient); +Console.WriteLine("GetStatus"); +await GetStatus(managementClient); +// Console.WriteLine("GetState"); +// await GetState(managementClient); +Console.WriteLine("GetResult"); +await GetResult(managementClient); + +return; + +static EventStoreProjectionManagementClient ManagementClient(string connection) { + #region createClient + + var settings = EventStoreClientSettings.Create(connection); + settings.ConnectionName = "Projection management client"; + settings.DefaultCredentials = new UserCredentials("admin", "changeit"); + var managementClient = new EventStoreProjectionManagementClient(settings); + + #endregion createClient + + return managementClient; +} + +static async Task RestartSubSystem(EventStoreProjectionManagementClient managementClient) { + #region RestartSubSystem + + await managementClient.RestartSubsystemAsync(); + + #endregion RestartSubSystem +} + +static async Task Disable(EventStoreProjectionManagementClient managementClient) { + #region Disable + + await managementClient.DisableAsync("$by_category"); + + #endregion Disable +} + +static async Task DisableNotFound(EventStoreProjectionManagementClient managementClient) { + #region DisableNotFound + + try { + await managementClient.DisableAsync("projection that does not exists"); + } + catch (RpcException e) when (e.StatusCode is StatusCode.NotFound) { + Console.WriteLine(e.Message); + } + catch (RpcException e) when (e.Message.Contains("NotFound")) { // will be removed in a future release + Console.WriteLine(e.Message); + } + + #endregion DisableNotFound +} + +static async Task Enable(EventStoreProjectionManagementClient managementClient) { + #region Enable + + await managementClient.EnableAsync("$by_category"); + + #endregion Enable +} + +static async Task EnableNotFound(EventStoreProjectionManagementClient managementClient) { + #region EnableNotFound + + try { + await managementClient.EnableAsync("projection that does not exists"); + } + catch (RpcException e) when (e.StatusCode is StatusCode.NotFound) { + Console.WriteLine(e.Message); + } + catch (RpcException e) when (e.Message.Contains("NotFound")) { // will be removed in a future release + Console.WriteLine(e.Message); + } + + #endregion EnableNotFound +} + +static Task Delete(EventStoreProjectionManagementClient managementClient) { + #region Delete + + // this is not yet available in the .net grpc client + + #endregion Delete + + return Task.CompletedTask; +} + +static async Task Abort(EventStoreProjectionManagementClient managementClient) { + try { + var js = + "fromAll() .when({$init:function(){return {count:0};},$any:function(s, e){s.count += 1;}}).outputState();"; + + await managementClient.CreateContinuousAsync("countEvents_Abort", js); + } + catch (RpcException e) when (e.StatusCode is StatusCode.Aborted) { + // ignore was already created in a previous run + } + catch (RpcException e) when (e.Message.Contains("Conflict")) { // will be removed in a future release + // ignore was already created in a previous run + } + + #region Abort + + // The .net clients prior to version 21.6 had an incorrect behavior: they will save the checkpoint. + await managementClient.AbortAsync("countEvents_Abort"); + + #endregion Abort +} + +static async Task Abort_NotFound(EventStoreProjectionManagementClient managementClient) { + #region Abort_NotFound + + try { + await managementClient.AbortAsync("projection that does not exists"); + } + catch (RpcException e) when (e.StatusCode is StatusCode.NotFound) { + Console.WriteLine(e.Message); + } + catch (RpcException e) when (e.Message.Contains("NotFound")) { // will be removed in a future release + Console.WriteLine(e.Message); + } + + #endregion Abort_NotFound +} + +static async Task Reset(EventStoreProjectionManagementClient managementClient) { + try { + var js = + "fromAll() .when({$init:function(){return {count:0};},$any:function(s, e){s.count += 1;}}).outputState();"; + + await managementClient.CreateContinuousAsync("countEvents_Reset", js); + } + catch (RpcException e) when (e.StatusCode is StatusCode.Internal) { + // ignore was already created in a previous run + } + catch (RpcException e) when (e.Message.Contains("Conflict")) { // will be removed in a future release + // ignore was already created in a previous run + } + + #region Reset + + // Checkpoint will be written prior to resetting the projection + await managementClient.ResetAsync("countEvents_Reset"); + + #endregion Reset +} + +static async Task Reset_NotFound(EventStoreProjectionManagementClient managementClient) { + #region Reset_NotFound + + try { + await managementClient.ResetAsync("projection that does not exists"); + } + catch (RpcException e) when (e.StatusCode is StatusCode.NotFound) { + Console.WriteLine(e.Message); + } + catch (RpcException e) when (e.Message.Contains("NotFound")) { // will be removed in a future release + Console.WriteLine(e.Message); + } + + #endregion Reset_NotFound +} + +static async Task CreateOneTime(EventStoreProjectionManagementClient managementClient) { + const string js = + "fromAll() .when({$init:function(){return {count:0};},$any:function(s, e){s.count += 1;}}).outputState();"; + + await managementClient.CreateOneTimeAsync(js); +} + +static async Task CreateContinuous(EventStoreProjectionManagementClient managementClient) { + #region CreateContinuous + + const string js = @"fromAll() .when({ $init: function() { return { @@ -214,14 +241,15 @@ private static async Task CreateContinuous(EventStoreProjectionManagementClient } }) .outputState();"; - var name = $"countEvents_Create_{Guid.NewGuid()}"; - await managementClient.CreateContinuousAsync(name, js); - #endregion CreateContinuous - } - private static async Task CreateContinuous_Conflict(EventStoreProjectionManagementClient managementClient) { + var name = $"countEvents_Create_{Guid.NewGuid()}"; + await managementClient.CreateContinuousAsync(name, js); - const string js = @"fromAll() + #endregion CreateContinuous +} + +static async Task CreateContinuous_Conflict(EventStoreProjectionManagementClient managementClient) { + const string js = @"fromAll() .when({ $init: function() { return { @@ -233,25 +261,30 @@ private static async Task CreateContinuous_Conflict(EventStoreProjectionManageme } }) .outputState();"; - var name = $"countEvents_Create_{Guid.NewGuid()}"; - - #region CreateContinuous_Conflict - await managementClient.CreateContinuousAsync(name, js); - try { - - await managementClient.CreateContinuousAsync(name, js); - } catch (RpcException e) when (e.StatusCode is StatusCode.AlreadyExists) { - Console.WriteLine(e.Message); - } catch (RpcException e) when (e.Message.Contains("Conflict")) { // will be removed in a future release - var format = $"{name} already exists"; - Console.WriteLine(format); - } - #endregion CreateContinuous_Conflict - } - - private static async Task Update(EventStoreProjectionManagementClient managementClient) { - #region Update - const string js = @"fromAll() + + var name = $"countEvents_Create_{Guid.NewGuid()}"; + + #region CreateContinuous_Conflict + + await managementClient.CreateContinuousAsync(name, js); + try { + await managementClient.CreateContinuousAsync(name, js); + } + catch (RpcException e) when (e.StatusCode is StatusCode.AlreadyExists) { + Console.WriteLine(e.Message); + } + catch (RpcException e) when (e.Message.Contains("Conflict")) { // will be removed in a future release + var format = $"{name} already exists"; + Console.WriteLine(format); + } + + #endregion CreateContinuous_Conflict +} + +static async Task Update(EventStoreProjectionManagementClient managementClient) { + #region Update + + const string js = @"fromAll() .when({ $init: function() { return { @@ -263,92 +296,107 @@ private static async Task Update(EventStoreProjectionManagementClient management } }) .outputState();"; - var name = $"countEvents_Update_{Guid.NewGuid()}"; - - await managementClient.CreateContinuousAsync(name, "fromAll().when()"); - await managementClient.UpdateAsync(name, js); - #endregion Update - } - - private static async Task Update_NotFound(EventStoreProjectionManagementClient managementClient) { - #region Update_NotFound - try { - await managementClient.UpdateAsync("Update Not existing projection", "fromAll().when()"); - } catch (RpcException e) when (e.StatusCode is StatusCode.NotFound) { - Console.WriteLine(e.Message); - } catch (RpcException e) when (e.Message.Contains("NotFound")) { // will be removed in a future release - Console.WriteLine("'Update Not existing projection' does not exists and can not be updated"); - } - #endregion Update_NotFound - } - - private static async Task ListAll(EventStoreProjectionManagementClient managementClient) { - #region ListAll - var details = managementClient.ListAllAsync(); - await foreach (var detail in details) { - Console.WriteLine( - $@"{detail.Name}, {detail.Status}, {detail.CheckpointStatus}, {detail.Mode}, {detail.Progress}"); - } - #endregion ListAll - } - - private static async Task ListContinuous(EventStoreProjectionManagementClient managementClient) { - #region ListContinuous - var details = managementClient.ListContinuousAsync(); - await foreach (var detail in details) { - Console.WriteLine( - $@"{detail.Name}, {detail.Status}, {detail.CheckpointStatus}, {detail.Mode}, {detail.Progress}"); - } - #endregion ListContinuous - - } - - private static async Task GetStatus(EventStoreProjectionManagementClient managementClient) { - const string js = - "fromAll().when({$init:function(){return {count:0};},$any:function(s, e){s.count += 1;}}).outputState();"; - var name = $"countEvents_status_{Guid.NewGuid()}"; - - #region GetStatus - await managementClient.CreateContinuousAsync(name, js); - var status = await managementClient.GetStatusAsync(name); - Console.WriteLine( - $@"{status?.Name}, {status?.Status}, {status?.CheckpointStatus}, {status?.Mode}, {status?.Progress}"); - #endregion GetStatus - } - - private static async Task GetState(EventStoreProjectionManagementClient managementClient) { - - // will have to wait for the client to be fixed before we import in the doc - - #region GetState - const string js = - "fromAll().when({$init:function(){return {count:0};},$any:function(s, e){s.count += 1;}}).outputState();"; - var name = $"countEvents_State_{Guid.NewGuid()}"; - - await managementClient.CreateContinuousAsync(name, js); - //give it some time to process and have a state. - await Task.Delay(500); - - var stateDocument = await managementClient.GetStateAsync(name); - var result = await managementClient.GetStateAsync(name); - - Console.WriteLine(DocToString(stateDocument)); - Console.WriteLine(result); - - static async Task DocToString(JsonDocument d) { - await using var stream = new MemoryStream(); - Utf8JsonWriter writer = new Utf8JsonWriter(stream, new JsonWriterOptions { Indented = false }); - d.WriteTo(writer); - await writer.FlushAsync(); - return Encoding.UTF8.GetString(stream.ToArray()); - } - #endregion GetState - } - - private static async Task GetResult(EventStoreProjectionManagementClient managementClient) { - - #region GetResult - const string js = @"fromAll() + + var name = $"countEvents_Update_{Guid.NewGuid()}"; + + await managementClient.CreateContinuousAsync(name, "fromAll().when()"); + await managementClient.UpdateAsync(name, js); + + #endregion Update +} + +static async Task Update_NotFound(EventStoreProjectionManagementClient managementClient) { + #region Update_NotFound + + try { + await managementClient.UpdateAsync("Update Not existing projection", "fromAll().when()"); + } + catch (RpcException e) when (e.StatusCode is StatusCode.NotFound) { + Console.WriteLine(e.Message); + } + catch (RpcException e) when (e.Message.Contains("NotFound")) { // will be removed in a future release + Console.WriteLine("'Update Not existing projection' does not exists and can not be updated"); + } + + #endregion Update_NotFound +} + +static async Task ListAll(EventStoreProjectionManagementClient managementClient) { + #region ListAll + + var details = managementClient.ListAllAsync(); + await foreach (var detail in details) + Console.WriteLine( + $@"{detail.Name}, {detail.Status}, {detail.CheckpointStatus}, {detail.Mode}, {detail.Progress}" + ); + + #endregion ListAll +} + +static async Task ListContinuous(EventStoreProjectionManagementClient managementClient) { + #region ListContinuous + + var details = managementClient.ListContinuousAsync(); + await foreach (var detail in details) + Console.WriteLine( + $@"{detail.Name}, {detail.Status}, {detail.CheckpointStatus}, {detail.Mode}, {detail.Progress}" + ); + + #endregion ListContinuous +} + +static async Task GetStatus(EventStoreProjectionManagementClient managementClient) { + const string js = + "fromAll().when({$init:function(){return {count:0};},$any:function(s, e){s.count += 1;}}).outputState();"; + + var name = $"countEvents_status_{Guid.NewGuid()}"; + + #region GetStatus + + await managementClient.CreateContinuousAsync(name, js); + var status = await managementClient.GetStatusAsync(name); + Console.WriteLine( + $@"{status?.Name}, {status?.Status}, {status?.CheckpointStatus}, {status?.Mode}, {status?.Progress}" + ); + + #endregion GetStatus +} + +static async Task GetState(EventStoreProjectionManagementClient managementClient) { + // will have to wait for the client to be fixed before we import in the doc + + #region GetState + + const string js = + "fromAll().when({$init:function(){return {count:0};},$any:function(s, e){s.count += 1;}}).outputState();"; + + var name = $"countEvents_State_{Guid.NewGuid()}"; + + await managementClient.CreateContinuousAsync(name, js); + //give it some time to process and have a state. + await Task.Delay(500); + + var stateDocument = await managementClient.GetStateAsync(name); + var result = await managementClient.GetStateAsync(name); + + Console.WriteLine(DocToString(stateDocument)); + Console.WriteLine(result); + + static async Task DocToString(JsonDocument d) { + await using var stream = new MemoryStream(); + var writer = new Utf8JsonWriter(stream, new JsonWriterOptions { Indented = false }); + d.WriteTo(writer); + await writer.FlushAsync(); + return Encoding.UTF8.GetString(stream.ToArray()); + } + + #endregion GetState +} + +static async Task GetResult(EventStoreProjectionManagementClient managementClient) { + #region GetResult + + const string js = @"fromAll() .when({ $init: function() { return { @@ -360,43 +408,48 @@ private static async Task GetResult(EventStoreProjectionManagementClient managem } }) .outputState();"; - var name = $"countEvents_Result_{Guid.NewGuid()}"; - - await managementClient.CreateContinuousAsync(name, js); - await Task.Delay(500); //give it some time to have a result. - - // Results are retrieved either as JsonDocument or a typed result - var document = await managementClient.GetResultAsync(name); - var result = await managementClient.GetResultAsync(name); - - Console.WriteLine(DocToString(document)); - Console.WriteLine(result); - - static string DocToString(JsonDocument d) { - using var stream = new MemoryStream(); - using Utf8JsonWriter writer = new Utf8JsonWriter(stream, new JsonWriterOptions { Indented = false }); - d.WriteTo(writer); - writer.Flush(); - return Encoding.UTF8.GetString(stream.ToArray()); - } - #endregion GetResult - } - - public class Result { - public int count { get; set; } - public override string ToString() => $"count= {count}"; - }; - - private static async Task Populate(string connection, int numberOfEvents) { - var settings = EventStoreClientSettings.Create(connection); - settings.DefaultCredentials = new UserCredentials("admin", "changeit"); - var client = new EventStoreClient(settings); - var messages = Enumerable.Range(0, numberOfEvents).Select(number => - new EventData(Uuid.NewUuid(), - "eventtype", - Encoding.UTF8.GetBytes($@"{{ ""Id"":{number} }}")) - ); - await client.AppendToStreamAsync("sample", StreamState.Any, messages); - } + + var name = $"countEvents_Result_{Guid.NewGuid()}"; + + await managementClient.CreateContinuousAsync(name, js); + await Task.Delay(500); //give it some time to have a result. + + // Results are retrieved either as JsonDocument or a typed result + var document = await managementClient.GetResultAsync(name); + var result = await managementClient.GetResultAsync(name); + + Console.WriteLine(DocToString(document)); + Console.WriteLine(result); + + static string DocToString(JsonDocument d) { + using var stream = new MemoryStream(); + using var writer = new Utf8JsonWriter(stream, new JsonWriterOptions { Indented = false }); + d.WriteTo(writer); + writer.Flush(); + return Encoding.UTF8.GetString(stream.ToArray()); } + + #endregion GetResult } + +static async Task Populate(string connection, int numberOfEvents) { + var settings = EventStoreClientSettings.Create(connection); + settings.DefaultCredentials = new UserCredentials("admin", "changeit"); + var client = new EventStoreClient(settings); + var messages = Enumerable.Range(0, numberOfEvents).Select( + number => + new EventData( + Uuid.NewUuid(), + "eventtype", + Encoding.UTF8.GetBytes($@"{{ ""Id"":{number} }}") + ) + ); + + await client.AppendToStreamAsync("sample", StreamState.Any, messages); +} + +public class Result { + public int count { get; set; } + + public override string ToString() => $"count= {count}"; +}; \ No newline at end of file diff --git a/samples/quick-start/Program.cs b/samples/quick-start/Program.cs index e79b524d9..7ffb748c7 100644 --- a/samples/quick-start/Program.cs +++ b/samples/quick-start/Program.cs @@ -1,77 +1,69 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net.Http; -using System.Net.Security; -using System.Security.Cryptography.X509Certificates; -using System.Text; -using System.Text.Json; -using System.Threading; -using System.Threading.Tasks; -using EventStore.Client; - -namespace quick_start { - public class TestEvent { - public string? EntityId { get; set; } - public string? ImportantData { get; set; } - } - - class Program { - static void Main(string[] args) { - } - - static async Task Samples() { - CancellationTokenSource tokenSource = new CancellationTokenSource(); - CancellationToken cancellationToken = tokenSource.Token; - - #region createClient - var settings = EventStoreClientSettings - .Create("{connectionString}"); - var client = new EventStoreClient(settings); - #endregion createClient - - #region createEvent - var evt = new TestEvent - { - EntityId = Guid.NewGuid().ToString("N"), - ImportantData = "I wrote my first event!" - }; - - var eventData = new EventData( - Uuid.NewUuid(), - "TestEvent", - JsonSerializer.SerializeToUtf8Bytes(evt) - ); - #endregion createEvent - - #region appendEvents - await client.AppendToStreamAsync( - "some-stream", - StreamState.Any, - new[] { eventData }, - cancellationToken: cancellationToken - ); - #endregion appendEvents - - #region overriding-user-credentials - await client.AppendToStreamAsync( - "some-stream", - StreamState.Any, - new[] { eventData }, - userCredentials: new UserCredentials("admin", "changeit"), - cancellationToken: cancellationToken - ); - #endregion overriding-user-credentials - - #region readStream - var result = client.ReadStreamAsync( - Direction.Forwards, - "some-stream", - StreamPosition.Start, - cancellationToken: cancellationToken); - - var events = await result.ToListAsync(cancellationToken); - #endregion readStream - } - } -} +using System.Text.Json; + +var tokenSource = new CancellationTokenSource(); +var cancellationToken = tokenSource.Token; + +#region createClient + +var settings = EventStoreClientSettings + .Create("{connectionString}"); + +var client = new EventStoreClient(settings); + +#endregion createClient + +#region createEvent + +var evt = new TestEvent { + EntityId = Guid.NewGuid().ToString("N"), + ImportantData = "I wrote my first event!" +}; + +var eventData = new EventData( + Uuid.NewUuid(), + "TestEvent", + JsonSerializer.SerializeToUtf8Bytes(evt) +); + +#endregion createEvent + +#region appendEvents + +await client.AppendToStreamAsync( + "some-stream", + StreamState.Any, + new[] { eventData }, + cancellationToken: cancellationToken +); + +#endregion appendEvents + +#region overriding-user-credentials + +await client.AppendToStreamAsync( + "some-stream", + StreamState.Any, + new[] { eventData }, + userCredentials: new UserCredentials("admin", "changeit"), + cancellationToken: cancellationToken +); + +#endregion overriding-user-credentials + +#region readStream + +var result = client.ReadStreamAsync( + Direction.Forwards, + "some-stream", + StreamPosition.Start, + cancellationToken: cancellationToken +); + +var events = await result.ToListAsync(cancellationToken); + +#endregion readStream + +public class TestEvent { + public string? EntityId { get; set; } + public string? ImportantData { get; set; } +} \ No newline at end of file diff --git a/samples/quick-start/docker-compose.yml b/samples/quick-start/docker-compose.yml index 9001ea312..2a96c51a8 100644 --- a/samples/quick-start/docker-compose.yml +++ b/samples/quick-start/docker-compose.yml @@ -6,4 +6,4 @@ services: - EVENTSTORE_INSECURE=true - EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP=true ports: - - 2113:2113 + - "2113:2113" diff --git a/samples/reading-events/Program.cs b/samples/reading-events/Program.cs index c09c64238..854634da8 100644 --- a/samples/reading-events/Program.cs +++ b/samples/reading-events/Program.cs @@ -1,295 +1,321 @@ -using System; -using System.Linq; -using System.Net.Http; -using System.Reflection; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using EventStore.Client; - -namespace reading_events { - class Program { - static async Task Main(string[] args) { - using var client = new EventStoreClient( - EventStoreClientSettings.Create("esdb://localhost:2113?tls=false") - ); - - var events = Enumerable.Range(0, 20) - .Select(r => new EventData( - Uuid.NewUuid(), - "some-event", - Encoding.UTF8.GetBytes("{\"id\": \"" + r + "\" \"value\": \"some value\"}"))); - - await client.AppendToStreamAsync( - "some-stream", - StreamState.Any, - events); - - await ReadFromStream(client); - - return; - } +#pragma warning disable CS8321 // Local function is declared but never used - private static async Task ReadFromStream(EventStoreClient client) { - #region read-from-stream - var events = client.ReadStreamAsync( - Direction.Forwards, - "some-stream", - StreamPosition.Start); - #endregion read-from-stream - - #region iterate-stream - await foreach (var @event in events) { - Console.WriteLine(Encoding.UTF8.GetString(@event.Event.Data.ToArray())); - } - #endregion iterate-stream - - #region #read-from-stream-positions - Console.WriteLine(events.FirstStreamPosition); - Console.WriteLine(events.LastStreamPosition); - #endregion - } +await using var client = new EventStoreClient(EventStoreClientSettings.Create("esdb://localhost:2113?tls=false")); - private static async Task ReadFromStreamMessages(EventStoreClient client) { - #region read-from-stream-messages - var streamPosition = StreamPosition.Start; - var results = client.ReadStreamAsync( - Direction.Forwards, - "some-stream", - streamPosition); - #endregion read-from-stream-messages - - #region iterate-stream-messages - await foreach (var message in results.Messages) { - switch (message) { - case StreamMessage.Ok ok: - Console.WriteLine("Stream found."); - break; - case StreamMessage.NotFound: - Console.WriteLine("Stream not found."); - return; - case StreamMessage.Event(var resolvedEvent): - Console.WriteLine(Encoding.UTF8.GetString(resolvedEvent.Event.Data.Span)); - break; - case StreamMessage.FirstStreamPosition(var sp): - Console.WriteLine($"{sp} is after {streamPosition}; updating checkpoint."); - streamPosition = sp; - break; - case StreamMessage.LastStreamPosition(var sp): - Console.WriteLine($"The end of the stream is {sp}"); - break; - default: - break; - } - } - #endregion iterate-stream-messages - } +var events = Enumerable.Range(0, 20) + .Select( + r => new EventData( + Uuid.NewUuid(), + "some-event", + Encoding.UTF8.GetBytes($"{{\"id\": \"{r}\" \"value\": \"some value\"}}") + ) + ); - private static async Task ReadFromStreamPosition(EventStoreClient client) { - #region read-from-stream-position - var events = client.ReadStreamAsync( - Direction.Forwards, - "some-stream", - revision: 10, - maxCount: 20); - #endregion read-from-stream-position - - #region iterate-stream - await foreach (var @event in events) { - Console.WriteLine(Encoding.UTF8.GetString(@event.Event.Data.ToArray())); - } - #endregion iterate-stream - } +await client.AppendToStreamAsync( + "some-stream", + StreamState.Any, + events +); + +await ReadFromStream(client); + +return; + +static async Task ReadFromStream(EventStoreClient client) { + #region read-from-stream + + var events = client.ReadStreamAsync( + Direction.Forwards, + "some-stream", + StreamPosition.Start + ); + + #endregion read-from-stream + + #region iterate-stream + + await foreach (var @event in events) Console.WriteLine(Encoding.UTF8.GetString(@event.Event.Data.ToArray())); + + #endregion iterate-stream + + #region #read-from-stream-positions - private static async Task ReadFromStreamPositionCheck(EventStoreClient client) { - #region checking-for-stream-presence - var result = client.ReadStreamAsync( - Direction.Forwards, - "some-stream", - revision: 10, - maxCount: 20); + Console.WriteLine(events.FirstStreamPosition); + Console.WriteLine(events.LastStreamPosition); - if (await result.ReadState == ReadState.StreamNotFound) { + #endregion +} + +static async Task ReadFromStreamMessages(EventStoreClient client) { + #region read-from-stream-messages + + var streamPosition = StreamPosition.Start; + var results = client.ReadStreamAsync( + Direction.Forwards, + "some-stream", + streamPosition + ); + + #endregion read-from-stream-messages + + #region iterate-stream-messages + + await foreach (var message in results.Messages) + switch (message) { + case StreamMessage.Ok ok: + Console.WriteLine("Stream found."); + break; + + case StreamMessage.NotFound: + Console.WriteLine("Stream not found."); return; - } - await foreach (var e in result) { - Console.WriteLine(Encoding.UTF8.GetString(e.Event.Data.ToArray())); - } - #endregion checking-for-stream-presence - } + case StreamMessage.Event(var resolvedEvent): + Console.WriteLine(Encoding.UTF8.GetString(resolvedEvent.Event.Data.Span)); + break; - private static async Task ReadFromStreamBackwards(EventStoreClient client) { - #region reading-backwards - var events = client.ReadStreamAsync( - Direction.Backwards, - "some-stream", - StreamPosition.End); - - await foreach (var e in events) { - Console.WriteLine(Encoding.UTF8.GetString(e.Event.Data.ToArray())); - } - #endregion reading-backwards - } + case StreamMessage.FirstStreamPosition(var sp): + Console.WriteLine($"{sp} is after {streamPosition}; updating checkpoint."); + streamPosition = sp; + break; - private static async Task ReadFromStreamMessagesBackwards(EventStoreClient client) { - #region read-from-stream-messages-backwards - var results = client.ReadStreamAsync( - Direction.Forwards, - "some-stream", - StreamPosition.End); - #endregion read-from-stream-messages-backwards - - #region iterate-stream-messages-backwards - await foreach (var message in results.Messages) { - switch (message) { - case StreamMessage.Ok ok: - Console.WriteLine("Stream found."); - break; - case StreamMessage.NotFound: - Console.WriteLine("Stream not found."); - return; - case StreamMessage.Event(var resolvedEvent): - Console.WriteLine(Encoding.UTF8.GetString(resolvedEvent.Event.Data.Span)); - break; - case StreamMessage.LastStreamPosition(var sp): - Console.WriteLine($"The end of the stream is {sp}"); - break; - } - } - #endregion iterate-stream-messages-backwards + case StreamMessage.LastStreamPosition(var sp): + Console.WriteLine($"The end of the stream is {sp}"); + break; + + default: + break; } + #endregion iterate-stream-messages +} - private static async Task ReadFromAllStream(EventStoreClient client) { - #region read-from-all-stream - var events = client.ReadAllAsync( - Direction.Forwards, Position.Start); - #endregion read-from-all-stream +static async Task ReadFromStreamPosition(EventStoreClient client) { + #region read-from-stream-position - #region read-from-all-stream-iterate - await foreach (var e in events) { - Console.WriteLine(Encoding.UTF8.GetString(e.Event.Data.ToArray())); - } - #endregion read-from-all-stream-iterate - } + var events = client.ReadStreamAsync( + Direction.Forwards, + "some-stream", + 10, + 20 + ); - private static async Task ReadFromAllStreamMessages(EventStoreClient client) { - #region read-from-all-stream-messages - var position = Position.Start; - var results = client.ReadAllAsync( - Direction.Forwards, - position: position); - #endregion read-from-all-stream-messages - - #region iterate-all-stream-messages - await foreach (var message in results.Messages) { - switch (message) { - case StreamMessage.Event(var resolvedEvent): - Console.WriteLine(Encoding.UTF8.GetString(resolvedEvent.Event.Data.Span)); - break; - case StreamMessage.LastAllStreamPosition(var p): - Console.WriteLine($"The end of the $all stream is {p}"); - break; - } - } - #endregion iterate-all-stream-messages - } + #endregion read-from-stream-position - private static async Task IgnoreSystemEvents(EventStoreClient client) { - #region ignore-system-events - var events = client.ReadAllAsync( - Direction.Forwards, Position.Start); + #region iterate-stream - await foreach (var e in events) { - if (e.Event.EventType.StartsWith("$")) { - continue; - } + await foreach (var @event in events) Console.WriteLine(Encoding.UTF8.GetString(@event.Event.Data.ToArray())); - Console.WriteLine(Encoding.UTF8.GetString(e.Event.Data.ToArray())); - } - #endregion ignore-system-events - } + #endregion iterate-stream +} - private static async Task ReadFromAllStreamBackwards(EventStoreClient client) { - #region read-from-all-stream-backwards - var events = client.ReadAllAsync( - Direction.Backwards, Position.End); - #endregion read-from-all-stream-backwards - - #region read-from-all-stream-iterate - await foreach (var e in events) { - Console.WriteLine(Encoding.UTF8.GetString(e.Event.Data.ToArray())); - } - #endregion read-from-all-stream-iterate - } +static async Task ReadFromStreamPositionCheck(EventStoreClient client) { + #region checking-for-stream-presence - private static async Task ReadFromAllStreamBackwardsMessages(EventStoreClient client) { - #region read-from-all-stream-messages-backwards - var position = Position.End; - var results = client.ReadAllAsync( - Direction.Backwards, - position: position); - #endregion read-from-all-stream-messages-backwards - - #region iterate-all-stream-messages-backwards - await foreach (var message in results.Messages) { - switch (message) { - case StreamMessage.Event(var resolvedEvent): - Console.WriteLine(Encoding.UTF8.GetString(resolvedEvent.Event.Data.Span)); - break; - case StreamMessage.LastAllStreamPosition(var p): - Console.WriteLine($"{p} is before {position}; updating checkpoint."); - position = p; - break; - } - } - #endregion iterate-all-stream-messages-backwards - } + var result = client.ReadStreamAsync( + Direction.Forwards, + "some-stream", + 10, + 20 + ); - private static async Task FilteringOutSystemEvents(EventStoreClient client) { - var events = client.ReadAllAsync(Direction.Forwards, Position.Start); + if (await result.ReadState == ReadState.StreamNotFound) return; - await foreach (var e in events) { - if (!e.Event.EventType.StartsWith("$")) { - Console.WriteLine(Encoding.UTF8.GetString(e.Event.Data.ToArray())); - } - } - } + await foreach (var e in result) Console.WriteLine(Encoding.UTF8.GetString(e.Event.Data.ToArray())); - private void ReadStreamOverridingUserCredentials(EventStoreClient client, CancellationToken cancellationToken) - { - #region overriding-user-credentials - var result = client.ReadStreamAsync( - Direction.Forwards, - "some-stream", - StreamPosition.Start, - userCredentials: new UserCredentials("admin", "changeit"), - cancellationToken: cancellationToken); - #endregion overriding-user-credentials - } + #endregion checking-for-stream-presence +} + +static async Task ReadFromStreamBackwards(EventStoreClient client) { + #region reading-backwards + + var events = client.ReadStreamAsync( + Direction.Backwards, + "some-stream", + StreamPosition.End + ); + + await foreach (var e in events) Console.WriteLine(Encoding.UTF8.GetString(e.Event.Data.ToArray())); + + #endregion reading-backwards +} + +static async Task ReadFromStreamMessagesBackwards(EventStoreClient client) { + #region read-from-stream-messages-backwards + + var results = client.ReadStreamAsync( + Direction.Forwards, + "some-stream", + StreamPosition.End + ); + + #endregion read-from-stream-messages-backwards + + #region iterate-stream-messages-backwards + + await foreach (var message in results.Messages) + switch (message) { + case StreamMessage.Ok ok: + Console.WriteLine("Stream found."); + break; - private void ReadAllOverridingUserCredentials(EventStoreClient client, CancellationToken cancellationToken) - { - #region read-all-overriding-user-credentials - var result = client.ReadAllAsync( - Direction.Forwards, - Position.Start, - userCredentials: new UserCredentials("admin", "changeit"), - cancellationToken: cancellationToken); - #endregion read-all-overriding-user-credentials + case StreamMessage.NotFound: + Console.WriteLine("Stream not found."); + return; + + case StreamMessage.Event(var resolvedEvent): + Console.WriteLine(Encoding.UTF8.GetString(resolvedEvent.Event.Data.Span)); + break; + + case StreamMessage.LastStreamPosition(var sp): + Console.WriteLine($"The end of the stream is {sp}"); + break; } - - - private void ReadAllResolvingLinkTos(EventStoreClient client, CancellationToken cancellationToken) - { - #region read-from-all-stream-resolving-link-Tos - var result = client.ReadAllAsync( - Direction.Forwards, - Position.Start, - resolveLinkTos: true, - cancellationToken: cancellationToken); - #endregion read-from-all-stream-resolving-link-Tos + + #endregion iterate-stream-messages-backwards +} + +static async Task ReadFromAllStream(EventStoreClient client) { + #region read-from-all-stream + + var events = client.ReadAllAsync(Direction.Forwards, Position.Start); + + #endregion read-from-all-stream + + #region read-from-all-stream-iterate + + await foreach (var e in events) Console.WriteLine(Encoding.UTF8.GetString(e.Event.Data.ToArray())); + + #endregion read-from-all-stream-iterate +} + +static async Task ReadFromAllStreamMessages(EventStoreClient client) { + #region read-from-all-stream-messages + + var position = Position.Start; + var results = client.ReadAllAsync( + Direction.Forwards, + position + ); + + #endregion read-from-all-stream-messages + + #region iterate-all-stream-messages + + await foreach (var message in results.Messages) + switch (message) { + case StreamMessage.Event(var resolvedEvent): + Console.WriteLine(Encoding.UTF8.GetString(resolvedEvent.Event.Data.Span)); + break; + + case StreamMessage.LastAllStreamPosition(var p): + Console.WriteLine($"The end of the $all stream is {p}"); + break; } + + #endregion iterate-all-stream-messages +} + +static async Task IgnoreSystemEvents(EventStoreClient client) { + #region ignore-system-events + + var events = client.ReadAllAsync(Direction.Forwards, Position.Start); + + await foreach (var e in events) { + if (e.Event.EventType.StartsWith("$")) continue; + + Console.WriteLine(Encoding.UTF8.GetString(e.Event.Data.ToArray())); } + + #endregion ignore-system-events } + +static async Task ReadFromAllStreamBackwards(EventStoreClient client) { + #region read-from-all-stream-backwards + + var events = client.ReadAllAsync(Direction.Backwards, Position.End); + + #endregion read-from-all-stream-backwards + + #region read-from-all-stream-iterate + + await foreach (var e in events) Console.WriteLine(Encoding.UTF8.GetString(e.Event.Data.ToArray())); + + #endregion read-from-all-stream-iterate +} + +static async Task ReadFromAllStreamBackwardsMessages(EventStoreClient client) { + #region read-from-all-stream-messages-backwards + + var position = Position.End; + var results = client.ReadAllAsync( + Direction.Backwards, + position + ); + + #endregion read-from-all-stream-messages-backwards + + #region iterate-all-stream-messages-backwards + + await foreach (var message in results.Messages) + switch (message) { + case StreamMessage.Event(var resolvedEvent): + Console.WriteLine(Encoding.UTF8.GetString(resolvedEvent.Event.Data.Span)); + break; + + case StreamMessage.LastAllStreamPosition(var p): + Console.WriteLine($"{p} is before {position}; updating checkpoint."); + position = p; + break; + } + + #endregion iterate-all-stream-messages-backwards +} + +static async Task FilteringOutSystemEvents(EventStoreClient client) { + var events = client.ReadAllAsync(Direction.Forwards, Position.Start); + + await foreach (var e in events) + if (!e.Event.EventType.StartsWith("$")) + Console.WriteLine(Encoding.UTF8.GetString(e.Event.Data.ToArray())); +} + +static void ReadStreamOverridingUserCredentials(EventStoreClient client, CancellationToken cancellationToken) { + #region overriding-user-credentials + + var result = client.ReadStreamAsync( + Direction.Forwards, + "some-stream", + StreamPosition.Start, + userCredentials: new UserCredentials("admin", "changeit"), + cancellationToken: cancellationToken + ); + + #endregion overriding-user-credentials +} + +static void ReadAllOverridingUserCredentials(EventStoreClient client, CancellationToken cancellationToken) { + #region read-all-overriding-user-credentials + + var result = client.ReadAllAsync( + Direction.Forwards, + Position.Start, + userCredentials: new UserCredentials("admin", "changeit"), + cancellationToken: cancellationToken + ); + + #endregion read-all-overriding-user-credentials +} + +static void ReadAllResolvingLinkTos(EventStoreClient client, CancellationToken cancellationToken) { + #region read-from-all-stream-resolving-link-Tos + + var result = client.ReadAllAsync( + Direction.Forwards, + Position.Start, + resolveLinkTos: true, + cancellationToken: cancellationToken + ); + + #endregion read-from-all-stream-resolving-link-Tos +} \ No newline at end of file diff --git a/samples/secure-with-tls/Program.cs b/samples/secure-with-tls/Program.cs index e7c1433b2..2f9857f76 100644 --- a/samples/secure-with-tls/Program.cs +++ b/samples/secure-with-tls/Program.cs @@ -1,69 +1,58 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading.Tasks; -using EventStore.Client; -using Grpc.Core; +using Grpc.Core; -namespace secure_with_tls -{ - class Program - { - private const string NoNodeConnectionErrorMessage = - "No connection could be made because the target machine actively refused it."; - - private const string ConnectionRefused = - "Connection refused"; +const string noNodeConnectionErrorMessage = "No connection could be made because the target machine actively refused it."; +const string connectionRefused = "Connection refused"; +const string certificateIsNotInstalledOrInvalidErrorMessage = "The remote certificate is invalid according to the validation procedure."; - private const string CertificateIsNotInstalledOrInvalidErrorMessage = - "The remote certificate is invalid according to the validation procedure."; - - static async Task Main(string[] args) - { - // take the address from environment variable (when run with Docker) or use localhost by default - var connectionString = Environment.GetEnvironmentVariable("ESDB_CONNECTION_STRING") ?? "esdb://localhost:2113?tls=true"; +// take the address from environment variable (when run with Docker) or use localhost by default +var connectionString = Environment.GetEnvironmentVariable("ESDB_CONNECTION_STRING") ?? "esdb://localhost:2113?tls=true"; - Console.WriteLine($"Connecting to EventStoreDB at: `{connectionString}`"); - - using var client = new EventStoreClient(EventStoreClientSettings.Create(connectionString)); - - var eventData = new EventData( - Uuid.NewUuid(), - "some-event", - Encoding.UTF8.GetBytes("{\"id\": \"1\" \"value\": \"some value\"}") - ); +Console.WriteLine($"Connecting to EventStoreDB at: `{connectionString}`"); + +await using var client = new EventStoreClient(EventStoreClientSettings.Create(connectionString)); + +var eventData = new EventData( + Uuid.NewUuid(), + "some-event", + "{\"id\": \"1\" \"value\": \"some value\"}"u8.ToArray() +); + +try { + var appendResult = await client.AppendToStreamAsync( + "some-stream", + StreamState.Any, + new List { + eventData + } + ); + + Console.WriteLine($"SUCCESS! Append result: {appendResult.LogPosition}"); +} +catch (Exception exception) { + var innerException = exception.InnerException; + if (innerException is RpcException rpcException) { + if (rpcException.Message.Contains(noNodeConnectionErrorMessage) + || rpcException.Message.Contains(connectionRefused)) { + Console.WriteLine( + $"FAILED! {noNodeConnectionErrorMessage} " + + $"Please makes sure that: EventStoreDB node is running, you're using a valid IP " + + $"address or DNS name, that port is valid and exposed (forwarded) in node config." + ); - try { - var appendResult = await client.AppendToStreamAsync( - "some-stream", - StreamState.Any, - new List { - eventData - }); - Console.WriteLine($"SUCCESS! Append result: {appendResult.LogPosition}"); - } - catch (Exception exception) - { - var innerException = exception.InnerException; + return; + } - if (innerException is RpcException rpcException) - { - if (rpcException.Message.Contains(NoNodeConnectionErrorMessage) || rpcException.Message.Contains(ConnectionRefused)) { - Console.WriteLine( - $"FAILED! {NoNodeConnectionErrorMessage} Please makes sure that: EventStoreDB node is running, you're using a valid IP address or DNS name, that port is valid and exposed (forwarded) in node config."); - return; - } + if (rpcException.Message.Contains(certificateIsNotInstalledOrInvalidErrorMessage)) { + Console.WriteLine( + $"FAILED! {certificateIsNotInstalledOrInvalidErrorMessage} " + + $"Please makes sure that you installed CA certificate on client environment " + + $"and that it was generated with IP address or DNS name used for connecting." + ); - if (rpcException.Message.Contains(CertificateIsNotInstalledOrInvalidErrorMessage)) - { - Console.WriteLine( - $"FAILED! {CertificateIsNotInstalledOrInvalidErrorMessage} Please makes sure that you installed CA certificate on client environment and that it was generated with IP address or DNS name used for connecting."); - return; - } - } - Console.WriteLine($"FAILED! {exception}"); - } + return; } } -} + + Console.WriteLine($"FAILED! {exception}"); +} \ No newline at end of file diff --git a/samples/secure-with-tls/docker-compose.yml b/samples/secure-with-tls/docker-compose.yml index 53ad888e6..7149b916d 100644 --- a/samples/secure-with-tls/docker-compose.yml +++ b/samples/secure-with-tls/docker-compose.yml @@ -28,8 +28,8 @@ services: - EVENTSTORE_CERTIFICATE_PRIVATE_KEY_FILE=/etc/eventstore/certs/node/node.key - EVENTSTORE_TRUSTED_ROOT_CERTIFICATES_PATH=/etc/eventstore/certs/ca ports: - - 1113:1113 - - 2113:2113 + - "1113:1113" + - "2113:2113" networks: - esdb_network volumes: diff --git a/samples/server-side-filtering/Program.cs b/samples/server-side-filtering/Program.cs index e2e2c814e..a7aeaa7ee 100644 --- a/samples/server-side-filtering/Program.cs +++ b/samples/server-side-filtering/Program.cs @@ -1,174 +1,176 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using EventStore.Client; +#pragma warning disable CS8321 // Local function is declared but never used + using EventTypeFilter = EventStore.Client.EventTypeFilter; -namespace server_side_filtering { - class Program { - static async Task Main() { - const int eventCount = 100; - var semaphore = new SemaphoreSlim(eventCount); - - await using var client = new EventStoreClient( - EventStoreClientSettings.Create("esdb://localhost:2113?tls=false") - ); - - await client.SubscribeToAllAsync(FromAll.Start, - (s, e, c) => { - Console.WriteLine($"{e.Event.EventType} @ {e.Event.Position.PreparePosition}"); - semaphore.Release(); - return Task.CompletedTask; - }, - filterOptions: new SubscriptionFilterOptions( - EventTypeFilter.Prefix("some-"), - 1, - (s, p, c) => { - Console.WriteLine($"checkpoint taken at {p.PreparePosition}"); - return Task.CompletedTask; - }) - ); - - await Task.Delay(2000); - - for (var i = 0; i < eventCount; i++) { - var eventData = new EventData( - Uuid.NewUuid(), - i % 2 == 0 ? "some-event" : "other-event", - Encoding.UTF8.GetBytes("{\"id\": \"1\" \"value\": \"some value\"}") - ); - - await client.AppendToStreamAsync( - Guid.NewGuid().ToString("N"), - StreamRevision.None, - new List {eventData} - ); - } - - await semaphore.WaitAsync(); +const int eventCount = 100; + +var semaphore = new SemaphoreSlim(eventCount); + +await using var client = new EventStoreClient(EventStoreClientSettings.Create("esdb://localhost:2113?tls=false")); + +await client.SubscribeToAllAsync( + FromAll.Start, + (s, e, c) => { + Console.WriteLine($"{e.Event.EventType} @ {e.Event.Position.PreparePosition}"); + semaphore.Release(); + return Task.CompletedTask; + }, + filterOptions: new SubscriptionFilterOptions( + EventTypeFilter.Prefix("some-"), + 1, + (s, p, c) => { + Console.WriteLine($"checkpoint taken at {p.PreparePosition}"); + return Task.CompletedTask; } + ) +); + +await Task.Delay(2000); + +for (var i = 0; i < eventCount; i++) { + var eventData = new EventData( + Uuid.NewUuid(), + i % 2 == 0 ? "some-event" : "other-event", + Encoding.UTF8.GetBytes("{\"id\": \"1\" \"value\": \"some value\"}") + ); + + await client.AppendToStreamAsync( + Guid.NewGuid().ToString("N"), + StreamRevision.None, + new List { eventData } + ); +} - private static async Task ExcludeSystemEvents(EventStoreClient client) { - #region exclude-system - await client.SubscribeToAllAsync(FromAll.Start, - (s, e, c) => { - Console.WriteLine( - $"{e.Event.EventType} @ {e.Event.Position.PreparePosition}"); - return Task.CompletedTask; - }, - filterOptions: new SubscriptionFilterOptions( - EventTypeFilter.ExcludeSystemEvents()) - ); - #endregion exclude-system - } +await semaphore.WaitAsync(); - private static async Task EventTypePrefix(EventStoreClient client) { - #region event-type-prefix - var filter = new SubscriptionFilterOptions( - EventTypeFilter.Prefix("customer-")); - #endregion event-type-prefix - - await client.SubscribeToAllAsync(FromAll.Start, - (s, e, c) => { - Console.WriteLine( - $"{e.Event.EventType} @ {e.Event.Position.PreparePosition}"); - return Task.CompletedTask; - }, - filterOptions: filter - ); - } +return; - private static async Task EventTypeRegex(EventStoreClient client) { - #region event-type-regex - var filter = new SubscriptionFilterOptions( - EventTypeFilter.RegularExpression("^user|^company")); - #endregion event-type-regex - - await client.SubscribeToAllAsync(FromAll.Start, - (s, e, c) => { - Console.WriteLine( - $"{e.Event.EventType} @ {e.Event.Position.PreparePosition}"); - return Task.CompletedTask; - }, - filterOptions: filter - ); - } +static async Task ExcludeSystemEvents(EventStoreClient client) { + #region exclude-system - private static async Task StreamPrefix(EventStoreClient client) { - #region stream-prefix - var filter = new SubscriptionFilterOptions( - StreamFilter.Prefix("user-")); - #endregion stream-prefix - - await client.SubscribeToAllAsync(FromAll.Start, - (s, e, c) => { - Console.WriteLine( - $"{e.Event.EventType} @ {e.Event.Position.PreparePosition}"); - return Task.CompletedTask; - }, - filterOptions: filter - ); - } + await client.SubscribeToAllAsync( + FromAll.Start, + (s, e, c) => { + Console.WriteLine($"{e.Event.EventType} @ {e.Event.Position.PreparePosition}"); + return Task.CompletedTask; + }, + filterOptions: new SubscriptionFilterOptions(EventTypeFilter.ExcludeSystemEvents()) + ); - private static async Task StreamRegex(EventStoreClient client) { - #region stream-regex - var filter = new SubscriptionFilterOptions( - StreamFilter.RegularExpression("^account|^savings")); - #endregion stream-regex - - await client.SubscribeToAllAsync(FromAll.Start, - (s, e, c) => { - Console.WriteLine( - $"{e.Event.EventType} @ {e.Event.Position.PreparePosition}"); - return Task.CompletedTask; - }, - filterOptions: filter - ); - } + #endregion exclude-system +} - private static async Task CheckpointCallback(EventStoreClient client) { - #region checkpoint - var filter = new SubscriptionFilterOptions( - EventTypeFilter.ExcludeSystemEvents(), - checkpointReached: (s, p, c) => - { - Console.WriteLine($"checkpoint taken at {p.PreparePosition}"); - return Task.CompletedTask; - }); - #endregion checkpoint - - await client.SubscribeToAllAsync(FromAll.Start, - (s, e, c) => { - Console.WriteLine( - $"{e.Event.EventType} @ {e.Event.Position.PreparePosition}"); - return Task.CompletedTask; - }, - filterOptions: filter - ); - } +static async Task EventTypePrefix(EventStoreClient client) { + #region event-type-prefix + + var filter = new SubscriptionFilterOptions(EventTypeFilter.Prefix("customer-")); + + #endregion event-type-prefix + + await client.SubscribeToAllAsync( + FromAll.Start, + (s, e, c) => { + Console.WriteLine($"{e.Event.EventType} @ {e.Event.Position.PreparePosition}"); + return Task.CompletedTask; + }, + filterOptions: filter + ); +} + +static async Task EventTypeRegex(EventStoreClient client) { + #region event-type-regex + + var filter = new SubscriptionFilterOptions(EventTypeFilter.RegularExpression("^user|^company")); + + #endregion event-type-regex - private static async Task CheckpointCallbackWithInterval(EventStoreClient client) { - #region checkpoint-with-interval - var filter = new SubscriptionFilterOptions( - EventTypeFilter.ExcludeSystemEvents(), - checkpointInterval: 1000, - checkpointReached: (s, p, c) => - { - Console.WriteLine($"checkpoint taken at {p.PreparePosition}"); - return Task.CompletedTask; - }); - #endregion checkpoint-with-interval - - await client.SubscribeToAllAsync(FromAll.Start, - (s, e, c) => { - Console.WriteLine( - $"{e.Event.EventType} @ {e.Event.Position.PreparePosition}"); - return Task.CompletedTask; - }, - filterOptions: filter - ); + await client.SubscribeToAllAsync( + FromAll.Start, + (s, e, c) => { + Console.WriteLine($"{e.Event.EventType} @ {e.Event.Position.PreparePosition}"); + return Task.CompletedTask; + }, + filterOptions: filter + ); +} + +static async Task StreamPrefix(EventStoreClient client) { + #region stream-prefix + + var filter = new SubscriptionFilterOptions(StreamFilter.Prefix("user-")); + + #endregion stream-prefix + + await client.SubscribeToAllAsync( + FromAll.Start, + (s, e, c) => { + Console.WriteLine($"{e.Event.EventType} @ {e.Event.Position.PreparePosition}"); + return Task.CompletedTask; + }, + filterOptions: filter + ); +} + +static async Task StreamRegex(EventStoreClient client) { + #region stream-regex + + var filter = new SubscriptionFilterOptions(StreamFilter.RegularExpression("^account|^savings")); + + #endregion stream-regex + + await client.SubscribeToAllAsync( + FromAll.Start, + (s, e, c) => { + Console.WriteLine($"{e.Event.EventType} @ {e.Event.Position.PreparePosition}"); + return Task.CompletedTask; + }, + filterOptions: filter + ); +} + +static async Task CheckpointCallback(EventStoreClient client) { + #region checkpoint + + var filter = new SubscriptionFilterOptions( + EventTypeFilter.ExcludeSystemEvents(), + checkpointReached: (s, p, c) => { + Console.WriteLine($"checkpoint taken at {p.PreparePosition}"); + return Task.CompletedTask; } - } + ); + + #endregion checkpoint + + await client.SubscribeToAllAsync( + FromAll.Start, + (s, e, c) => { + Console.WriteLine($"{e.Event.EventType} @ {e.Event.Position.PreparePosition}"); + return Task.CompletedTask; + }, + filterOptions: filter + ); } + +static async Task CheckpointCallbackWithInterval(EventStoreClient client) { + #region checkpoint-with-interval + + var filter = new SubscriptionFilterOptions( + EventTypeFilter.ExcludeSystemEvents(), + 1000, + (s, p, c) => { + Console.WriteLine($"checkpoint taken at {p.PreparePosition}"); + return Task.CompletedTask; + } + ); + + #endregion checkpoint-with-interval + + await client.SubscribeToAllAsync( + FromAll.Start, + (s, e, c) => { + Console.WriteLine($"{e.Event.EventType} @ {e.Event.Position.PreparePosition}"); + return Task.CompletedTask; + }, + filterOptions: filter + ); +} \ No newline at end of file diff --git a/samples/setting-up-dependency-injection/Controllers/EventStoreController.cs b/samples/setting-up-dependency-injection/Controllers/EventStoreController.cs index d1ad74a8c..b9ec3e340 100644 --- a/samples/setting-up-dependency-injection/Controllers/EventStoreController.cs +++ b/samples/setting-up-dependency-injection/Controllers/EventStoreController.cs @@ -1,6 +1,4 @@ -using System.Collections.Generic; -using EventStore.Client; -using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc; namespace setting_up_dependency_injection.Controllers { [ApiController] diff --git a/samples/setting-up-dependency-injection/Program.cs b/samples/setting-up-dependency-injection/Program.cs index f1d6624d7..49b316496 100644 --- a/samples/setting-up-dependency-injection/Program.cs +++ b/samples/setting-up-dependency-injection/Program.cs @@ -1,20 +1,12 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Hosting; +namespace setting_up_dependency_injection; -namespace setting_up_dependency_injection { - public class Program { - public static async Task Main(string[] args) { - using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(1)); - await CreateHostBuilder(args).Build().WaitForShutdownAsync(cts.Token); - } - - public static IHostBuilder CreateHostBuilder(string[] args) => - Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults(webBuilder => { - webBuilder.UseStartup(); - }); +public class Program { + public static async Task Main(string[] args) { + using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(1)); + await CreateHostBuilder(args).Build().WaitForShutdownAsync(cts.Token); } -} + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(); }); +} \ No newline at end of file diff --git a/samples/setting-up-dependency-injection/Startup.cs b/samples/setting-up-dependency-injection/Startup.cs index 7e28c1d53..a1d618aff 100644 --- a/samples/setting-up-dependency-injection/Startup.cs +++ b/samples/setting-up-dependency-injection/Startup.cs @@ -1,38 +1,25 @@ -using System; -using System.Net.Http; -using EventStore.Client; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; - -namespace setting_up_dependency_injection { - public class Startup { - public Startup(IConfiguration configuration) { - Configuration = configuration; - } - - public IConfiguration Configuration { get; } - - public void ConfigureServices(IServiceCollection services) { - services.AddControllers(); - - #region setting-up-dependency - services.AddEventStoreClient("esdb://admin:changeit@localhost:2113?tls=false"); - #endregion setting-up-dependency - } - - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { - if (env.IsDevelopment()) { - app.UseDeveloperExceptionPage(); - } - - app.UseHttpsRedirection(); - app.UseRouting(); - app.UseEndpoints(endpoints => { - endpoints.MapControllers(); - }); - } +namespace setting_up_dependency_injection; + +public class Startup { + public Startup(IConfiguration configuration) => Configuration = configuration; + + public IConfiguration Configuration { get; } + + public void ConfigureServices(IServiceCollection services) { + services.AddControllers(); + + #region setting-up-dependency + + services.AddEventStoreClient("esdb://admin:changeit@localhost:2113?tls=false"); + + #endregion setting-up-dependency + } + + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { + if (env.IsDevelopment()) app.UseDeveloperExceptionPage(); + + app.UseHttpsRedirection(); + app.UseRouting(); + app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); } -} +} \ No newline at end of file diff --git a/samples/subscribing-to-streams/Program.cs b/samples/subscribing-to-streams/Program.cs index 724b1b2e5..2bc574bd8 100644 --- a/samples/subscribing-to-streams/Program.cs +++ b/samples/subscribing-to-streams/Program.cs @@ -1,162 +1,184 @@ -using System; -using System.Net.Http; -using System.Reflection.Metadata; -using System.Threading; -using System.Threading.Tasks; -using EventStore.Client; -using EventStore.Client.Streams; - -namespace subscribing_to_streams { - class Program { - static async Task Main(string[] args) { - using var client = new EventStoreClient( - EventStoreClientSettings.Create("esdb://localhost:2113?tls=false") - ); - - await SubscribeToStream(client); - await SubscribeToAll(client); - await OverridingUserCredentials(client); - } +#pragma warning disable CS8321 // Local function is declared but never used - private static async Task SubscribeToStream(EventStoreClient client) { - #region subscribe-to-stream - await client.SubscribeToStreamAsync("some-stream", - FromStream.Start, - async (subscription, evnt, cancellationToken) => { - Console.WriteLine($"Received event {evnt.OriginalEventNumber}@{evnt.OriginalStreamId}"); - await HandleEvent(evnt); - }); - #endregion subscribe-to-stream - - #region subscribe-to-stream-from-position - await client.SubscribeToStreamAsync( - "some-stream", - FromStream.After(StreamPosition.FromInt64(20)), - EventAppeared); - #endregion subscribe-to-stream-from-position - - #region subscribe-to-stream-live - await client.SubscribeToStreamAsync( - "some-stream", - FromStream.End, - EventAppeared); - #endregion subscribe-to-stream-live - - #region subscribe-to-stream-resolving-linktos - await client.SubscribeToStreamAsync( - "$et-myEventType", - FromStream.Start, - EventAppeared, - resolveLinkTos: true); - #endregion subscribe-to-stream-resolving-linktos - - #region subscribe-to-stream-subscription-dropped - - var checkpoint = await ReadStreamCheckpointAsync(); - await client.SubscribeToStreamAsync( - "some-stream", - checkpoint is null ? FromStream.Start : FromStream.After(checkpoint.Value), - eventAppeared: async (subscription, evnt, cancellationToken) => { - await HandleEvent(evnt); - checkpoint = evnt.OriginalEventNumber; - }, - subscriptionDropped: ((subscription, reason, exception) => { - Console.WriteLine($"Subscription was dropped due to {reason}. {exception}"); - if (reason != SubscriptionDroppedReason.Disposed) { - // Resubscribe if the client didn't stop the subscription - Resubscribe(checkpoint); - } - })); - #endregion subscribe-to-stream-subscription-dropped - } +// ReSharper disable UnusedParameter.Local +// ReSharper disable UnusedVariable - private static async Task SubscribeToAll(EventStoreClient client) { - #region subscribe-to-all - await client.SubscribeToAllAsync( - FromAll.Start, - async (subscription, evnt, cancellationToken) => { - Console.WriteLine($"Received event {evnt.OriginalEventNumber}@{evnt.OriginalStreamId}"); - await HandleEvent(evnt); - }); - #endregion subscribe-to-all - - #region subscribe-to-all-from-position - - var result = await client.AppendToStreamAsync("subscribe-to-all-from-position", StreamState.NoStream, new[] { - new EventData(Uuid.NewUuid(), "-", ReadOnlyMemory.Empty) - }); - - await client.SubscribeToAllAsync( - FromAll.After(result.LogPosition), - EventAppeared); - #endregion subscribe-to-all-from-position - - #region subscribe-to-all-live - await client.SubscribeToAllAsync( - FromAll.End, - EventAppeared); - #endregion subscribe-to-all-live - - #region subscribe-to-all-subscription-dropped - var checkpoint = await ReadCheckpointAsync(); - await client.SubscribeToAllAsync( - checkpoint is null ? FromAll.Start : FromAll.After(checkpoint.Value), - eventAppeared: async (subscription, evnt, cancellationToken) => { - await HandleEvent(evnt); - checkpoint = evnt.OriginalPosition!.Value; - }, - subscriptionDropped: ((subscription, reason, exception) => { - Console.WriteLine($"Subscription was dropped due to {reason}. {exception}"); - if (reason != SubscriptionDroppedReason.Disposed) { - // Resubscribe if the client didn't stop the subscription - Resubscribe(checkpoint); - } - })); - #endregion subscribe-to-all-subscription-dropped - } +await using var client = new EventStoreClient(EventStoreClientSettings.Create("esdb://localhost:2113?tls=false")); + +await SubscribeToStream(client); +await SubscribeToAll(client); +await OverridingUserCredentials(client); + +return; - private static async Task SubscribeToFiltered(EventStoreClient client) { - #region stream-prefix-filtered-subscription - var prefixStreamFilter = new SubscriptionFilterOptions(StreamFilter.Prefix("test-", "other-")); - await client.SubscribeToAllAsync( - FromAll.Start, - EventAppeared, - filterOptions: prefixStreamFilter); - #endregion stream-prefix-filtered-subscription - - #region stream-regex-filtered-subscription - var regexStreamFilter = StreamFilter.RegularExpression(@"/invoice-\d\d\d/g"); - #endregion stream-regex-filtered-subscription +static async Task SubscribeToStream(EventStoreClient client) { + #region subscribe-to-stream + + await client.SubscribeToStreamAsync( + "some-stream", + FromStream.Start, + async (subscription, evnt, cancellationToken) => { + Console.WriteLine($"Received event {evnt.OriginalEventNumber}@{evnt.OriginalStreamId}"); + await HandleEvent(evnt); } + ); + + #endregion subscribe-to-stream + + #region subscribe-to-stream-from-position + + await client.SubscribeToStreamAsync( + "some-stream", + FromStream.After(StreamPosition.FromInt64(20)), + EventAppeared + ); + + #endregion subscribe-to-stream-from-position - private static async Task OverridingUserCredentials(EventStoreClient client) { - #region overriding-user-credentials - await client.SubscribeToAllAsync( - FromAll.Start, - EventAppeared, - userCredentials: new UserCredentials("admin", "changeit")); - #endregion overriding-user-credentials + #region subscribe-to-stream-live + + await client.SubscribeToStreamAsync( + "some-stream", + FromStream.End, + EventAppeared + ); + + #endregion subscribe-to-stream-live + + #region subscribe-to-stream-resolving-linktos + + await client.SubscribeToStreamAsync( + "$et-myEventType", + FromStream.Start, + EventAppeared, + true + ); + + #endregion subscribe-to-stream-resolving-linktos + + #region subscribe-to-stream-subscription-dropped + + var checkpoint = await ReadStreamCheckpointAsync(); + await client.SubscribeToStreamAsync( + "some-stream", + checkpoint is null ? FromStream.Start : FromStream.After(checkpoint.Value), + async (subscription, evnt, cancellationToken) => { + await HandleEvent(evnt); + checkpoint = evnt.OriginalEventNumber; + }, + subscriptionDropped: (subscription, reason, exception) => { + Console.WriteLine($"Subscription was dropped due to {reason}. {exception}"); + if (reason != SubscriptionDroppedReason.Disposed) + // Resubscribe if the client didn't stop the subscription + ResubscribeToStream(checkpoint); } + ); + + #endregion subscribe-to-stream-subscription-dropped +} - private static Task EventAppeared(StreamSubscription subscription, ResolvedEvent evnt, - CancellationToken cancellationToken) { - return Task.CompletedTask; +static async Task SubscribeToAll(EventStoreClient client) { + #region subscribe-to-all + + await client.SubscribeToAllAsync( + FromAll.Start, + async (subscription, evnt, cancellationToken) => { + Console.WriteLine($"Received event {evnt.OriginalEventNumber}@{evnt.OriginalStreamId}"); + await HandleEvent(evnt); } + ); + + #endregion subscribe-to-all + + #region subscribe-to-all-from-position - private static void SubscriptionDropped(StreamSubscription subscription, SubscriptionDroppedReason reason, - Exception ex) { + var result = await client.AppendToStreamAsync( + "subscribe-to-all-from-position", + StreamState.NoStream, + new[] { + new EventData(Uuid.NewUuid(), "-", ReadOnlyMemory.Empty) } - private static Task HandleEvent(ResolvedEvent evnt) { - return Task.CompletedTask; + ); + + await client.SubscribeToAllAsync( + FromAll.After(result.LogPosition), + EventAppeared + ); + + #endregion subscribe-to-all-from-position + + #region subscribe-to-all-live + + await client.SubscribeToAllAsync( + FromAll.End, + EventAppeared + ); + + #endregion subscribe-to-all-live + + #region subscribe-to-all-subscription-dropped + + var checkpoint = await ReadCheckpointAsync(); + await client.SubscribeToAllAsync( + checkpoint is null ? FromAll.Start : FromAll.After(checkpoint.Value), + async (subscription, evnt, cancellationToken) => { + await HandleEvent(evnt); + checkpoint = evnt.OriginalPosition!.Value; + }, + subscriptionDropped: (subscription, reason, exception) => { + Console.WriteLine($"Subscription was dropped due to {reason}. {exception}"); + if (reason != SubscriptionDroppedReason.Disposed) + // Resubscribe if the client didn't stop the subscription + Resubscribe(checkpoint); } + ); + + #endregion subscribe-to-all-subscription-dropped +} + +static async Task SubscribeToFiltered(EventStoreClient client) { + #region stream-prefix-filtered-subscription + + var prefixStreamFilter = new SubscriptionFilterOptions(StreamFilter.Prefix("test-", "other-")); + await client.SubscribeToAllAsync( + FromAll.Start, + EventAppeared, + filterOptions: prefixStreamFilter + ); + + #endregion stream-prefix-filtered-subscription + + #region stream-regex-filtered-subscription - private static void Resubscribe(StreamPosition? checkpoint) { } - private static void Resubscribe(Position? checkpoint) { } + var regexStreamFilter = StreamFilter.RegularExpression(@"/invoice-\d\d\d/g"); - private static Task ReadStreamCheckpointAsync() => - Task.FromResult(new StreamPosition?()); + #endregion stream-regex-filtered-subscription +} + +static async Task OverridingUserCredentials(EventStoreClient client) { + #region overriding-user-credentials + + await client.SubscribeToAllAsync( + FromAll.Start, + EventAppeared, + userCredentials: new UserCredentials("admin", "changeit") + ); - private static Task ReadCheckpointAsync() => - Task.FromResult(new Position?()); - } + #endregion overriding-user-credentials } + +static Task EventAppeared(StreamSubscription subscription, ResolvedEvent evnt, CancellationToken cancellationToken) => + Task.CompletedTask; + +static void SubscriptionDropped(StreamSubscription subscription, SubscriptionDroppedReason reason, Exception ex) { } + +static Task HandleEvent(ResolvedEvent evnt) => Task.CompletedTask; + +static void ResubscribeToStream(StreamPosition? checkpoint) { } +static void Resubscribe(Position? checkpoint) { } + +static Task ReadStreamCheckpointAsync() => + Task.FromResult(new StreamPosition?()); + +static Task ReadCheckpointAsync() => + Task.FromResult(new Position?()); \ No newline at end of file diff --git a/test/Directory.Build.props b/test/Directory.Build.props index 213f077ff..0bde796bc 100644 --- a/test/Directory.Build.props +++ b/test/Directory.Build.props @@ -9,11 +9,11 @@ - + - + - + all runtime; build; native; contentfiles; analyzers 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 7df9db71a..60b447bb4 100644 --- a/test/EventStore.Client.Tests.Common/EventStore.Client.Tests.Common.csproj +++ b/test/EventStore.Client.Tests.Common/EventStore.Client.Tests.Common.csproj @@ -16,20 +16,21 @@ + - + - + - - + + - - + + - + diff --git a/test/EventStore.Client.Tests/EventStore.Client.Tests.csproj b/test/EventStore.Client.Tests/EventStore.Client.Tests.csproj index 05e3f6663..44a934d3b 100644 --- a/test/EventStore.Client.Tests/EventStore.Client.Tests.csproj +++ b/test/EventStore.Client.Tests/EventStore.Client.Tests.csproj @@ -6,15 +6,15 @@ - - - - + + + + From 619fc02b249d923edb4029e9b9059ce4a79cc77f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Silveira?= Date: Wed, 29 Nov 2023 17:20:28 +0100 Subject: [PATCH 02/22] samples: fixed secure-with-tls samples: upgraded esdb nuget packages --- samples/.dockerignore | 25 ----------- samples/Directory.Build.props | 2 +- .../appending-events/appending-events.csproj | 2 +- .../connecting-to-a-cluster.csproj | 2 +- .../connecting-to-a-single-node.csproj | 2 +- samples/quick-start/docker-compose.yml | 4 +- samples/quick-start/quick-start.csproj | 2 +- samples/reading-events/reading-events.csproj | 2 +- samples/secure-with-tls/Dockerfile | 42 +++++++++++++++++-- samples/secure-with-tls/Program.cs | 4 +- samples/secure-with-tls/docker-compose.yml | 2 +- .../secure-with-tls/secure-with-tls.csproj | 16 ++++++- .../server-side-filtering.csproj | 2 +- .../Controllers/EventStoreController.cs | 1 - .../setting-up-dependency-injection.csproj | 2 +- .../subscribing-to-streams.csproj | 2 +- 16 files changed, 68 insertions(+), 44 deletions(-) delete mode 100644 samples/.dockerignore diff --git a/samples/.dockerignore b/samples/.dockerignore deleted file mode 100644 index cd967fc3a..000000000 --- a/samples/.dockerignore +++ /dev/null @@ -1,25 +0,0 @@ -**/.dockerignore -**/.env -**/.git -**/.gitignore -**/.project -**/.settings -**/.toolstarget -**/.vs -**/.vscode -**/.idea -**/*.*proj.user -**/*.dbmdl -**/*.jfm -**/azds.yaml -**/bin -**/charts -**/docker-compose* -**/Dockerfile* -**/node_modules -**/npm-debug.log -**/obj -**/secrets.dev.yaml -**/values.dev.yaml -LICENSE -README.md \ No newline at end of file diff --git a/samples/Directory.Build.props b/samples/Directory.Build.props index 7c4e1140e..54497a508 100644 --- a/samples/Directory.Build.props +++ b/samples/Directory.Build.props @@ -1,6 +1,6 @@ - net6.0;net7.0;net8.0 + net8.0 enable enable true diff --git a/samples/appending-events/appending-events.csproj b/samples/appending-events/appending-events.csproj index 34b8399e9..fb93d800e 100644 --- a/samples/appending-events/appending-events.csproj +++ b/samples/appending-events/appending-events.csproj @@ -6,7 +6,7 @@ - + diff --git a/samples/connecting-to-a-cluster/connecting-to-a-cluster.csproj b/samples/connecting-to-a-cluster/connecting-to-a-cluster.csproj index 1d8ff5b7d..4754bd0e2 100644 --- a/samples/connecting-to-a-cluster/connecting-to-a-cluster.csproj +++ b/samples/connecting-to-a-cluster/connecting-to-a-cluster.csproj @@ -6,7 +6,7 @@ - + diff --git a/samples/connecting-to-a-single-node/connecting-to-a-single-node.csproj b/samples/connecting-to-a-single-node/connecting-to-a-single-node.csproj index 337b66b85..4ef794ee4 100644 --- a/samples/connecting-to-a-single-node/connecting-to-a-single-node.csproj +++ b/samples/connecting-to-a-single-node/connecting-to-a-single-node.csproj @@ -5,7 +5,7 @@ - + diff --git a/samples/quick-start/docker-compose.yml b/samples/quick-start/docker-compose.yml index 2a96c51a8..9fc63ec33 100644 --- a/samples/quick-start/docker-compose.yml +++ b/samples/quick-start/docker-compose.yml @@ -1,9 +1,9 @@ version: '3' services: eventstore: - image: eventstore/eventstore:20.10.0-buster-slim + image: eventstore/eventstore:latest environment: - EVENTSTORE_INSECURE=true - EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP=true ports: - - "2113:2113" + - "2113:2113" \ No newline at end of file diff --git a/samples/quick-start/quick-start.csproj b/samples/quick-start/quick-start.csproj index 9921046d6..b33948026 100644 --- a/samples/quick-start/quick-start.csproj +++ b/samples/quick-start/quick-start.csproj @@ -5,7 +5,7 @@ - + diff --git a/samples/reading-events/reading-events.csproj b/samples/reading-events/reading-events.csproj index 0ae95a9a5..436254ea7 100644 --- a/samples/reading-events/reading-events.csproj +++ b/samples/reading-events/reading-events.csproj @@ -5,7 +5,7 @@ - + \ No newline at end of file diff --git a/samples/secure-with-tls/Dockerfile b/samples/secure-with-tls/Dockerfile index 5dc195f0d..6bc78c753 100644 --- a/samples/secure-with-tls/Dockerfile +++ b/samples/secure-with-tls/Dockerfile @@ -1,5 +1,5 @@ # BUILDER -FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim AS builder +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS builder WORKDIR /app @@ -18,10 +18,10 @@ COPY ./Program.cs ./ RUN dotnet build -c Release --no-restore ./secure-with-tls.csproj # Package -RUN dotnet publish -c Release --no-build -o ./out ./secure-with-tls.csproj +RUN dotnet publish -c Release --no-build -o ./out ./secure-with-tls.csproj /p:UseAppHost=false # HOST -FROM mcr.microsoft.com/dotnet/runtime:5.0-buster-slim +FROM mcr.microsoft.com/dotnet/runtime:8.0 WORKDIR /app @@ -35,3 +35,39 @@ RUN chmod 644 /usr/local/share/ca-certificates/eventstoredb_ca.crt && update-ca- # Run ENTRYPOINT ["dotnet", "secure-with-tls.dll"] + +# +#FROM mcr.microsoft.com/dotnet/runtime:8.0 AS base +#USER $APP_UID +#WORKDIR /app +# +#FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +#ARG BUILD_CONFIGURATION=Release +#WORKDIR /src +#COPY ["secure-with-tls/secure-with-tls.csproj", "secure-with-tls/"] +# +## we need comment out project reference and uncomment the package reference +## If you're using the package reference those lines are not needed +#RUN sed -i 's///' secure-with-tls.csproj && \ +# sed -i 's//secure_with_tls + + net8.0 + enable + enable + true + Exe + preview + + + + + + + - + \ No newline at end of file diff --git a/samples/server-side-filtering/server-side-filtering.csproj b/samples/server-side-filtering/server-side-filtering.csproj index 34b2d4c39..7b80aba18 100644 --- a/samples/server-side-filtering/server-side-filtering.csproj +++ b/samples/server-side-filtering/server-side-filtering.csproj @@ -6,7 +6,7 @@ - + diff --git a/samples/setting-up-dependency-injection/Controllers/EventStoreController.cs b/samples/setting-up-dependency-injection/Controllers/EventStoreController.cs index b9ec3e340..d4c3f4d59 100644 --- a/samples/setting-up-dependency-injection/Controllers/EventStoreController.cs +++ b/samples/setting-up-dependency-injection/Controllers/EventStoreController.cs @@ -4,7 +4,6 @@ namespace setting_up_dependency_injection.Controllers { [ApiController] [Route("[controller]")] public class EventStoreController : ControllerBase { - #region using-dependency private readonly EventStoreClient _eventStoreClient; diff --git a/samples/setting-up-dependency-injection/setting-up-dependency-injection.csproj b/samples/setting-up-dependency-injection/setting-up-dependency-injection.csproj index 7f3b511bd..0e2adfd05 100644 --- a/samples/setting-up-dependency-injection/setting-up-dependency-injection.csproj +++ b/samples/setting-up-dependency-injection/setting-up-dependency-injection.csproj @@ -5,7 +5,7 @@ - + diff --git a/samples/subscribing-to-streams/subscribing-to-streams.csproj b/samples/subscribing-to-streams/subscribing-to-streams.csproj index d67c0a569..397f07197 100644 --- a/samples/subscribing-to-streams/subscribing-to-streams.csproj +++ b/samples/subscribing-to-streams/subscribing-to-streams.csproj @@ -5,7 +5,7 @@ - + From 52202781d760bab2c17795d5c39b802252eef752 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Silveira?= Date: Fri, 1 Dec 2023 19:07:38 +0100 Subject: [PATCH 03/22] refactored and fixed secure-with-tls sample --- samples/quick-start/docker-compose.yml | 1 - samples/secure-with-tls/.dockerignore | 29 ++++- samples/secure-with-tls/Dockerfile | 119 +++++++++--------- samples/secure-with-tls/Program.cs | 31 ++--- samples/secure-with-tls/README.md | 45 +++---- samples/secure-with-tls/create-certs.ps1 | 2 +- samples/secure-with-tls/create-certs.sh | 31 ++++- .../secure-with-tls/docker-compose.app.yml | 19 +++ .../secure-with-tls/docker-compose.certs.yml | 30 +++++ .../docker-compose.generate-certs.yml | 14 --- samples/secure-with-tls/docker-compose.yml | 72 +++++------ samples/secure-with-tls/run-app.sh | 7 ++ .../secure-with-tls/secure-with-tls.csproj | 14 +-- 13 files changed, 245 insertions(+), 169 deletions(-) mode change 100644 => 100755 samples/secure-with-tls/create-certs.sh create mode 100644 samples/secure-with-tls/docker-compose.app.yml create mode 100644 samples/secure-with-tls/docker-compose.certs.yml delete mode 100644 samples/secure-with-tls/docker-compose.generate-certs.yml create mode 100755 samples/secure-with-tls/run-app.sh diff --git a/samples/quick-start/docker-compose.yml b/samples/quick-start/docker-compose.yml index 9fc63ec33..003ef97d4 100644 --- a/samples/quick-start/docker-compose.yml +++ b/samples/quick-start/docker-compose.yml @@ -4,6 +4,5 @@ services: image: eventstore/eventstore:latest environment: - EVENTSTORE_INSECURE=true - - EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP=true ports: - "2113:2113" \ No newline at end of file diff --git a/samples/secure-with-tls/.dockerignore b/samples/secure-with-tls/.dockerignore index cf69769bd..cd967fc3a 100644 --- a/samples/secure-with-tls/.dockerignore +++ b/samples/secure-with-tls/.dockerignore @@ -1,4 +1,25 @@ -**/bin/ -**/obj/ -**/out/ -**/TestResults/ \ No newline at end of file +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/.idea +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md \ No newline at end of file diff --git a/samples/secure-with-tls/Dockerfile b/samples/secure-with-tls/Dockerfile index 6bc78c753..6e454b881 100644 --- a/samples/secure-with-tls/Dockerfile +++ b/samples/secure-with-tls/Dockerfile @@ -1,73 +1,72 @@ -# BUILDER -FROM mcr.microsoft.com/dotnet/sdk:8.0 AS builder +ARG BUILDER_IMG=mcr.microsoft.com/dotnet/sdk:8.0-jammy +ARG RUNNER_IMG=mcr.microsoft.com/dotnet/runtime:8.0.0-jammy +ARG APP_NAME="secure-with-tls" +ARG BUILD_CONFIGURATION=Release +#--------------------------------------------- +# Prepare runtime image +#--------------------------------------------- +FROM $RUNNER_IMG AS run +ARG APP_NAME + +# copy pregenerated certificates into usr local CA location +COPY ./certs/ca/ca.crt /usr/local/share/ca-certificates/eventstoredb_ca.crt + +# set permissions +RUN chmod 644 /usr/local/share/ca-certificates/eventstoredb_ca.crt + +# install certificates +RUN update-ca-certificates + +# configure entrypoint WORKDIR /app +ENV ENTRYPOINT "dotnet ${APP_NAME}.dll" +ENTRYPOINT $ENTRYPOINT -# Copy csproj and restore -COPY ./secure-with-tls.csproj ./ +#--------------------------------------------- +# Build application +#--------------------------------------------- +FROM $BUILDER_IMG AS build +ARG APP_NAME +ARG BUILD_CONFIGURATION + +WORKDIR /src + +# copy project file +COPY ${APP_NAME}.csproj /src/${APP_NAME}/ + +# helper var +ENV PROJECT_FILE_PATH=$APP_NAME/$APP_NAME.csproj # we need comment out project reference and uncomment the package reference -# If you're using the package reference those lines are not needed -RUN sed -i 's///' secure-with-tls.csproj && \ - sed -i 's////' $PROJECT_FILE_PATH && \ + sed -i 's////' secure-with-tls.csproj && \ -# sed -i 's// { - eventData - } + "some-stream", StreamState.Any, new List { eventData } ); Console.WriteLine($"SUCCESS! Append result: {appendResult.LogPosition}"); } catch (Exception exception) { - var innerException = exception.InnerException; + const string noNodeConnectionErrorMessage = "No connection could be made because the target machine actively refused it."; + const string connectionRefused = "Connection refused"; + const string certificateIsNotInstalledOrInvalidErrorMessage = "The remote certificate is invalid according to the validation procedure."; + var innerException = exception.InnerException; + if (innerException is RpcException rpcException) { if (rpcException.Message.Contains(noNodeConnectionErrorMessage) || rpcException.Message.Contains(connectionRefused)) { diff --git a/samples/secure-with-tls/README.md b/samples/secure-with-tls/README.md index 01f7f96d4..6458d2b30 100644 --- a/samples/secure-with-tls/README.md +++ b/samples/secure-with-tls/README.md @@ -56,7 +56,7 @@ services: command: > -c "es-gencert-cli create-ca -out /tmp/certs/ca && es-gencert-cli create-node -ca-certificate /tmp/certs/ca/ca.crt -ca-key /tmp/certs/ca/ca.key -out \ - /tmp/certs/node -ip-addresses 127.0.0.1 -dns-names localhost,eventstoredb" + /tmp/certs/node -ip-addresses 127.0.0.1 -dns-names localhost,eventstore" user: "1000:1000" volumes: - "./certs:/tmp/certs" @@ -67,17 +67,18 @@ And run `docker-compose up` to generate certificates. See instruction how to install certificates [below](#3-run-run-samples-locally-without-docker). You can find helpers scripts that are also installing created CA on local machine: -- Linux (Debian based) - [create-certs.sh](./create-certs.sh), +- Linux (Debian based, MacOS and WSL) - [create-certs.sh](./create-certs.sh), - Windows - [create-certs.ps1](./create-certs.ps1) ## Description -The sample shows how to connect with the gRPC client and append new event. You can run it locally or through docker configuration. +The sample shows how to connect with the client and append new event. You can run it locally or through docker configuration. Suggested order of reading: - whole code is located in [Program.cs](./Program.cs) file - [Dockerfile](./Dockerfile) for building sample image -- [Docker compose config](./docker-compose.yml) that has configuration for both sample client app and EventStoreDB node. +- [Docker compose config](./docker-compose.yml) that has configuration for the EventStoreDB node. +- [Docker compose app config](./docker-compose.app.yml) that has configuration for the sample client app. ## Running Sample @@ -91,43 +92,43 @@ Use following command to generate certificates: ```powershell .\create-certs.ps1 ``` + _Note: to regenerate certificates you need to remove the [./certs](./certs) folder._ ### 2. Run samples with Docker -Use the following command to run samples with Docker: -```consoler -docker-compose up +The following command will automatically generate certificates in the certs folder, and run both server and client with preconfigured TLS connection setup. + +```console +docker-compose -f docker-compose.yml -f docker-compose.app.yml up ``` -It will run both server and client with preconfigured TLS connection setup. ### 3. Run samples locally (without Docker) To run samples locally, you need to install the generated CA certificate. -#### 3.1 Install certificate - Linux (Ubuntu, Debian) -- Copy [./certs/ca/ca.crt](./certs/ca/ca.crt) to dir `/usr/local/share/ca-certificates/` -- Use command: +#### 3.1 Generate and install the CA certificate +The certificate will be automatically generated and installed if you just run the using the following command: + +- Linux (Ubuntu, Debian, WSL) or MacOS ```console - sudo cp foo.crt /usr/local/share/ca-certificates/foo.crt + create-certs.sh ``` -- Update the CA store: + +- Windows ```console - sudo update-ca-certificates + create-certs.ps1 ``` -#### 3.2 Install certificate - Windows -Windows certificate will be automatically installed when [./create-certs.ps1](./create-certs.ps1) was run. - -#### 3.3. Run EventStoreDB node + +#### 3.4 Run EventStoreDB Use the following command to run EventStoreDB ```console -docker-compose up eventstoredb +docker-compose up ``` -#### 3.3 Run client application -Run application from console: +#### 3.5 Run client application +Run application from your favourite IDE or the console: ```console dotnet run ./secure-with-tls.csproj ``` -or from your favourite IDE. diff --git a/samples/secure-with-tls/create-certs.ps1 b/samples/secure-with-tls/create-certs.ps1 index b53185cda..34fabb178 100644 --- a/samples/secure-with-tls/create-certs.ps1 +++ b/samples/secure-with-tls/create-certs.ps1 @@ -1,5 +1,5 @@ New-Item -ItemType Directory -Force -Path certs -docker-compose -f docker-compose.generate-certs.yml up +docker-compose -f docker-compose.certs.yml up --remove-orphans Import-Certificate -FilePath ".\certs\ca\ca.crt" -CertStoreLocation Cert:\CurrentUser\Root diff --git a/samples/secure-with-tls/create-certs.sh b/samples/secure-with-tls/create-certs.sh old mode 100644 new mode 100755 index 2fc0777b2..e51e2a296 --- a/samples/secure-with-tls/create-certs.sh +++ b/samples/secure-with-tls/create-certs.sh @@ -1,2 +1,31 @@ +unameOutput="$(uname -sr)" +case "${unameOutput}" in + Linux*Microsoft*) machine=WSL;; + Linux*) machine=Linux;; + Darwin*) machine=MacOS;; + *) machine="${unameOutput}" +esac + +echo ">> Generating certificate..." mkdir -p certs -docker-compose -f docker-compose.generate-certs.yml up +docker-compose -f docker-compose.certs.yml up --remove-orphans + +echo ">> Copying certificate..." +cp certs/ca/ca.crt /usr/local/share/ca-certificates/eventstore_ca.crt +#rsync --progress certs/ca/ca.crt /usr/local/share/ca-certificates/eventstore_ca.crt + +echo ">> Updating certificate permissions..." +#chmod 644 /usr/local/share/ca-certificates/eventstore_ca.crt + +if [ "${machine}" == "MacOS" ]; then + echo ">> Installing certificate on ${machine}..." + sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain /usr/local/share/ca-certificates/eventstore_ca.crt +elif [ "$(machine)" == "Linux" ]; then + echo ">> Installing certificate on ${machine}..." + sudo update-ca-certificates +elif [ "$(machine)" == "WSL" ]; then + echo ">> Installing certificate on ${machine}..." + sudo update-ca-certificates +else + echo ">> Unknown platform. Please install the certificate manually." +fi \ No newline at end of file diff --git a/samples/secure-with-tls/docker-compose.app.yml b/samples/secure-with-tls/docker-compose.app.yml new file mode 100644 index 000000000..34fbfa433 --- /dev/null +++ b/samples/secure-with-tls/docker-compose.app.yml @@ -0,0 +1,19 @@ +version: "3.5" + +networks: + default: + name: eventstore-network + +services: + + app: + container_name: app + build: ./ + environment: + # URL should match the DNS name in certificate and container name + - ESDB__CONNECTION__STRING=esdb://admin:changeit@eventstore:2113?Tls=true + depends_on: + eventstore: + condition: service_healthy + links: + - eventstore diff --git a/samples/secure-with-tls/docker-compose.certs.yml b/samples/secure-with-tls/docker-compose.certs.yml new file mode 100644 index 000000000..56c6278dc --- /dev/null +++ b/samples/secure-with-tls/docker-compose.certs.yml @@ -0,0 +1,30 @@ +version: "3.5" + +networks: + default: + name: eventstore-network + +services: + + volumes-provisioner: + image: hasnat/volumes-provisioner + container_name: volumes-provisioner + environment: + PROVISION_DIRECTORIES: "1000:1000:0755:/tmp/certs" + volumes: + - "./certs:/tmp/certs" + network_mode: none + + cert-gen: + image: eventstore/es-gencert-cli:1.0.2 + container_name: cert-gen + user: "1000:1000" + entrypoint: [ "/bin/sh","-c" ] + command: + - | + es-gencert-cli create-ca -out /tmp/certs/ca + es-gencert-cli create-node -ca-certificate /tmp/certs/ca/ca.crt -ca-key /tmp/certs/ca/ca.key -out /tmp/certs/node -ip-addresses 127.0.0.1 -dns-names localhost,eventstore + volumes: + - "./certs:/tmp/certs" + depends_on: + - volumes-provisioner diff --git a/samples/secure-with-tls/docker-compose.generate-certs.yml b/samples/secure-with-tls/docker-compose.generate-certs.yml deleted file mode 100644 index ec62ab85a..000000000 --- a/samples/secure-with-tls/docker-compose.generate-certs.yml +++ /dev/null @@ -1,14 +0,0 @@ -version: "3.5" - -services: - cert-gen: - image: eventstore/es-gencert-cli:1.0.2 - entrypoint: bash - # dns-name in this case `eventstoredb` matches EventStoreDB container_name and URL it's accessed at `docker-compose.yml` - command: > - -c "es-gencert-cli create-ca -out /tmp/certs/ca && - es-gencert-cli create-node -ca-certificate /tmp/certs/ca/ca.crt -ca-key /tmp/certs/ca/ca.key -out \ - /tmp/certs/node -ip-addresses 127.0.0.1 -dns-names localhost,eventstoredb" - user: "1000:1000" - volumes: - - "./certs:/tmp/certs" diff --git a/samples/secure-with-tls/docker-compose.yml b/samples/secure-with-tls/docker-compose.yml index 5a3eae599..61336df7a 100644 --- a/samples/secure-with-tls/docker-compose.yml +++ b/samples/secure-with-tls/docker-compose.yml @@ -1,43 +1,37 @@ version: "3.5" -services: - grpc.client: - build: ./ - environment: - # URL should match the DNS name in certificate and container name - - ESDB_CONNECTION_STRING=esdb://eventstoredb:2113?Tls=true - networks: - - esdb_network - depends_on: - eventstoredb: - condition: service_healthy +networks: + default: + name: eventstore-network - eventstoredb: - image: eventstore/eventstore:latest - # container_name should match the DNS name in certificate - container_name: eventstoredb - environment: - - EVENTSTORE_CLUSTER_SIZE=1 - - EVENTSTORE_RUN_PROJECTIONS=All - - EVENTSTORE_ENABLE_EXTERNAL_TCP=true - - EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP=true - - EVENTSTORE_EXT_TCP_PORT=1113 - - EVENTSTORE_EXT_HTTP_PORT=2113 - # set certificates location - - 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 - ports: - - "1113:1113" - - "2113:2113" - networks: - - esdb_network - volumes: - # define volume that will copy pregenerated certificates - - ./certs:/etc/eventstore/certs - restart: unless-stopped +services: + + eventstore: + image: eventstore/eventstore:latest + container_name: eventstore + environment: + - EVENTSTORE_MEM_DB=true + - EVENTSTORE_HTTP_PORT=2113 + - EVENTSTORE_LOG_LEVEL=Information + - EVENTSTORE_RUN_PROJECTIONS=None + - EVENTSTORE_START_STANDARD_PROJECTIONS=true + + # set certificates location + - 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 + ports: + - "2113:2113" + volumes: + - ./certs:/etc/eventstore/certs + - type: volume + source: eventstore-volume-data1 + target: /var/lib/eventstore + - type: volume + source: eventstore-volume-logs1 + target: /var/log/eventstore + restart: unless-stopped -networks: - esdb_network: - name: eventstoredb.local - driver: bridge +volumes: + eventstore-volume-data1: + eventstore-volume-logs1: diff --git a/samples/secure-with-tls/run-app.sh b/samples/secure-with-tls/run-app.sh new file mode 100755 index 000000000..4bf5f1e27 --- /dev/null +++ b/samples/secure-with-tls/run-app.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +echo "Going down..." +docker-compose -f docker-compose.yml -f docker-compose.app.yml down + +echo "Going up..." +docker-compose -f docker-compose.yml -f docker-compose.app.yml up --remove-orphans diff --git a/samples/secure-with-tls/secure-with-tls.csproj b/samples/secure-with-tls/secure-with-tls.csproj index b4f46b4fc..2af29c992 100644 --- a/samples/secure-with-tls/secure-with-tls.csproj +++ b/samples/secure-with-tls/secure-with-tls.csproj @@ -1,15 +1,12 @@ - - secure_with_tls - + Exe net8.0 + secure_with_tls + enable enable - enable - true - Exe - preview + Linux @@ -22,4 +19,5 @@ - \ No newline at end of file + + From cb558bd4e1b8e6b46e475b895e63a4e018fe2e44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Silveira?= Date: Fri, 1 Dec 2023 19:31:43 +0100 Subject: [PATCH 04/22] some fixes on the readme --- samples/appending-events/Program.cs | 12 ++--- samples/secure-with-tls/README.md | 66 +++++++---------------- samples/server-side-filtering/Program.cs | 2 +- samples/subscribing-to-streams/Program.cs | 3 +- 4 files changed, 28 insertions(+), 55 deletions(-) diff --git a/samples/appending-events/Program.cs b/samples/appending-events/Program.cs index 72ba2a1ec..2e1bb758f 100644 --- a/samples/appending-events/Program.cs +++ b/samples/appending-events/Program.cs @@ -19,7 +19,7 @@ static async Task AppendToStream(EventStoreClient client) { var eventData = new EventData( Uuid.NewUuid(), "some-event", - Encoding.UTF8.GetBytes("{\"id\": \"1\" \"value\": \"some value\"}") + "{\"id\": \"1\" \"value\": \"some value\"}"u8.ToArray() ); await client.AppendToStreamAsync( @@ -39,7 +39,7 @@ static async Task AppendWithSameId(EventStoreClient client) { var eventData = new EventData( Uuid.NewUuid(), "some-event", - Encoding.UTF8.GetBytes("{\"id\": \"1\" \"value\": \"some value\"}") + "{\"id\": \"1\" \"value\": \"some value\"}"u8.ToArray() ); await client.AppendToStreamAsync( @@ -68,13 +68,13 @@ static async Task AppendWithNoStream(EventStoreClient client) { var eventDataOne = new EventData( Uuid.NewUuid(), "some-event", - Encoding.UTF8.GetBytes("{\"id\": \"1\" \"value\": \"some value\"}") + "{\"id\": \"1\" \"value\": \"some value\"}"u8.ToArray() ); var eventDataTwo = new EventData( Uuid.NewUuid(), "some-event", - Encoding.UTF8.GetBytes("{\"id\": \"2\" \"value\": \"some other value\"}") + "{\"id\": \"2\" \"value\": \"some other value\"}"u8.ToArray() ); await client.AppendToStreamAsync( @@ -120,7 +120,7 @@ await client.AppendToStreamAsync( var clientOneData = new EventData( Uuid.NewUuid(), "some-event", - Encoding.UTF8.GetBytes("{\"id\": \"1\" \"value\": \"clientOne\"}") + "{\"id\": \"1\" \"value\": \"clientOne\"}"u8.ToArray() ); await client.AppendToStreamAsync( @@ -134,7 +134,7 @@ await client.AppendToStreamAsync( var clientTwoData = new EventData( Uuid.NewUuid(), "some-event", - Encoding.UTF8.GetBytes("{\"id\": \"2\" \"value\": \"clientTwo\"}") + "{\"id\": \"2\" \"value\": \"clientTwo\"}"u8.ToArray() ); await client.AppendToStreamAsync( diff --git a/samples/secure-with-tls/README.md b/samples/secure-with-tls/README.md index 6458d2b30..74da47d62 100644 --- a/samples/secure-with-tls/README.md +++ b/samples/secure-with-tls/README.md @@ -8,14 +8,14 @@ - [1. Generate self-signed certificates](#1-generate-self-signed-certificates) - [2. Run samples with Docker](#2-run-samples-with-docker) - [3. Run samples locally (without Docker)](#3-run-samples-locally-without-docker) - - [3.1 Install certificate - Linux (Ubuntu, Debian)](#31-install-certificate---linux-ubuntu-debian) + - [3.1 Install certificate - Linux (Ubuntu, Debian, WSL) or MacOS](#31-install-certificate---linux-ubuntu-debian) - [3.2 Install certificate - Windows](#32-install-certificate---windows) - - [3.3. Run EventStoreDB node](#33-run-eventstoredb-node) + - [3.3 Run EventStoreDB node](#33-run-eventstoredb-node) - [3.3 Run client application](#33-run-client-application) ## Overview -The sample shows how to run the .NET gRPC client secured by TLS certificates. +The sample shows how to run the .NET client secured by TLS certificates. Read more in the docs: - [Security](https://developers.eventstore.com/server/v20/server/security/) @@ -23,7 +23,9 @@ Read more in the docs: - [Event Store Certificate Generation CLI](https://github.com/EventStore/es-gencert-cli) It is essential for production use to configure EventStoreDB security features to prevent unauthorised access to your data. -EventStoreDB supports gRPC with TLS and SSL. Each protocol has its security configuration, but you can only use one set of certificates for TLS and HTTPS. +EventStoreDB supports gRPC with TLS and SSL. + +Each protocol has its security configuration, but you can only use one set of certificates for TLS and HTTPS. ### Certificates @@ -44,25 +46,7 @@ While generating the certificate, you need to remember to pass: - DNS names to `-dns-names`: e.g. `localhost,eventstoredb` that will match the URLs that you will be accessing EventStoreDB nodes. -[Certificate Generation CLI](https://github.com/EventStore/es-gencert-cli) is also available as the Docker image. You can define [docker-compose configuration](./docker-compose.generate-certs.yml) as e.g.: - -```yaml -version: "3.5" - -services: - cert-gen: - image: eventstore/es-gencert-cli:1.0.2 - entrypoint: bash - command: > - -c "es-gencert-cli create-ca -out /tmp/certs/ca && - es-gencert-cli create-node -ca-certificate /tmp/certs/ca/ca.crt -ca-key /tmp/certs/ca/ca.key -out \ - /tmp/certs/node -ip-addresses 127.0.0.1 -dns-names localhost,eventstore" - user: "1000:1000" - volumes: - - "./certs:/tmp/certs" -``` - -And run `docker-compose up` to generate certificates. +The [Certificate Generation CLI](https://github.com/EventStore/es-gencert-cli) is also available as the Docker image. Check the [docker-compose.certs.yml](./docker-compose.certs.yml) See instruction how to install certificates [below](#3-run-run-samples-locally-without-docker). @@ -75,15 +59,16 @@ You can find helpers scripts that are also installing created CA on local machin The sample shows how to connect with the client and append new event. You can run it locally or through docker configuration. Suggested order of reading: -- whole code is located in [Program.cs](./Program.cs) file -- [Dockerfile](./Dockerfile) for building sample image -- [Docker compose config](./docker-compose.yml) that has configuration for the EventStoreDB node. -- [Docker compose app config](./docker-compose.app.yml) that has configuration for the sample client app. +- The full code is located in [Program.cs](./Program.cs) file +- [Dockerfile](./Dockerfile) - for building the sample image +- [docker-compose.yml](./docker-compose.yml) - for running a single EventStoreDB node. +- [docker-compose.app.yml](./docker-compose.app.yml) - for running the sample client app. +- [docker-compose.certs.yml](./docker-compose.certs.yml) - for generating certificates. ## Running Sample ### 1. Generate self-signed certificates -Use following command to generate certificates: +Use following command to generate and install certificates: - Linux/MacOS ```console ./create-certs.sh @@ -96,38 +81,25 @@ Use following command to generate certificates: _Note: to regenerate certificates you need to remove the [./certs](./certs) folder._ ### 2. Run samples with Docker -The following command will automatically generate certificates in the certs folder, and run both server and client with preconfigured TLS connection setup. +The following command will run both server and client with preconfigured TLS connection setup. ```console docker-compose -f docker-compose.yml -f docker-compose.app.yml up ``` ### 3. Run samples locally (without Docker) -To run samples locally, you need to install the generated CA certificate. - -#### 3.1 Generate and install the CA certificate -The certificate will be automatically generated and installed if you just run the using the following command: - -- Linux (Ubuntu, Debian, WSL) or MacOS - ```console - create-certs.sh - ``` +Assuming the certificates were generated and installed. -- Windows - ```console - create-certs.ps1 - ``` - -#### 3.4 Run EventStoreDB +#### 3.1 Run EventStoreDB Use the following command to run EventStoreDB ```console -docker-compose up +docker-compose up -d ``` -#### 3.5 Run client application -Run application from your favourite IDE or the console: +#### 3.2 Run client application +Run the application from your favourite IDE or the console: ```console dotnet run ./secure-with-tls.csproj diff --git a/samples/server-side-filtering/Program.cs b/samples/server-side-filtering/Program.cs index a7aeaa7ee..243e40b60 100644 --- a/samples/server-side-filtering/Program.cs +++ b/samples/server-side-filtering/Program.cs @@ -31,7 +31,7 @@ await client.SubscribeToAllAsync( var eventData = new EventData( Uuid.NewUuid(), i % 2 == 0 ? "some-event" : "other-event", - Encoding.UTF8.GetBytes("{\"id\": \"1\" \"value\": \"some value\"}") + "{\"id\": \"1\" \"value\": \"some value\"}"u8.ToArray() ); await client.AppendToStreamAsync( diff --git a/samples/subscribing-to-streams/Program.cs b/samples/subscribing-to-streams/Program.cs index 2bc574bd8..b0a59ea22 100644 --- a/samples/subscribing-to-streams/Program.cs +++ b/samples/subscribing-to-streams/Program.cs @@ -175,7 +175,8 @@ static void SubscriptionDropped(StreamSubscription subscription, SubscriptionDro static Task HandleEvent(ResolvedEvent evnt) => Task.CompletedTask; static void ResubscribeToStream(StreamPosition? checkpoint) { } -static void Resubscribe(Position? checkpoint) { } + +static void Resubscribe(Position? checkpoint) { } static Task ReadStreamCheckpointAsync() => Task.FromResult(new StreamPosition?()); From eda32ed90aa05e84ac29881c71c8371b3053449a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Silveira?= Date: Fri, 1 Dec 2023 23:32:30 +0100 Subject: [PATCH 05/22] lowered log level removed NET5_0 and GRPC_CORE leftovers killed zombie code --- .github/workflows/publish.yml | 2 +- .../secure-with-tls/secure-with-tls.csproj | 2 - .../server-side-filtering.csproj | 2 - test/EventStore.Client.Tests.Common/.env | 17 ----- .../Fixtures/EventStoreTestNode.cs | 8 +-- .../FluentDockerServiceExtensions.cs | 9 --- .../FluentDocker/TestCompositeService.cs | 2 +- .../FluentDocker/TestContainerService.cs | 2 +- .../FluentDocker/TestService.cs | 64 ++++--------------- .../EventStore.Client.Tests.Common/Logging.cs | 4 -- .../appsettings.json | 2 +- 11 files changed, 18 insertions(+), 96 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 02f79aa37..25cdd67f6 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -49,7 +49,7 @@ jobs: image: ghcr.io/eventstore/eventstore:lts env: EVENTSTORE_INSECURE: true - EVENTSTORE_MEMDB: true + EVENTSTORE_MEM_DB: true EVENTSTORE_RUN_PROJECTIONS: all EVENTSTORE_START_STANDARD_PROJECTIONS: true ports: diff --git a/samples/secure-with-tls/secure-with-tls.csproj b/samples/secure-with-tls/secure-with-tls.csproj index 2af29c992..7dd4b7c03 100644 --- a/samples/secure-with-tls/secure-with-tls.csproj +++ b/samples/secure-with-tls/secure-with-tls.csproj @@ -1,5 +1,4 @@ - Exe net8.0 @@ -19,5 +18,4 @@ - diff --git a/samples/server-side-filtering/server-side-filtering.csproj b/samples/server-side-filtering/server-side-filtering.csproj index 7b80aba18..b69b90670 100644 --- a/samples/server-side-filtering/server-side-filtering.csproj +++ b/samples/server-side-filtering/server-side-filtering.csproj @@ -1,5 +1,4 @@ - server_side_filtering @@ -10,5 +9,4 @@ - \ No newline at end of file diff --git a/test/EventStore.Client.Tests.Common/.env b/test/EventStore.Client.Tests.Common/.env index da2b09379..bfbcbf3ab 100644 --- a/test/EventStore.Client.Tests.Common/.env +++ b/test/EventStore.Client.Tests.Common/.env @@ -1,19 +1,2 @@ ES_CERTS_CLUSTER=./certs-cluster ES_DOCKER_TAG=ci - -#EVENTSTORE_CLUSTER_SIZE=3 -#EVENTSTORE_INT_TCP_PORT=1112 -#EVENTSTORE_HTTP_PORT=2113 -#EVENTSTORE_TRUSTED_ROOT_CERTIFICATES_PATH=/etc/eventstore/certs/ca -#EVENTSTORE_DISCOVER_VIA_DNS=false -#EVENTSTORE_ENABLE_EXTERNAL_TCP=false -#EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP=true -#EVENTSTORE_STREAM_EXISTENCE_FILTER_SIZE=10000 -# -## pass through from environment -#EVENTSTORE_DB_LOG_FORMAT=V2 -#EVENTSTORE_LOG_LEVEL=Verbose -#EVENTSTORE_MAX_APPEND_SIZE -#EVENTSTORE_MEM_DB=false -#EVENTSTORE_RUN_PROJECTIONS=false -#EVENTSTORE_START_STANDARD_PROJECTIONS=false diff --git a/test/EventStore.Client.Tests.Common/Fixtures/EventStoreTestNode.cs b/test/EventStore.Client.Tests.Common/Fixtures/EventStoreTestNode.cs index eae421f55..547e9e8df 100644 --- a/test/EventStore.Client.Tests.Common/Fixtures/EventStoreTestNode.cs +++ b/test/EventStore.Client.Tests.Common/Fixtures/EventStoreTestNode.cs @@ -132,13 +132,7 @@ public async Task GetNextAvailablePort(TimeSpan delay = default) { await Task.Delay(delay); } finally { - if (socket.Connected) { -#if NET5_0 - socket.Disconnect(true); -#else - await socket.DisconnectAsync(true); -#endif - } + if (socket.Connected) await socket.DisconnectAsync(true); } } } diff --git a/test/EventStore.Client.Tests.Common/FluentDocker/FluentDockerServiceExtensions.cs b/test/EventStore.Client.Tests.Common/FluentDocker/FluentDockerServiceExtensions.cs index d5f62059d..e763edd35 100644 --- a/test/EventStore.Client.Tests.Common/FluentDocker/FluentDockerServiceExtensions.cs +++ b/test/EventStore.Client.Tests.Common/FluentDocker/FluentDockerServiceExtensions.cs @@ -30,21 +30,12 @@ public static async ValueTask WaitUntilNodesAreHealthy(this IContainerService se public static async Task WaitUntilNodesAreHealthy(this ICompositeService service, IEnumerable services, CancellationToken cancellationToken) { var nodes = service.Containers.Where(x => services.Contains(x.Name)); -#if NET5_0 - foreach (var node in nodes) await node.WaitUntilNodesAreHealthy(cancellationToken); -#else await Parallel.ForEachAsync(nodes, cancellationToken, async (node, ct) => await node.WaitUntilNodesAreHealthy(ct)); -#endif } public static async Task WaitUntilNodesAreHealthy(this ICompositeService service, string serviceNamePrefix, CancellationToken cancellationToken) { var nodes = service.Containers.Where(x => x.Name.StartsWith(serviceNamePrefix)); - -#if NET5_0 - foreach (var node in nodes) await node.WaitUntilNodesAreHealthy(cancellationToken); -#else await Parallel.ForEachAsync(nodes, cancellationToken, async (node, ct) => await node.WaitUntilNodesAreHealthy(ct)); -#endif } public static async Task WaitUntilNodesAreHealthy(this ICompositeService service, string serviceNamePrefix, TimeSpan timeout) { diff --git a/test/EventStore.Client.Tests.Common/FluentDocker/TestCompositeService.cs b/test/EventStore.Client.Tests.Common/FluentDocker/TestCompositeService.cs index 274791e0a..104827f30 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; \ No newline at end of file diff --git a/test/EventStore.Client.Tests.Common/FluentDocker/TestContainerService.cs b/test/EventStore.Client.Tests.Common/FluentDocker/TestContainerService.cs index 01ab098af..40ed937fc 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; \ No newline at end of file diff --git a/test/EventStore.Client.Tests.Common/FluentDocker/TestService.cs b/test/EventStore.Client.Tests.Common/FluentDocker/TestService.cs index 2f99c99fd..7b90a89c7 100644 --- a/test/EventStore.Client.Tests.Common/FluentDocker/TestService.cs +++ b/test/EventStore.Client.Tests.Common/FluentDocker/TestService.cs @@ -14,17 +14,6 @@ public interface ITestService : IAsyncDisposable { void ReportStatus(); } -/// -/// This prevents multiple services from starting at the same time. -/// Required to avoid failures on creating the networks the containers are attached to. -/// -sealed class TestServiceGatekeeper { - static readonly SemaphoreSlim Semaphore = new(1, 1); - - public static Task Wait() => Semaphore.WaitAsync(); - public static void Next() => Semaphore.Release(); -} - public abstract class TestService : ITestService where TService : IService where TBuilder : BaseBuilder { ILogger Logger { get; } @@ -37,44 +26,23 @@ public abstract class TestService : ITestService where TServ public virtual async Task Start() { Logger.Information("Container service starting"); - //await TestServiceGatekeeper.Wait(); + var builder = Configure(); - try { - var builder = Configure(); - - Service = builder.Build(); - - // // for some reason fluent docker does not always create the network - // // before the service is started, so we do it manually here - // if (Service is IContainerService service) { - // var cfg = service.GetConfiguration(true); - // - // Network = Fd - // .UseNetwork(cfg.Name) - // .IsInternal() - // .Build() - // .Attach(service, true); - // - // Logger.Information("Created network {Network}", Network.Name); - // } + Service = builder.Build(); - try { - Service.Start(); - Logger.Information("Container service started"); - } - catch (Exception ex) { - throw new FluentDockerException("Failed to start container service", ex); - } + try { + Service.Start(); + Logger.Information("Container service started"); + } + catch (Exception ex) { + throw new FluentDockerException("Failed to start container service", ex); + } - try { - await OnServiceStarted(); - } - catch (Exception ex) { - throw new FluentDockerException($"{nameof(OnServiceStarted)} execution error", ex); - } + try { + await OnServiceStarted(); } - finally { - //TestServiceGatekeeper.Next(); + catch (Exception ex) { + throw new FluentDockerException($"{nameof(OnServiceStarted)} execution error", ex); } } @@ -111,8 +79,6 @@ void ReportContainerStatus(IContainerService service) { var cfg = service.GetConfiguration(true); Logger.Information("Container {Name} {State} Ports: {Ports}", service.Name, service.State, cfg.Config.ExposedPorts.Keys); } - - // var docker = Fd.Hosts().Discover().FirstOrDefault(x => x.IsNative || x.Name == "default")!; } public virtual ValueTask DisposeAsync() { @@ -125,10 +91,6 @@ public virtual ValueTask DisposeAsync() { catch { // ignored } - - /*if (Service.State != ServiceRunningState.Unknown) { - Service.Dispose(); - }*/ } catch (Exception ex) { throw new FluentDockerException("Failed to dispose of container service", ex); diff --git a/test/EventStore.Client.Tests.Common/Logging.cs b/test/EventStore.Client.Tests.Common/Logging.cs index 44b2ba83b..1c37ef142 100644 --- a/test/EventStore.Client.Tests.Common/Logging.cs +++ b/test/EventStore.Client.Tests.Common/Logging.cs @@ -22,10 +22,6 @@ static Logging() { .WriteTo.Observers(x => x.Subscribe(LogEventSubject.OnNext)) .CreateLogger(); -#if GRPC_CORE - GrpcEnvironment.SetLogger(new GrpcCoreSerilogLogger(Log.Logger.ForContext())); -#endif - Ductus.FluentDocker.Services.Logging.Enabled(); AppDomain.CurrentDomain.DomainUnload += (_, _) => Log.CloseAndFlush(); diff --git a/test/EventStore.Client.Tests.Common/appsettings.json b/test/EventStore.Client.Tests.Common/appsettings.json index b8155a789..78193ee2e 100644 --- a/test/EventStore.Client.Tests.Common/appsettings.json +++ b/test/EventStore.Client.Tests.Common/appsettings.json @@ -3,7 +3,7 @@ "MinimumLevel": { "Default": "Debug" }, "Override": { "Microsoft": "Warning", - "Grpc": "Verbose" + "Grpc": "Information" }, "Enrich": ["FromLogContext", "WithThreadId"], "WriteTo": [ From f924ab47baf93d48ec4f17bef690cc1ee796813e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Silveira?= Date: Fri, 1 Dec 2023 23:38:12 +0100 Subject: [PATCH 06/22] removed zombie nuget packages upgraded xunit nuget packages --- test/Directory.Build.props | 4 ++-- .../EventStore.Client.Tests.Common.csproj | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/test/Directory.Build.props b/test/Directory.Build.props index 0bde796bc..73a280b20 100644 --- a/test/Directory.Build.props +++ b/test/Directory.Build.props @@ -13,8 +13,8 @@ - - + + all runtime; build; native; contentfiles; analyzers 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 60b447bb4..303d73840 100644 --- a/test/EventStore.Client.Tests.Common/EventStore.Client.Tests.Common.csproj +++ b/test/EventStore.Client.Tests.Common/EventStore.Client.Tests.Common.csproj @@ -31,9 +31,7 @@ - - From f90efca2d5d4a5d3327c2c345bcaa743b49d3b8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Silveira?= Date: Sat, 2 Dec 2023 00:33:46 +0100 Subject: [PATCH 07/22] upgraded grpc & protobuf packages minor tweaks --- Directory.Build.props | 4 +-- .../EventStore.Client.csproj | 4 +-- .../EventStore.Client.Tests.Common.csproj | 15 +++++------ .../Facts/AnonymousAccess.cs | 9 +++---- .../Facts/Deprecation.cs | 13 +++------- .../Facts/Regression.cs | 25 ++++--------------- .../Facts/SupportsPSToAllFact.cs | 11 ++++---- .../Fixtures/Base/EventStoreTestServer.cs | 2 +- .../Fixtures/EventStoreTestCluster.cs | 3 +-- .../FluentDocker/TestService.cs | 1 - .../GlobalEnvironment.cs | 3 --- .../EventStore.Client.Tests.Common/shared.env | 2 +- .../EventStore.Client.Tests.csproj | 4 +-- 13 files changed, 33 insertions(+), 63 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 2e2b7fb3b..eecbb8220 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -13,7 +13,7 @@ pdbonly true - 2.49.0 - 2.50.0 + 2.59.0 + 2.59.0 diff --git a/src/EventStore.Client/EventStore.Client.csproj b/src/EventStore.Client/EventStore.Client.csproj index ca10005c9..2bbe5b29e 100644 --- a/src/EventStore.Client/EventStore.Client.csproj +++ b/src/EventStore.Client/EventStore.Client.csproj @@ -6,9 +6,9 @@ EventStore.Client.Grpc - + - + 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 303d73840..3608cdb92 100644 --- a/test/EventStore.Client.Tests.Common/EventStore.Client.Tests.Common.csproj +++ b/test/EventStore.Client.Tests.Common/EventStore.Client.Tests.Common.csproj @@ -11,13 +11,6 @@ - - - - - - - @@ -34,6 +27,14 @@ + + + + + + + + certs\%(RecursiveDir)/%(FileName)%(Extension) diff --git a/test/EventStore.Client.Tests.Common/Facts/AnonymousAccess.cs b/test/EventStore.Client.Tests.Common/Facts/AnonymousAccess.cs index 3fd901892..575093085 100644 --- a/test/EventStore.Client.Tests.Common/Facts/AnonymousAccess.cs +++ b/test/EventStore.Client.Tests.Common/Facts/AnonymousAccess.cs @@ -1,14 +1,11 @@ namespace EventStore.Client.Tests; +[PublicAPI] public class AnonymousAccess { static readonly Version LegacySince = new(23, 6); static readonly string SkipMessage = "Anonymous access is turned off since v23.6.0!"; - public class FactAttribute : Deprecation.FactAttribute { - public FactAttribute() : base(LegacySince, SkipMessage) { } - } + public class FactAttribute() : Deprecation.FactAttribute(LegacySince, SkipMessage); - public class TheoryAttribute : Deprecation.TheoryAttribute { - public TheoryAttribute() : base(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 111b3b016..01adee242 100644 --- a/test/EventStore.Client.Tests.Common/Facts/Deprecation.cs +++ b/test/EventStore.Client.Tests.Common/Facts/Deprecation.cs @@ -1,17 +1,10 @@ namespace EventStore.Client.Tests; +[PublicAPI] public class Deprecation { - public class FactAttribute : Xunit.FactAttribute { - readonly Version _legacySince; - readonly string _skipMessage; - - public FactAttribute(Version since, string skipMessage) { - _legacySince = since; - _skipMessage = skipMessage; - } - + public class FactAttribute(Version since, string skipMessage) : Xunit.FactAttribute { public override string? Skip { - get => EventStoreTestServer.Version >= _legacySince ? _skipMessage : null; + get => EventStoreTestServer.Version >= since ? skipMessage : null; set => throw new NotSupportedException(); } } diff --git a/test/EventStore.Client.Tests.Common/Facts/Regression.cs b/test/EventStore.Client.Tests.Common/Facts/Regression.cs index 371c00547..3c6a92f0c 100644 --- a/test/EventStore.Client.Tests.Common/Facts/Regression.cs +++ b/test/EventStore.Client.Tests.Common/Facts/Regression.cs @@ -1,32 +1,17 @@ namespace EventStore.Client.Tests; +[PublicAPI] public class Regression { - public class FactAttribute : Xunit.FactAttribute { - readonly int _major; - readonly string _skipMessage; - - public FactAttribute(int major, string skipMessage) { - _major = major; - _skipMessage = skipMessage; - } - + public class FactAttribute(int major, string skipMessage) : Xunit.FactAttribute { public override string? Skip { - get => (EventStoreTestServer.Version?.Major ?? int.MaxValue) < _major ? _skipMessage : null; + get => (EventStoreTestServer.Version?.Major ?? int.MaxValue) < major ? skipMessage : null; set => throw new NotSupportedException(); } } - public class TheoryAttribute : Xunit.TheoryAttribute { - readonly int _major; - readonly string _skipMessage; - - public TheoryAttribute(int major, string skipMessage) { - _major = major; - _skipMessage = skipMessage; - } - + public class TheoryAttribute(int major, string skipMessage) : Xunit.TheoryAttribute { public override string? Skip { - get => (EventStoreTestServer.Version?.Major ?? int.MaxValue) < _major ? _skipMessage : null; + get => (EventStoreTestServer.Version?.Major ?? int.MaxValue) < major ? skipMessage : null; set => throw new NotSupportedException(); } } diff --git a/test/EventStore.Client.Tests.Common/Facts/SupportsPSToAllFact.cs b/test/EventStore.Client.Tests.Common/Facts/SupportsPSToAllFact.cs index 9200aaf46..3f5d993fe 100644 --- a/test/EventStore.Client.Tests.Common/Facts/SupportsPSToAllFact.cs +++ b/test/EventStore.Client.Tests.Common/Facts/SupportsPSToAllFact.cs @@ -1,5 +1,8 @@ +// ReSharper disable InconsistentNaming + namespace EventStore.Client.Tests; +[PublicAPI] public class SupportsPSToAll { const int SupportedFromMajorVersion = 21; @@ -9,11 +12,7 @@ public class SupportsPSToAll { public static bool No => !Yes; public static bool Yes => (EventStoreTestServer.Version?.Major ?? int.MaxValue) >= SupportedFromMajorVersion; - public class FactAttribute : Regression.FactAttribute { - public FactAttribute() : base(SupportedFromMajorVersion, SkipMessage) { } - } + public class FactAttribute() : Regression.FactAttribute(SupportedFromMajorVersion, SkipMessage); - public class TheoryAttribute : Regression.TheoryAttribute { - public TheoryAttribute() : base(SupportedFromMajorVersion, SkipMessage) { } - } + public class TheoryAttribute() : Regression.TheoryAttribute(SupportedFromMajorVersion, SkipMessage); } \ No newline at end of file diff --git a/test/EventStore.Client.Tests.Common/Fixtures/Base/EventStoreTestServer.cs b/test/EventStore.Client.Tests.Common/Fixtures/Base/EventStoreTestServer.cs index 98ec6ebb2..772946347 100644 --- a/test/EventStore.Client.Tests.Common/Fixtures/Base/EventStoreTestServer.cs +++ b/test/EventStore.Client.Tests.Common/Fixtures/Base/EventStoreTestServer.cs @@ -33,7 +33,7 @@ public EventStoreTestServer( }; var env = new Dictionary { - ["EVENTSTORE_DB_LOG_FORMAT"] = GlobalEnvironment.DbLogFormat, + ["EVENTSTORE_DB_LOG_FORMAT"] = "V2", ["EVENTSTORE_MEM_DB"] = "true", ["EVENTSTORE_CHUNK_SIZE"] = (1024 * 1024).ToString(), ["EVENTSTORE_CERTIFICATE_FILE"] = "/etc/eventstore/certs/node/node.crt", diff --git a/test/EventStore.Client.Tests.Common/Fixtures/EventStoreTestCluster.cs b/test/EventStore.Client.Tests.Common/Fixtures/EventStoreTestCluster.cs index d0f0bbe88..f97b852e2 100644 --- a/test/EventStore.Client.Tests.Common/Fixtures/EventStoreTestCluster.cs +++ b/test/EventStore.Client.Tests.Common/Fixtures/EventStoreTestCluster.cs @@ -26,8 +26,7 @@ public static EventStoreFixtureOptions DefaultOptions() { ["EVENTSTORE_DISCOVER_VIA_DNS"] = "false", ["EVENTSTORE_ENABLE_EXTERNAL_TCP"] = "false", ["EVENTSTORE_STREAM_EXISTENCE_FILTER_SIZE"] = "10000", - ["EVENTSTORE_STREAM_INFO_CACHE_CAPACITY"] = "10000", - ["EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP"] = "true" // why true? + ["EVENTSTORE_STREAM_INFO_CACHE_CAPACITY"] = "10000" }; return new(defaultSettings, defaultEnvironment); diff --git a/test/EventStore.Client.Tests.Common/FluentDocker/TestService.cs b/test/EventStore.Client.Tests.Common/FluentDocker/TestService.cs index 7b90a89c7..3e10cbeb2 100644 --- a/test/EventStore.Client.Tests.Common/FluentDocker/TestService.cs +++ b/test/EventStore.Client.Tests.Common/FluentDocker/TestService.cs @@ -1,4 +1,3 @@ -using Ductus.FluentDocker; using Ductus.FluentDocker.Builders; using Ductus.FluentDocker.Common; using Ductus.FluentDocker.Services; diff --git a/test/EventStore.Client.Tests.Common/GlobalEnvironment.cs b/test/EventStore.Client.Tests.Common/GlobalEnvironment.cs index 563ff4cb6..d797a8369 100644 --- a/test/EventStore.Client.Tests.Common/GlobalEnvironment.cs +++ b/test/EventStore.Client.Tests.Common/GlobalEnvironment.cs @@ -10,7 +10,6 @@ static GlobalEnvironment() { UseCluster = Application.Configuration.GetValue("ES_USE_CLUSTER"); UseExternalServer = Application.Configuration.GetValue("ES_USE_EXTERNAL_SERVER"); DockerImage = Application.Configuration.GetValue("ES_DOCKER_IMAGE")!; - DbLogFormat = Application.Configuration.GetValue("EVENTSTORE_DB_LOG_FORMAT")!; Variables = Application.Configuration.AsEnumerable() .Where(x => x.Key.StartsWith("ES_") || x.Key.StartsWith("EVENTSTORE_")) @@ -30,7 +29,6 @@ static void EnsureDefaults(IConfiguration configuration) { configuration.EnsureValue("EVENTSTORE_MEM_DB", "false"); configuration.EnsureValue("EVENTSTORE_RUN_PROJECTIONS", "None"); configuration.EnsureValue("EVENTSTORE_START_STANDARD_PROJECTIONS", "false"); - configuration.EnsureValue("EVENTSTORE_DB_LOG_FORMAT", "V2"); configuration.EnsureValue("EVENTSTORE_LOG_LEVEL", "Verbose"); configuration.EnsureValue("EVENTSTORE_TRUSTED_ROOT_CERTIFICATES_PATH", "/etc/eventstore/certs/ca"); @@ -43,7 +41,6 @@ static void EnsureDefaults(IConfiguration configuration) { public static bool UseCluster { get; } public static bool UseExternalServer { get; } public static string DockerImage { get; } - public static string DbLogFormat { get; } #region . Obsolete . diff --git a/test/EventStore.Client.Tests.Common/shared.env b/test/EventStore.Client.Tests.Common/shared.env index d8746d86a..2b8c93eff 100644 --- a/test/EventStore.Client.Tests.Common/shared.env +++ b/test/EventStore.Client.Tests.Common/shared.env @@ -4,7 +4,7 @@ EVENTSTORE_HTTP_PORT=2113 EVENTSTORE_TRUSTED_ROOT_CERTIFICATES_PATH=/etc/eventstore/certs/ca EVENTSTORE_DISCOVER_VIA_DNS=false EVENTSTORE_ENABLE_EXTERNAL_TCP=false -EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP=true +EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP=false EVENTSTORE_STREAM_EXISTENCE_FILTER_SIZE=10000 # pass through from environment diff --git a/test/EventStore.Client.Tests/EventStore.Client.Tests.csproj b/test/EventStore.Client.Tests/EventStore.Client.Tests.csproj index 44a934d3b..0bd9cef57 100644 --- a/test/EventStore.Client.Tests/EventStore.Client.Tests.csproj +++ b/test/EventStore.Client.Tests/EventStore.Client.Tests.csproj @@ -16,8 +16,8 @@ - - + + all From 7bb5a21a101f329e54a179f88b089e805c341273 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Silveira?= Date: Mon, 4 Dec 2023 19:11:56 +0100 Subject: [PATCH 08/22] fixed logging configuration refactored typed exception interceptor refactored subscription reconnection test fixed fixture GetStreamName helper added restart capabilities to test service --- Directory.Build.props | 6 +- .../EventStoreOperationsClient.cs | 57 ++--- .../EventStoreUserManagementClient.cs | 2 +- src/EventStore.Client/EventStoreClientBase.cs | 4 +- .../Interceptors/TypedExceptionInterceptor.cs | 242 ++++++++++-------- .../append_to_stream_limits.cs | 83 +++--- .../append_to_stream_retry.cs | 6 +- .../reconnection.cs | 239 +++++++++++------ .../Fixtures/EventStoreFixture.Helpers.cs | 16 +- .../Fixtures/EventStoreFixture.cs | 7 +- .../Fixtures/EventStoreTestNode.cs | 19 +- .../FluentDocker/TestService.cs | 39 ++- .../GlobalEnvironment.cs | 9 +- .../EventStore.Client.Tests.Common/Logging.cs | 7 +- .../appsettings.Development.json | 14 +- .../appsettings.json | 11 +- .../enabling_a_user.cs | 3 +- 17 files changed, 471 insertions(+), 293 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index eecbb8220..21cacfc24 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -13,7 +13,9 @@ pdbonly true - 2.59.0 - 2.59.0 + 2.49.0 + 2.50.0 + + diff --git a/src/EventStore.Client.Operations/EventStoreOperationsClient.cs b/src/EventStore.Client.Operations/EventStoreOperationsClient.cs index 156d0eda0..672383348 100644 --- a/src/EventStore.Client.Operations/EventStoreOperationsClient.cs +++ b/src/EventStore.Client.Operations/EventStoreOperationsClient.cs @@ -1,38 +1,33 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Grpc.Core; +using Grpc.Core; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; -namespace EventStore.Client { - /// - /// The client used to perform maintenance and other administrative tasks on the EventStoreDB. - /// - public sealed partial class EventStoreOperationsClient : EventStoreClientBase { - private static readonly IDictionary> ExceptionMap = - new Dictionary> { - [Constants.Exceptions.ScavengeNotFound] = ex => new ScavengeNotFoundException(ex.Trailers - .FirstOrDefault(x => x.Key == Constants.Exceptions.ScavengeId)?.Value) - }; +namespace EventStore.Client; - private readonly ILogger _log; +/// +/// The client used to perform maintenance and other administrative tasks on the EventStoreDB. +/// +public sealed partial class EventStoreOperationsClient : EventStoreClientBase { + static readonly Dictionary> ExceptionMap = + new() { + [Constants.Exceptions.ScavengeNotFound] = ex => new ScavengeNotFoundException( + ex.Trailers.FirstOrDefault(x => x.Key == Constants.Exceptions.ScavengeId)?.Value + ) + }; - /// - /// Constructs a new . This method is not intended to be called directly in your code. - /// - /// - public EventStoreOperationsClient(IOptions options) : this(options.Value) { - } + readonly ILogger _log; - /// - /// Constructs a new . - /// - /// - public EventStoreOperationsClient(EventStoreClientSettings? settings = null) : base(settings, ExceptionMap) { - _log = Settings.LoggerFactory?.CreateLogger() ?? - new NullLogger(); - } - } -} + /// + /// Constructs a new . This method is not intended to be called directly in your code. + /// + /// + public EventStoreOperationsClient(IOptions options) : this(options.Value) { } + + /// + /// Constructs a new . + /// + /// + public EventStoreOperationsClient(EventStoreClientSettings? settings = null) : base(settings, ExceptionMap) => + _log = Settings.LoggerFactory?.CreateLogger() ?? new NullLogger(); +} \ No newline at end of file diff --git a/src/EventStore.Client.UserManagement/EventStoreUserManagementClient.cs b/src/EventStore.Client.UserManagement/EventStoreUserManagementClient.cs index a0680cbf6..6b86e81b4 100644 --- a/src/EventStore.Client.UserManagement/EventStoreUserManagementClient.cs +++ b/src/EventStore.Client.UserManagement/EventStoreUserManagementClient.cs @@ -270,7 +270,7 @@ public async Task ResetPasswordAsync(string loginName, string newPassword, await call.ResponseAsync.ConfigureAwait(false); } - private static readonly IDictionary> ExceptionMap = + private static readonly Dictionary> ExceptionMap = new Dictionary> { [Constants.Exceptions.UserNotFound] = ex => new UserNotFoundException( ex.Trailers.First(x => x.Key == Constants.Exceptions.LoginName).Value), diff --git a/src/EventStore.Client/EventStoreClientBase.cs b/src/EventStore.Client/EventStoreClientBase.cs index d3252a330..39f579fcc 100644 --- a/src/EventStore.Client/EventStoreClientBase.cs +++ b/src/EventStore.Client/EventStoreClientBase.cs @@ -14,7 +14,7 @@ public abstract class EventStoreClientBase : IDisposable, // for grpc.net we can dispose synchronously, but not for grpc.core IAsyncDisposable { - private readonly IDictionary> _exceptionMap; + private readonly Dictionary> _exceptionMap; private readonly CancellationTokenSource _cts; private readonly ChannelCache _channelCache; private readonly SharingProvider _channelInfoProvider; @@ -28,7 +28,7 @@ public abstract class EventStoreClientBase : /// Constructs a new . protected EventStoreClientBase(EventStoreClientSettings? settings, - IDictionary> exceptionMap) { + Dictionary> exceptionMap) { Settings = settings ?? new EventStoreClientSettings(); _exceptionMap = exceptionMap; _cts = new CancellationTokenSource(); diff --git a/src/EventStore.Client/Interceptors/TypedExceptionInterceptor.cs b/src/EventStore.Client/Interceptors/TypedExceptionInterceptor.cs index f49307287..7a6965284 100644 --- a/src/EventStore.Client/Interceptors/TypedExceptionInterceptor.cs +++ b/src/EventStore.Client/Interceptors/TypedExceptionInterceptor.cs @@ -1,119 +1,159 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; +using System.Diagnostics.CodeAnalysis; using Grpc.Core; using Grpc.Core.Interceptors; +using static EventStore.Client.Constants; +using static Grpc.Core.StatusCode; -namespace EventStore.Client.Interceptors { - internal class TypedExceptionInterceptor : Interceptor { - private static readonly IDictionary> DefaultExceptionMap = - new Dictionary> { - [Constants.Exceptions.AccessDenied] = ex => new AccessDeniedException(ex.Message, ex), - [Constants.Exceptions.NotLeader] = ex => new NotLeaderException( - ex.Trailers.FirstOrDefault(x => x.Key == Constants.Exceptions.LeaderEndpointHost)?.Value!, - ex.Trailers.GetIntValueOrDefault(Constants.Exceptions.LeaderEndpointPort), ex) +namespace EventStore.Client.Interceptors; + +static class EnumerableExtensions { + public static Dictionary ToDictionary(this IEnumerable> source) where TKey : notnull => + ToDictionary(source, null); + + public static Dictionary ToDictionary(this IEnumerable> source, IEqualityComparer? comparer) where TKey : notnull => + new(source, comparer); +} + +class TypedExceptionInterceptor : Interceptor { + static readonly Dictionary> DefaultExceptionMap = new() { + [Exceptions.AccessDenied] = ex => ex.ToAccessDeniedException(), + [Exceptions.NotLeader] = ex => ex.ToNotLeaderException(), + }; + + public TypedExceptionInterceptor(Dictionary> customExceptionMap) { + //var map = DefaultExceptionMap.Concat(customExceptionMap).ToDictionary(); // net 8... + var map = new Dictionary>(DefaultExceptionMap.Concat(customExceptionMap)); + + ConvertRpcException = rpcEx => { + if (rpcEx.TryMapException(map, out var ex)) + throw ex; + + throw rpcEx.StatusCode switch { + Unavailable when rpcEx.Status.Detail == "Deadline Exceeded" => rpcEx.ToDeadlineExceededRpcException(), + Unauthenticated => rpcEx.ToNotAuthenticatedException(), + _ => rpcEx }; + }; + } - private readonly IDictionary> _exceptionMap; + Func ConvertRpcException { get; } + + public override AsyncServerStreamingCall AsyncServerStreamingCall( + TRequest request, + ClientInterceptorContext context, + AsyncServerStreamingCallContinuation continuation + ) { + var response = continuation(request, context); + + return new AsyncServerStreamingCall( + response.ResponseStream.Apply(ConvertRpcException), + response.ResponseHeadersAsync, + response.GetStatus, + response.GetTrailers, + response.Dispose + ); + } - public TypedExceptionInterceptor(IDictionary> exceptionMap) { - _exceptionMap = new Dictionary>(DefaultExceptionMap); - foreach (var pair in exceptionMap) { - _exceptionMap.Add(pair); - } - } + public override AsyncClientStreamingCall AsyncClientStreamingCall( + ClientInterceptorContext context, + AsyncClientStreamingCallContinuation continuation + ) { + var response = continuation(context); + + return new AsyncClientStreamingCall( + response.RequestStream, + response.ResponseAsync.Apply(ConvertRpcException), + response.ResponseHeadersAsync, + response.GetStatus, + response.GetTrailers, + response.Dispose + ); + } - public override AsyncServerStreamingCall AsyncServerStreamingCall( - TRequest request, - ClientInterceptorContext context, - AsyncServerStreamingCallContinuation continuation) { - var response = continuation(request, context); + public override AsyncUnaryCall AsyncUnaryCall( + TRequest request, + ClientInterceptorContext context, + AsyncUnaryCallContinuation continuation + ) { + var response = continuation(request, context); + + return new AsyncUnaryCall( + response.ResponseAsync.Apply(ConvertRpcException), + response.ResponseHeadersAsync, + response.GetStatus, + response.GetTrailers, + response.Dispose + ); + } - return new AsyncServerStreamingCall( - new AsyncStreamReader(_exceptionMap, response.ResponseStream), - response.ResponseHeadersAsync, response.GetStatus, response.GetTrailers, response.Dispose); - } + public override AsyncDuplexStreamingCall AsyncDuplexStreamingCall( + ClientInterceptorContext context, + AsyncDuplexStreamingCallContinuation continuation + ) { + var response = continuation(context); + + return new AsyncDuplexStreamingCall( + response.RequestStream, + response.ResponseStream.Apply(ConvertRpcException), + response.ResponseHeadersAsync, + response.GetStatus, + response.GetTrailers, + response.Dispose + ); + } +} - public override AsyncClientStreamingCall AsyncClientStreamingCall( - ClientInterceptorContext context, - AsyncClientStreamingCallContinuation continuation) { - var response = continuation(context); - - return new AsyncClientStreamingCall( - response.RequestStream, - response.ResponseAsync.ContinueWith(t => t.Exception?.InnerException is RpcException ex - ? throw ConvertRpcException(ex, _exceptionMap) - : t.Result), - response.ResponseHeadersAsync, - response.GetStatus, - response.GetTrailers, - response.Dispose); - } +static class RpcExceptionConversionExtensions { + public static IAsyncStreamReader Apply(this IAsyncStreamReader reader, Func convertException) => + new ExceptionConverterStreamReader(reader, convertException); - public override AsyncUnaryCall AsyncUnaryCall( - TRequest request, - ClientInterceptorContext context, - AsyncUnaryCallContinuation continuation) { - var response = continuation(request, context); - - return new AsyncUnaryCall(response.ResponseAsync.ContinueWith(t => - t.Exception?.InnerException is RpcException ex - ? throw ConvertRpcException(ex, _exceptionMap) - : t.Result), response.ResponseHeadersAsync, response.GetStatus, response.GetTrailers, - response.Dispose); - } + // public static Task Apply(this Task task, Func convertException) => + // task.ContinueWith(t => t.Exception?.InnerException is RpcException ex ? throw convertException(ex) : t.Result); - public override AsyncDuplexStreamingCall AsyncDuplexStreamingCall( - ClientInterceptorContext context, - AsyncDuplexStreamingCallContinuation continuation) { - var response = continuation(context); - - return new AsyncDuplexStreamingCall( - response.RequestStream, - new AsyncStreamReader(_exceptionMap, response.ResponseStream), - response.ResponseHeadersAsync, - response.GetStatus, - response.GetTrailers, - response.Dispose); + public static async Task Apply(this Task task, Func convertException) { + try { + return await task.ConfigureAwait(false); + } + catch (RpcException ex) { + throw convertException(ex); } + } + + public static AccessDeniedException ToAccessDeniedException(this RpcException exception) => + new(exception.Message, exception); + + public static NotLeaderException ToNotLeaderException(this RpcException exception) { + var host = exception.Trailers.FirstOrDefault(x => x.Key == Exceptions.LeaderEndpointHost)?.Value!; + var port = exception.Trailers.GetIntValueOrDefault(Exceptions.LeaderEndpointPort); + return new NotLeaderException(host, port, exception); + } + + public static NotAuthenticatedException ToNotAuthenticatedException(this RpcException exception) => + new(exception.Message, exception); - private static Exception ConvertRpcException(RpcException ex, - IDictionary> exceptionMap) { - Func? factory = null; - return (ex.Trailers.TryGetValue(Constants.Exceptions.ExceptionKey, out var key) && - exceptionMap.TryGetValue(key!, out factory)) switch { - true => factory!.Invoke(ex), - false => (ex.StatusCode, ex.Status.Detail) switch { - (StatusCode.Unavailable, "Deadline Exceeded") => new RpcException(new Status( - StatusCode.DeadlineExceeded, ex.Status.Detail, ex.Status.DebugException)), - (StatusCode.DeadlineExceeded, _) => ex, - (StatusCode.Unauthenticated, _) => new NotAuthenticatedException(ex.Message, ex), - _ => ex - } - }; + public static RpcException ToDeadlineExceededRpcException(this RpcException exception) => + new(new Status(DeadlineExceeded, exception.Status.Detail, exception.Status.DebugException)); + + public static bool TryMapException(this RpcException exception, Dictionary> map, [MaybeNullWhen(false)] out Exception createdException) { + if (exception.Trailers.TryGetValue(Exceptions.ExceptionKey, out var key) && map.TryGetValue(key!, out var factory)) { + createdException = factory.Invoke(exception); + return true; } - private class AsyncStreamReader : IAsyncStreamReader { - private readonly IDictionary> _exceptionMap; - private readonly IAsyncStreamReader _inner; - - public AsyncStreamReader(IDictionary> exceptionMap, - IAsyncStreamReader inner) { - _exceptionMap = exceptionMap; - _inner = inner; - } - - public async Task MoveNext(CancellationToken cancellationToken) { - try { - return await _inner.MoveNext(cancellationToken).ConfigureAwait(false); - } catch (RpcException ex) { - throw ConvertRpcException(ex, _exceptionMap); - } - } - - public TResponse Current => _inner.Current; + createdException = null; + return false; + } +} + +class ExceptionConverterStreamReader(IAsyncStreamReader reader, Func convertException) : IAsyncStreamReader { + public TResponse Current => reader.Current; + + public async Task MoveNext(CancellationToken cancellationToken) { + try { + return await reader.MoveNext(cancellationToken).ConfigureAwait(false); + } + catch (RpcException ex) { + throw convertException(ex); } } } diff --git a/test/EventStore.Client.Streams.Tests/append_to_stream_limits.cs b/test/EventStore.Client.Streams.Tests/append_to_stream_limits.cs index 27b0885a0..5247ae9d9 100644 --- a/test/EventStore.Client.Streams.Tests/append_to_stream_limits.cs +++ b/test/EventStore.Client.Streams.Tests/append_to_stream_limits.cs @@ -1,57 +1,58 @@ namespace EventStore.Client.Streams.Tests; -public class append_to_stream_limits : IClassFixture { - const int MaxAppendSize = 1024; - - readonly Fixture _fixture; - - public append_to_stream_limits(Fixture fixture) => _fixture = fixture; +public class append_to_stream_limits : IClassFixture { + public append_to_stream_limits(ITestOutputHelper output, StreamLimitsFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); + StreamLimitsFixture Fixture { get; } + [Fact] public async Task succeeds_when_size_is_less_than_max_append_size() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); + + var (events, size) = Fixture.CreateTestEventsUpToMaxSize(StreamLimitsFixture.MaxAppendSize - 1); - await _fixture.Client.AppendToStreamAsync( - stream, - StreamState.NoStream, - _fixture.GetEvents(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 ex = await Assert.ThrowsAsync( - () => _fixture.Client.AppendToStreamAsync( - stream, - StreamState.NoStream, - _fixture.GetEvents(MaxAppendSize * 2) - ) - ); - - Assert.Equal((uint)MaxAppendSize, ex.MaxAppendSize); + 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 Fixture : EventStoreClientFixture { - public Fixture() : base( - env: new() { - ["EVENTSTORE_MAX_APPEND_SIZE"] = $"{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; } - ) { } - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - - public IEnumerable GetEvents(int maxSize) { - var size = 0; - foreach (var e in CreateTestEvents(int.MaxValue)) { - size += e.Data.Length; - if (size >= maxSize) - yield break; - - yield return e; - } + events.Add(evt); } + + return (events, (uint)size); } } \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/append_to_stream_retry.cs b/test/EventStore.Client.Streams.Tests/append_to_stream_retry.cs index fd2c8e70c..9db0343e0 100644 --- a/test/EventStore.Client.Streams.Tests/append_to_stream_retry.cs +++ b/test/EventStore.Client.Streams.Tests/append_to_stream_retry.cs @@ -23,9 +23,7 @@ public async Task can_retry() { var ex = await Assert.ThrowsAnyAsync(() => WriteAnEventAsync(new(0))); Assert.True( ex is RpcException { - Status: { - StatusCode: StatusCode.Unavailable - } + Status.StatusCode: StatusCode.Unavailable } or DiscoveryException ); @@ -34,7 +32,7 @@ ex is RpcException { // write can be retried var writeResult = await Policy .Handle() - .WaitAndRetryAsync(5, _ => TimeSpan.FromSeconds(3)) + .WaitAndRetryAsync(2, _ => TimeSpan.FromSeconds(1)) .ExecuteAsync(async () => await WriteAnEventAsync(new(0))); Assert.Equal(new(1), writeResult.NextExpectedStreamRevision); diff --git a/test/EventStore.Client.Streams.Tests/reconnection.cs b/test/EventStore.Client.Streams.Tests/reconnection.cs index bdb2174a6..8843b1c46 100644 --- a/test/EventStore.Client.Streams.Tests/reconnection.cs +++ b/test/EventStore.Client.Streams.Tests/reconnection.cs @@ -1,103 +1,182 @@ using Grpc.Core; +using static System.TimeSpan; namespace EventStore.Client.Streams.Tests; -public class @reconnection : IClassFixture { - readonly Fixture _fixture; - - public reconnection(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task when_the_connection_is_lost() { - var streamName = _fixture.GetStreamName(); - var eventCount = 512; - var receivedAllEvents = new TaskCompletionSource(); - var serverRestarted = new TaskCompletionSource(); - var receivedEvents = new List(); - var resubscribed = new TaskCompletionSource(); - - using var _ = await _fixture.Client.SubscribeToStreamAsync( - streamName, - FromStream.Start, - EventAppeared, - subscriptionDropped: SubscriptionDropped - ) - .WithTimeout(); - - await _fixture.Client - .AppendToStreamAsync(streamName, StreamState.NoStream, _fixture.CreateTestEvents(eventCount)) - .WithTimeout(); // ensure we get backpressure - - _fixture.TestServer.Stop(); - await Task.Delay(TimeSpan.FromSeconds(2)); - - await _fixture.TestServer.StartAsync().WithTimeout(); - serverRestarted.SetResult(); +public class @reconnection : IClassFixture { + public reconnection(ITestOutputHelper output, ReconnectionFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); + + ReconnectionFixture Fixture { get; } + + [Theory] + [InlineData(4, 1000, 0, 15000)] + 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(); + } +} - await resubscribed.Task.WithTimeout(TimeSpan.FromSeconds(10)); +public class ReconnectionFixture() + : EventStoreFixture( + x => x.RunInMemory(false) + .With(o => o.ClientSettings.ConnectivitySettings.DiscoveryInterval = FromMilliseconds(100)) + .With(o => o.ClientSettings.ConnectivitySettings.GossipTimeout = FromMilliseconds(100)) + ) { + - await receivedAllEvents.Task.WithTimeout(TimeSpan.FromSeconds(10)); - async Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) { - await serverRestarted.Task; - receivedEvents.Add(e); - if (receivedEvents.Count == eventCount) - receivedAllEvents.TrySetResult(); - } + 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 + ); - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) { - if (reason == SubscriptionDroppedReason.Disposed || ex is null) - return; + if (result is SuccessResult success) { + Log.Information( + "{NumberOfEvents} events produced to {StreamName}.", numberOfEvents, streamName + ); - if (ex is not RpcException { - Status.StatusCode: StatusCode.Unavailable - }) { - receivedAllEvents.TrySetException(ex); - } - else { - var _ = ResubscribeAsync(); - } - } + return; + } - async Task ResubscribeAsync() { - try { - var sub = await _fixture.Client.SubscribeToStreamAsync( - streamName, - receivedEvents.Any() - ? FromStream.After(receivedEvents[^1].OriginalEventNumber) - : FromStream.Start, - EventAppeared, - subscriptionDropped: SubscriptionDropped + Log.Error( + "Failed to produce {NumberOfEvents} events to {StreamName}.", numberOfEvents, streamName ); - resubscribed.SetResult(sub); + await Task.Delay(250); } - catch (Exception ex) { - ex = ex.GetBaseException(); + catch (Exception ex) when ( ex is not OperationCanceledException) { + Log.Error( + ex, "Failed to produce {NumberOfEvents} events to {StreamName}.", numberOfEvents, streamName + ); - if (ex is RpcException) { - await Task.Delay(200); - var _ = ResubscribeAsync(); - } - else { - resubscribed.SetException(ex); - } + await Task.Delay(250); } } } - public class Fixture : EventStoreClientFixture { - public Fixture() : base( - env: new() { - ["EVENTSTORE_MEM_DB"] = "false" - } - ) { - Settings.ConnectivitySettings.DiscoveryInterval = TimeSpan.FromMilliseconds(100); - Settings.ConnectivitySettings.GossipTimeout = TimeSpan.FromMilliseconds(100); + 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; + }; } - protected override Task Given() => 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); - protected override Task When() => Task.CompletedTask; + return false; + }; + } + } + + 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); + } } } \ No newline at end of file diff --git a/test/EventStore.Client.Tests.Common/Fixtures/EventStoreFixture.Helpers.cs b/test/EventStore.Client.Tests.Common/Fixtures/EventStoreFixture.Helpers.cs index 960434c33..f698dd55a 100644 --- a/test/EventStore.Client.Tests.Common/Fixtures/EventStoreFixture.Helpers.cs +++ b/test/EventStore.Client.Tests.Common/Fixtures/EventStoreFixture.Helpers.cs @@ -8,9 +8,9 @@ public partial class EventStoreFixture { public T NewClient(Action configure) where T : EventStoreClientBase, new() => (T)Activator.CreateInstance(typeof(T), new object?[] { ClientSettings.With(configure) })!; - + public string GetStreamName([CallerMemberName] string? testMethod = null) => - $"{GetType().DeclaringType?.Name}.{testMethod ?? "unknown"}"; + $"{testMethod}-{Guid.NewGuid():N}"; public IEnumerable CreateTestEvents(int count = 1, string? type = null, int metadataSize = 1) => Enumerable.Range(0, count).Select(index => CreateTestEvent(index, type ?? TestEventType, metadataSize)); @@ -37,14 +37,18 @@ public Task CreateTestUsers(int count = 3, bool withoutGroups = true .Select( async user => { await Users.CreateUserAsync( - user.LoginName, - user.FullName, - user.Groups, - user.Password, + user.LoginName, user.FullName, user.Groups, user.Password, userCredentials: useUserCredentials ? user.Credentials : TestCredentials.Root ); return user; } ).WhenAll(); + + public async Task RestartService(TimeSpan delay, Action? restarted = default) { + await Service.Restart(delay); + await Streams.WarmUp(); + Log.Information("Service restarted."); + restarted?.Invoke(); + } } \ No newline at end of file diff --git a/test/EventStore.Client.Tests.Common/Fixtures/EventStoreFixture.cs b/test/EventStore.Client.Tests.Common/Fixtures/EventStoreFixture.cs index 510293119..91767af78 100644 --- a/test/EventStore.Client.Tests.Common/Fixtures/EventStoreFixture.cs +++ b/test/EventStore.Client.Tests.Common/Fixtures/EventStoreFixture.cs @@ -21,6 +21,9 @@ this with { 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); @@ -31,7 +34,7 @@ public partial class EventStoreFixture : IAsyncLifetime, IAsyncDisposable { static EventStoreFixture() { Logging.Initialize(); - Logger = Log.ForContext(); + Logger = Serilog.Log.ForContext(); ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; } @@ -57,6 +60,8 @@ protected EventStoreFixture(ConfigureFixture configure) { List TestRuns { get; } = new(); + public ILogger Log => Logger; + public ITestService Service { get; } public EventStoreFixtureOptions Options { get; } diff --git a/test/EventStore.Client.Tests.Common/Fixtures/EventStoreTestNode.cs b/test/EventStore.Client.Tests.Common/Fixtures/EventStoreTestNode.cs index 547e9e8df..cfe7688cc 100644 --- a/test/EventStore.Client.Tests.Common/Fixtures/EventStoreTestNode.cs +++ b/test/EventStore.Client.Tests.Common/Fixtures/EventStoreTestNode.cs @@ -31,15 +31,16 @@ public static EventStoreFixtureOptions DefaultOptions() { .With(x => x.ConnectivitySettings.DiscoveryInterval = FromSeconds(1)); var defaultEnvironment = new Dictionary(GlobalEnvironment.Variables) { - ["EVENTSTORE_ENABLE_EXTERNAL_TCP"] = "false", - ["EVENTSTORE_MEM_DB"] = "true", - ["EVENTSTORE_CHUNK_SIZE"] = (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_DISABLE_LOG_FILE"] = "true" + ["EVENTSTORE_ENABLE_EXTERNAL_TCP"] = "false", + ["EVENTSTORE_MEM_DB"] = "true", + ["EVENTSTORE_CHUNK_SIZE"] = (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"] = "false", + ["EVENTSTORE_DISABLE_LOG_FILE"] = "true", + ["EVENTSTORE_ADVERTISE_HTTP_PORT_TO_CLIENT_AS"] = $"{NetworkPortProvider.DefaultEsdbPort}" }; // TODO SS: must find a way to enable parallel tests on CI. It works locally. diff --git a/test/EventStore.Client.Tests.Common/FluentDocker/TestService.cs b/test/EventStore.Client.Tests.Common/FluentDocker/TestService.cs index 3e10cbeb2..026e0a12c 100644 --- a/test/EventStore.Client.Tests.Common/FluentDocker/TestService.cs +++ b/test/EventStore.Client.Tests.Common/FluentDocker/TestService.cs @@ -9,7 +9,10 @@ namespace EventStore.Client.Tests.FluentDocker; public interface ITestService : IAsyncDisposable { Task Start(); Task Stop(); - + Task Restart(TimeSpan delay); + + Task Restart() => Restart(TimeSpan.Zero); + void ReportStatus(); } @@ -60,6 +63,40 @@ public virtual async Task Stop() { throw new FluentDockerException("Failed to stop container service", ex); } } + + public virtual async Task Restart(TimeSpan delay) { + try { + try { + Service.Stop(); + Logger.Information("Container service stopped"); + } + catch (Exception ex) { + throw new FluentDockerException("Failed to stop container service", ex); + } + + await Task.Delay(delay); + + Logger.Information("Container service starting..."); + + try { + Service.Start(); + } + catch (Exception ex) { + throw new FluentDockerException("Failed to start container service", ex); + } + + try { + await OnServiceStarted(); + Logger.Information("Container service started"); + } + catch (Exception ex) { + throw new FluentDockerException($"{nameof(OnServiceStarted)} execution error", ex); + } + } + catch (Exception ex) { + throw new FluentDockerException("Failed to restart container service", ex); + } + } public void ReportStatus() { if (Service is IContainerService containerService) { diff --git a/test/EventStore.Client.Tests.Common/GlobalEnvironment.cs b/test/EventStore.Client.Tests.Common/GlobalEnvironment.cs index d797a8369..3ecc3c859 100644 --- a/test/EventStore.Client.Tests.Common/GlobalEnvironment.cs +++ b/test/EventStore.Client.Tests.Common/GlobalEnvironment.cs @@ -23,16 +23,17 @@ static void EnsureDefaults(IConfiguration configuration) { configuration.EnsureValue("ES_USE_EXTERNAL_SERVER", "false"); configuration.EnsureValue("ES_DOCKER_REGISTRY", "ghcr.io/eventstore/eventstore"); - configuration.EnsureValue("ES_DOCKER_TAG", "previous-lts"); + configuration.EnsureValue("ES_DOCKER_TAG", "latest"); configuration.EnsureValue("ES_DOCKER_IMAGE", $"{configuration["ES_DOCKER_REGISTRY"]}:{configuration["ES_DOCKER_TAG"]}"); configuration.EnsureValue("EVENTSTORE_MEM_DB", "false"); configuration.EnsureValue("EVENTSTORE_RUN_PROJECTIONS", "None"); configuration.EnsureValue("EVENTSTORE_START_STANDARD_PROJECTIONS", "false"); - configuration.EnsureValue("EVENTSTORE_LOG_LEVEL", "Verbose"); - configuration.EnsureValue("EVENTSTORE_TRUSTED_ROOT_CERTIFICATES_PATH", "/etc/eventstore/certs/ca"); - + configuration.EnsureValue("EVENTSTORE_LOG_LEVEL", "Information"); 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", "false"); + } } diff --git a/test/EventStore.Client.Tests.Common/Logging.cs b/test/EventStore.Client.Tests.Common/Logging.cs index 1c37ef142..a9df9709a 100644 --- a/test/EventStore.Client.Tests.Common/Logging.cs +++ b/test/EventStore.Client.Tests.Common/Logging.cs @@ -52,7 +52,12 @@ Action WriteLogEvent() => logEvent.AddPropertyIfAbsent(testRunIdProperty); using var writer = new StringWriter(); DefaultFormatter.Format(logEvent, writer); - write(writer.ToString().Trim()); + try { + write(writer.ToString().Trim()); + } + catch (Exception) { + // ignored + } }; } diff --git a/test/EventStore.Client.Tests.Common/appsettings.Development.json b/test/EventStore.Client.Tests.Common/appsettings.Development.json index e459e6332..d2f3f54f5 100644 --- a/test/EventStore.Client.Tests.Common/appsettings.Development.json +++ b/test/EventStore.Client.Tests.Common/appsettings.Development.json @@ -1,9 +1,15 @@ { "Serilog": { - "MinimumLevel": { "Default": "Debug" }, - "Override": { - "Microsoft": "Warning", - "Grpc": "Verbose" + "MinimumLevel": { + "Default": "Debug", + "Override": { + "Microsoft": "Warning", + "Grpc": "Information", + "Grpc.Net.Client.Internal.GrpcCall": "Fatal", + "EventStore.Client.SharingProvider": "Information", + "EventStore.Client.EventStoreClient": "Information", + "EventStore.Client.SingleNodeChannelSelector": "Warning" + } }, "Enrich": ["FromLogContext", "WithThreadId"], "WriteTo": [ diff --git a/test/EventStore.Client.Tests.Common/appsettings.json b/test/EventStore.Client.Tests.Common/appsettings.json index 78193ee2e..b3e5fa22f 100644 --- a/test/EventStore.Client.Tests.Common/appsettings.json +++ b/test/EventStore.Client.Tests.Common/appsettings.json @@ -1,9 +1,12 @@ { "Serilog": { - "MinimumLevel": { "Default": "Debug" }, - "Override": { - "Microsoft": "Warning", - "Grpc": "Information" + "MinimumLevel": { + "Default": "Debug", + "Override": { + "Microsoft": "Warning", + "Grpc": "Information", + "EventStore.Client.EventStoreClient": "Information" + } }, "Enrich": ["FromLogContext", "WithThreadId"], "WriteTo": [ diff --git a/test/EventStore.Client.UserManagement.Tests/enabling_a_user.cs b/test/EventStore.Client.UserManagement.Tests/enabling_a_user.cs index c57505660..79755e891 100644 --- a/test/EventStore.Client.UserManagement.Tests/enabling_a_user.cs +++ b/test/EventStore.Client.UserManagement.Tests/enabling_a_user.cs @@ -1,7 +1,8 @@ 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)); + public enabling_a_user(ITestOutputHelper output, InsecureClientTestFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); InsecureClientTestFixture Fixture { get; } From 7f215230c6e925d75d1d0786bbd095b3dff73d75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Silveira?= Date: Tue, 5 Dec 2023 17:55:44 +0100 Subject: [PATCH 09/22] refactored all streams client tests --- .../EnumerableTaskExtensions.cs | 4 +- .../ChannelBaseExtensions.cs | 17 +- src/EventStore.Client/ChannelCache.cs | 9 +- test/Directory.Build.props | 1 + .../{ => AppendToStream}/append_to_stream.cs | 215 +++++++------- .../append_to_stream_limits.cs | 3 +- .../Bugs/Issue_104.cs | 25 +- .../Bugs/Issue_2544.cs | 64 ++--- .../delete_stream_with_timeout.cs | 30 +- .../{ => DeleteStream}/soft_deleted_stream.cs | 176 ++++++------ .../EventStoreClientFixture.cs | 19 -- .../{ => ReadAll}/read_all_events_backward.cs | 51 ++-- .../{ => ReadAll}/read_enumeration_tests.cs | 24 +- .../read_events_linked_to_deleted_stream.cs | 68 +++++ .../{ => ReadStream}/read_stream_backward.cs | 98 +++---- .../read_stream_backward_messages.cs | 48 ++++ .../{ => ReadStream}/read_stream_forward.cs | 88 +++--- .../read_stream_forward_messages.cs | 94 ++++++ .../when_having_max_count_set_for_stream.cs | 125 ++++++++ .../Security/SecurityFixture.cs | 141 +++++---- .../all_stream_with_no_acl_security.cs | 60 ++-- .../Security/delete_stream_security.cs | 147 +++++----- .../Security/multiple_role_security.cs | 42 +-- .../overriden_system_stream_security.cs | 85 +++--- ...verriden_system_stream_security_for_all.cs | 66 ++--- .../overriden_user_stream_security.cs | 82 +++--- .../Security/read_all_security.cs | 31 +- .../Security/read_stream_meta_security.cs | 44 ++- .../Security/read_stream_security.cs | 166 ++++------- .../Security/stream_security_inheritance.cs | 229 ++++++--------- .../Security/subscribe_to_all_security.cs | 20 +- .../Security/subscribe_to_stream_security.cs | 77 ++--- .../Security/system_stream_security.cs | 168 +++++------ .../Security/write_stream_meta_security.cs | 58 ++-- .../Security/write_stream_security.cs | 61 ++-- .../{ => StreamMetadata}/stream_metadata.cs | 56 ++-- .../stream_metadata_with_timeout.cs | 28 +- .../{ => Subscriptions}/reconnection.cs | 2 - .../subscribe_resolve_link_to.cs | 66 ++--- .../{ => Subscriptions}/subscribe_to_all.cs | 75 ++--- .../subscribe_to_all_filtered.cs | 67 +++-- .../subscribe_to_all_filtered_live.cs | 59 ++-- ...subscribe_to_all_filtered_with_position.cs | 67 +++-- .../subscribe_to_all_live.cs | 88 +++--- .../subscribe_to_all_with_position.cs | 269 ++++++++++-------- .../subscribe_to_stream.cs | 89 +++--- .../subscribe_to_stream_live.cs | 57 ++-- .../subscribe_to_stream_with_revision.cs | 63 ++-- ...nd_to_stream_expected_version_no_stream.cs | 39 +-- .../append_to_stream_retry.cs | 71 ++--- ...to_stream_when_events_enumerator_throws.cs | 54 ++-- .../append_to_stream_with_timeout.cs | 71 +++-- .../appending_to_implicitly_created_stream.cs | 174 ++++++----- .../deleting_stream.cs | 54 ++-- .../is_json.cs | 22 +- .../read_all_backward_messages.cs | 22 +- .../read_all_events_forward.cs | 57 ++-- ...ts_forward_with_linkto_passed_max_count.cs | 86 +++--- .../read_all_forward_messages.cs | 24 +- .../read_all_with_timeout.cs | 18 +- .../read_events_linked_to_deleted_stream.cs | 80 ------ .../read_stream_backward_messages.cs | 51 ---- .../read_stream_forward_messages.cs | 99 ------- .../read_stream_with_timeout.cs | 20 +- .../sending_and_receiving_large_messages.cs | 38 +-- .../when_having_max_count_set_for_stream.cs | 129 --------- .../EventStore.Client.Tests.Common.csproj | 1 + .../Fixtures/EventStoreFixture.Helpers.cs | 3 +- .../Fixtures/EventStoreFixture.cs | 36 ++- .../XUnit/Categories.cs | 49 ++++ 70 files changed, 2277 insertions(+), 2543 deletions(-) rename {test/EventStore.Client.Tests.Common/Extensions => src/EventStore.Client.Common}/EnumerableTaskExtensions.cs (75%) rename test/EventStore.Client.Streams.Tests/{ => AppendToStream}/append_to_stream.cs (54%) rename test/EventStore.Client.Streams.Tests/{ => AppendToStream}/append_to_stream_limits.cs (94%) rename test/EventStore.Client.Streams.Tests/{ => DeleteStream}/delete_stream_with_timeout.cs (56%) rename test/EventStore.Client.Streams.Tests/{ => DeleteStream}/soft_deleted_stream.cs (64%) delete mode 100644 test/EventStore.Client.Streams.Tests/EventStoreClientFixture.cs rename test/EventStore.Client.Streams.Tests/{ => ReadAll}/read_all_events_backward.cs (53%) rename test/EventStore.Client.Streams.Tests/{ => ReadAll}/read_enumeration_tests.cs (65%) create mode 100644 test/EventStore.Client.Streams.Tests/ReadStream/read_events_linked_to_deleted_stream.cs rename test/EventStore.Client.Streams.Tests/{ => ReadStream}/read_stream_backward.cs (57%) create mode 100644 test/EventStore.Client.Streams.Tests/ReadStream/read_stream_backward_messages.cs rename test/EventStore.Client.Streams.Tests/{ => ReadStream}/read_stream_forward.cs (58%) create mode 100644 test/EventStore.Client.Streams.Tests/ReadStream/read_stream_forward_messages.cs create mode 100644 test/EventStore.Client.Streams.Tests/ReadStream/when_having_max_count_set_for_stream.cs rename test/EventStore.Client.Streams.Tests/{ => StreamMetadata}/stream_metadata.cs (69%) rename test/EventStore.Client.Streams.Tests/{ => StreamMetadata}/stream_metadata_with_timeout.cs (53%) rename test/EventStore.Client.Streams.Tests/{ => Subscriptions}/reconnection.cs (99%) rename test/EventStore.Client.Streams.Tests/{ => Subscriptions}/subscribe_resolve_link_to.cs (69%) rename test/EventStore.Client.Streams.Tests/{ => Subscriptions}/subscribe_to_all.cs (67%) rename test/EventStore.Client.Streams.Tests/{ => Subscriptions}/subscribe_to_all_filtered.cs (74%) rename test/EventStore.Client.Streams.Tests/{ => Subscriptions}/subscribe_to_all_filtered_live.cs (58%) rename test/EventStore.Client.Streams.Tests/{ => Subscriptions}/subscribe_to_all_filtered_with_position.cs (62%) rename test/EventStore.Client.Streams.Tests/{ => Subscriptions}/subscribe_to_all_live.cs (66%) rename test/EventStore.Client.Streams.Tests/{ => Subscriptions}/subscribe_to_all_with_position.cs (53%) rename test/EventStore.Client.Streams.Tests/{ => Subscriptions}/subscribe_to_stream.cs (71%) rename test/EventStore.Client.Streams.Tests/{ => Subscriptions}/subscribe_to_stream_live.cs (69%) rename test/EventStore.Client.Streams.Tests/{ => Subscriptions}/subscribe_to_stream_with_revision.cs (77%) delete mode 100644 test/EventStore.Client.Streams.Tests/read_events_linked_to_deleted_stream.cs delete mode 100644 test/EventStore.Client.Streams.Tests/read_stream_backward_messages.cs delete mode 100644 test/EventStore.Client.Streams.Tests/read_stream_forward_messages.cs delete mode 100644 test/EventStore.Client.Streams.Tests/when_having_max_count_set_for_stream.cs create mode 100644 test/EventStore.Client.Tests.Common/XUnit/Categories.cs diff --git a/test/EventStore.Client.Tests.Common/Extensions/EnumerableTaskExtensions.cs b/src/EventStore.Client.Common/EnumerableTaskExtensions.cs similarity index 75% rename from test/EventStore.Client.Tests.Common/Extensions/EnumerableTaskExtensions.cs rename to src/EventStore.Client.Common/EnumerableTaskExtensions.cs index fd62d7b4c..eb4517006 100644 --- a/test/EventStore.Client.Tests.Common/Extensions/EnumerableTaskExtensions.cs +++ b/src/EventStore.Client.Common/EnumerableTaskExtensions.cs @@ -1,8 +1,8 @@ using System.Diagnostics; -namespace EventStore.Client.Tests; +namespace EventStore.Client; -public static class EnumerableTaskExtensions { +static class EnumerableTaskExtensions { [DebuggerStepThrough] public static Task WhenAll(this IEnumerable source) => Task.WhenAll(source); diff --git a/src/EventStore.Client/ChannelBaseExtensions.cs b/src/EventStore.Client/ChannelBaseExtensions.cs index eb078ae2e..3edbf59fd 100644 --- a/src/EventStore.Client/ChannelBaseExtensions.cs +++ b/src/EventStore.Client/ChannelBaseExtensions.cs @@ -1,15 +1,10 @@ -using System; -using System.Threading.Tasks; using Grpc.Core; -namespace EventStore.Client { - internal static class ChannelBaseExtensions { - public static async ValueTask DisposeAsync(this ChannelBase channel) { - // for grpc.core, shutdown does the cleanup and the cast returns null - // for grpc.net shutdown does nothing and dispose does the cleanup - await channel.ShutdownAsync().ConfigureAwait(false); +namespace EventStore.Client; - (channel as IDisposable)?.Dispose(); - } +static class ChannelBaseExtensions { + public static async ValueTask DisposeAsync(this ChannelBase channel) { + await channel.ShutdownAsync().ConfigureAwait(false); + (channel as IDisposable)?.Dispose(); } -} +} \ No newline at end of file diff --git a/src/EventStore.Client/ChannelCache.cs b/src/EventStore.Client/ChannelCache.cs index 1ed172bc6..f61654cee 100644 --- a/src/EventStore.Client/ChannelCache.cs +++ b/src/EventStore.Client/ChannelCache.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Threading.Tasks; - +using System.Net; using TChannel = Grpc.Net.Client.GrpcChannel; namespace EventStore.Client { @@ -11,7 +6,7 @@ namespace EventStore.Client { // Deals with the disposal difference between grpc.net and grpc.core // Thread safe. internal class ChannelCache : - IDisposable, // for grpc.net we can dispose synchronously, but not for grpc.core + //IDisposable, // for grpc.net we can dispose synchronously, but not for grpc.core IAsyncDisposable { private readonly EventStoreClientSettings _settings; diff --git a/test/Directory.Build.props b/test/Directory.Build.props index 73a280b20..a4de0b3a7 100644 --- a/test/Directory.Build.props +++ b/test/Directory.Build.props @@ -25,6 +25,7 @@ + diff --git a/test/EventStore.Client.Streams.Tests/append_to_stream.cs b/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream.cs similarity index 54% rename from test/EventStore.Client.Streams.Tests/append_to_stream.cs rename to test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream.cs index 5ab7f9f02..2595b67ca 100644 --- a/test/EventStore.Client.Streams.Tests/append_to_stream.cs +++ b/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream.cs @@ -1,11 +1,11 @@ namespace EventStore.Client.Streams.Tests; -[Trait("Category", "Network")] -public class append_to_stream : IClassFixture { - readonly Fixture _fixture; - - public append_to_stream(Fixture fixture) => _fixture = fixture; +[Network] +public class append_to_stream : IClassFixture { + public append_to_stream(ITestOutputHelper output, EventStoreFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); + EventStoreFixture Fixture { get; } public static IEnumerable ExpectedVersionCreateStreamTestCases() { yield return new object?[] { StreamState.Any }; yield return new object?[] { StreamState.NoStream }; @@ -14,17 +14,17 @@ public class append_to_stream : IClassFixture { [Theory] [MemberData(nameof(ExpectedVersionCreateStreamTestCases))] public async Task appending_zero_events(StreamState expectedStreamState) { - var stream = $"{_fixture.GetStreamName()}_{expectedStreamState}"; + var stream = $"{Fixture.GetStreamName()}_{expectedStreamState}"; const int iterations = 2; for (var i = 0; i < iterations; i++) { - var writeResult = await _fixture.Client.AppendToStreamAsync(stream, expectedStreamState, Enumerable.Empty()); + var writeResult = await Fixture.Streams.AppendToStreamAsync(stream, expectedStreamState, Enumerable.Empty()); Assert.Equal(StreamRevision.None, writeResult.NextExpectedStreamRevision); } var ex = await Assert.ThrowsAsync( () => - _fixture.Client + Fixture.Streams .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, iterations) .ToArrayAsync().AsTask() ); @@ -35,17 +35,17 @@ public async Task appending_zero_events(StreamState expectedStreamState) { [Theory] [MemberData(nameof(ExpectedVersionCreateStreamTestCases))] public async Task appending_zero_events_again(StreamState expectedStreamState) { - var stream = $"{_fixture.GetStreamName()}_{expectedStreamState}"; + var stream = $"{Fixture.GetStreamName()}_{expectedStreamState}"; const int iterations = 2; for (var i = 0; i < iterations; i++) { - var writeResult = await _fixture.Client.AppendToStreamAsync(stream, expectedStreamState, Enumerable.Empty()); + var writeResult = await Fixture.Streams.AppendToStreamAsync(stream, expectedStreamState, Enumerable.Empty()); Assert.Equal(StreamRevision.None, writeResult.NextExpectedStreamRevision); } var ex = await Assert.ThrowsAsync( () => - _fixture.Client + Fixture.Streams .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, iterations) .ToArrayAsync().AsTask() ); @@ -56,17 +56,17 @@ public async Task appending_zero_events_again(StreamState expectedStreamState) { [Theory] [MemberData(nameof(ExpectedVersionCreateStreamTestCases))] public async Task create_stream_expected_version_on_first_write_if_does_not_exist(StreamState expectedStreamState) { - var stream = $"{_fixture.GetStreamName()}_{expectedStreamState}"; + var stream = $"{Fixture.GetStreamName()}_{expectedStreamState}"; - var writeResult = await _fixture.Client.AppendToStreamAsync( + var writeResult = await Fixture.Streams.AppendToStreamAsync( stream, expectedStreamState, - _fixture.CreateTestEvents(1) + Fixture.CreateTestEvents(1) ); Assert.Equal(new(0), writeResult.NextExpectedStreamRevision); - var count = await _fixture.Client.ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, 2) + var count = await Fixture.Streams.ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, 2) .CountAsync(); Assert.Equal(1, count); @@ -74,86 +74,84 @@ public async Task create_stream_expected_version_on_first_write_if_does_not_exis [Fact] public async Task multiple_idempotent_writes() { - var stream = _fixture.GetStreamName(); - var events = _fixture.CreateTestEvents(4).ToArray(); + var stream = Fixture.GetStreamName(); + var events = Fixture.CreateTestEvents(4).ToArray(); - var writeResult = await _fixture.Client.AppendToStreamAsync(stream, StreamState.Any, events); + var writeResult = await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, events); Assert.Equal(new(3), writeResult.NextExpectedStreamRevision); - writeResult = await _fixture.Client.AppendToStreamAsync(stream, StreamState.Any, events); + writeResult = await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, events); Assert.Equal(new(3), writeResult.NextExpectedStreamRevision); } [Fact] public async Task multiple_idempotent_writes_with_same_id_bug_case() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - var evnt = _fixture.CreateTestEvents().First(); + var evnt = Fixture.CreateTestEvents().First(); var events = new[] { evnt, evnt, evnt, evnt, evnt, evnt }; - var writeResult = await _fixture.Client.AppendToStreamAsync(stream, StreamState.Any, events); + var writeResult = await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, events); Assert.Equal(new(5), writeResult.NextExpectedStreamRevision); } [Fact] - 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(); + 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(); - var evnt = _fixture.CreateTestEvents().First(); + var evnt = Fixture.CreateTestEvents().First(); var events = new[] { evnt, evnt, evnt, evnt, evnt, evnt }; - var writeResult = await _fixture.Client.AppendToStreamAsync(stream, StreamState.Any, events); + var writeResult = await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, events); Assert.Equal(new(5), writeResult.NextExpectedStreamRevision); - writeResult = await _fixture.Client.AppendToStreamAsync(stream, StreamState.Any, events); + writeResult = await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, events); Assert.Equal(new(0), writeResult.NextExpectedStreamRevision); } [Fact] - 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(); + 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(); - var evnt = _fixture.CreateTestEvents().First(); + var evnt = Fixture.CreateTestEvents().First(); var events = new[] { evnt, evnt, evnt, evnt, evnt, evnt }; var streamRevision = StreamRevision.FromInt64(events.Length - 1); - var writeResult = await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, events); + var writeResult = await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); Assert.Equal(streamRevision, writeResult.NextExpectedStreamRevision); - writeResult = await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, events); + writeResult = await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); Assert.Equal(streamRevision, writeResult.NextExpectedStreamRevision); } [Fact] public async Task writing_with_correct_expected_version_to_deleted_stream_throws_stream_deleted() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - await _fixture.Client.TombstoneAsync(stream, StreamState.NoStream); + await Fixture.Streams.TombstoneAsync(stream, StreamState.NoStream); await Assert.ThrowsAsync( - () => _fixture.Client.AppendToStreamAsync( + () => Fixture.Streams.AppendToStreamAsync( stream, StreamState.NoStream, - _fixture.CreateTestEvents(1) + Fixture.CreateTestEvents(1) ) ); } [Fact] public async Task returns_log_position_when_writing() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - var result = await _fixture.Client.AppendToStreamAsync( + var result = await Fixture.Streams.AppendToStreamAsync( stream, StreamState.NoStream, - _fixture.CreateTestEvents(1) + Fixture.CreateTestEvents(1) ); Assert.True(0 < result.LogPosition.PreparePosition); @@ -162,35 +160,35 @@ public async Task returns_log_position_when_writing() { [Fact] public async Task writing_with_any_expected_version_to_deleted_stream_throws_stream_deleted() { - var stream = _fixture.GetStreamName(); - await _fixture.Client.TombstoneAsync(stream, StreamState.NoStream); + var stream = Fixture.GetStreamName(); + await Fixture.Streams.TombstoneAsync(stream, StreamState.NoStream); - await Assert.ThrowsAsync(() => _fixture.Client.AppendToStreamAsync(stream, StreamState.Any, _fixture.CreateTestEvents(1))); + await Assert.ThrowsAsync(() => Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, Fixture.CreateTestEvents(1))); } [Fact] public async Task writing_with_invalid_expected_version_to_deleted_stream_throws_stream_deleted() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - await _fixture.Client.TombstoneAsync(stream, StreamState.NoStream); + await Fixture.Streams.TombstoneAsync(stream, StreamState.NoStream); - await Assert.ThrowsAsync(() => _fixture.Client.AppendToStreamAsync(stream, new StreamRevision(5), _fixture.CreateTestEvents())); + await Assert.ThrowsAsync(() => Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(5), Fixture.CreateTestEvents())); } [Fact] public async Task append_with_correct_expected_version_to_existing_stream() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - var writeResult = await _fixture.Client.AppendToStreamAsync( + var writeResult = await Fixture.Streams.AppendToStreamAsync( stream, StreamState.NoStream, - _fixture.CreateTestEvents(1) + Fixture.CreateTestEvents(1) ); - writeResult = await _fixture.Client.AppendToStreamAsync( + writeResult = await Fixture.Streams.AppendToStreamAsync( stream, writeResult.NextExpectedStreamRevision, - _fixture.CreateTestEvents() + Fixture.CreateTestEvents() ); Assert.Equal(new(1), writeResult.NextExpectedStreamRevision); @@ -198,20 +196,20 @@ public async Task append_with_correct_expected_version_to_existing_stream() { [Fact] public async Task append_with_any_expected_version_to_existing_stream() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - var writeResult = await _fixture.Client.AppendToStreamAsync( + var writeResult = await Fixture.Streams.AppendToStreamAsync( stream, StreamState.NoStream, - _fixture.CreateTestEvents(1) + Fixture.CreateTestEvents(1) ); Assert.Equal(new(0), writeResult.NextExpectedStreamRevision); - writeResult = await _fixture.Client.AppendToStreamAsync( + writeResult = await Fixture.Streams.AppendToStreamAsync( stream, StreamState.Any, - _fixture.CreateTestEvents(1) + Fixture.CreateTestEvents(1) ); Assert.Equal(new(1), writeResult.NextExpectedStreamRevision); @@ -219,12 +217,12 @@ public async Task append_with_any_expected_version_to_existing_stream() { [Fact] public async Task appending_with_wrong_expected_version_to_existing_stream_throws_wrong_expected_version() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, _fixture.CreateTestEvents()); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents()); var ex = await Assert.ThrowsAsync( - () => _fixture.Client.AppendToStreamAsync(stream, new StreamRevision(999), _fixture.CreateTestEvents()) + () => Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(999), Fixture.CreateTestEvents()) ); Assert.Equal(new(0), ex.ActualStreamRevision); @@ -233,12 +231,12 @@ public async Task appending_with_wrong_expected_version_to_existing_stream_throw [Fact] public async Task appending_with_wrong_expected_version_to_existing_stream_returns_wrong_expected_version() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - var writeResult = await _fixture.Client.AppendToStreamAsync( + var writeResult = await Fixture.Streams.AppendToStreamAsync( stream, new StreamRevision(1), - _fixture.CreateTestEvents(), + Fixture.CreateTestEvents(), options => { options.ThrowOnAppendFailure = false; } ); @@ -249,58 +247,57 @@ public async Task appending_with_wrong_expected_version_to_existing_stream_retur [Fact] public async Task append_with_stream_exists_expected_version_to_existing_stream() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, _fixture.CreateTestEvents()); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents()); - await _fixture.Client.AppendToStreamAsync( + await Fixture.Streams.AppendToStreamAsync( stream, StreamState.StreamExists, - _fixture.CreateTestEvents() + Fixture.CreateTestEvents() ); } [Fact] public async Task append_with_stream_exists_expected_version_to_stream_with_multiple_events() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); for (var i = 0; i < 5; i++) - await _fixture.Client.AppendToStreamAsync(stream, StreamState.Any, _fixture.CreateTestEvents(1)); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, Fixture.CreateTestEvents(1)); - await _fixture.Client.AppendToStreamAsync( + await Fixture.Streams.AppendToStreamAsync( stream, StreamState.StreamExists, - _fixture.CreateTestEvents() + Fixture.CreateTestEvents() ); } [Fact] public async Task append_with_stream_exists_expected_version_if_metadata_stream_exists() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - await _fixture.Client.SetStreamMetadataAsync( + await Fixture.Streams.SetStreamMetadataAsync( stream, StreamState.Any, new(10, default) ); - await _fixture.Client.AppendToStreamAsync( + await Fixture.Streams.AppendToStreamAsync( stream, StreamState.StreamExists, - _fixture.CreateTestEvents() + Fixture.CreateTestEvents() ); } [Fact] - public async Task - appending_with_stream_exists_expected_version_and_stream_does_not_exist_throws_wrong_expected_version() { - var stream = _fixture.GetStreamName(); + public async Task appending_with_stream_exists_expected_version_and_stream_does_not_exist_throws_wrong_expected_version() { + var stream = Fixture.GetStreamName(); var ex = await Assert.ThrowsAsync( - () => _fixture.Client.AppendToStreamAsync( + () => Fixture.Streams.AppendToStreamAsync( stream, StreamState.StreamExists, - _fixture.CreateTestEvents() + Fixture.CreateTestEvents() ) ); @@ -308,14 +305,13 @@ public async Task } [Fact] - public async Task - appending_with_stream_exists_expected_version_and_stream_does_not_exist_returns_wrong_expected_version() { - var stream = _fixture.GetStreamName(); + public async Task appending_with_stream_exists_expected_version_and_stream_does_not_exist_returns_wrong_expected_version() { + var stream = Fixture.GetStreamName(); - var writeResult = await _fixture.Client.AppendToStreamAsync( + var writeResult = await Fixture.Streams.AppendToStreamAsync( stream, StreamState.StreamExists, - _fixture.CreateTestEvents(), + Fixture.CreateTestEvents(), options => { options.ThrowOnAppendFailure = false; } ); @@ -326,53 +322,53 @@ public async Task [Fact] public async Task appending_with_stream_exists_expected_version_to_hard_deleted_stream_throws_stream_deleted() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - await _fixture.Client.TombstoneAsync(stream, StreamState.NoStream); + await Fixture.Streams.TombstoneAsync(stream, StreamState.NoStream); await Assert.ThrowsAsync( - () => _fixture.Client.AppendToStreamAsync( + () => Fixture.Streams.AppendToStreamAsync( stream, StreamState.StreamExists, - _fixture.CreateTestEvents() + Fixture.CreateTestEvents() ) ); } [Fact] public async Task appending_with_stream_exists_expected_version_to_deleted_stream_throws_stream_deleted() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, _fixture.CreateTestEvents()); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents()); - await _fixture.Client.DeleteAsync(stream, StreamState.Any); + await Fixture.Streams.DeleteAsync(stream, StreamState.Any); await Assert.ThrowsAsync( - () => _fixture.Client.AppendToStreamAsync( + () => Fixture.Streams.AppendToStreamAsync( stream, StreamState.StreamExists, - _fixture.CreateTestEvents() + Fixture.CreateTestEvents() ) ); } [Fact] public async Task can_append_multiple_events_at_once() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - var writeResult = await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, _fixture.CreateTestEvents(100)); + var writeResult = await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents(100)); Assert.Equal(new(99), writeResult.NextExpectedStreamRevision); } [Fact] public async Task returns_failure_status_when_conditionally_appending_with_version_mismatch() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - var result = await _fixture.Client.ConditionalAppendToStreamAsync( + var result = await Fixture.Streams.ConditionalAppendToStreamAsync( stream, new StreamRevision(7), - _fixture.CreateTestEvents() + Fixture.CreateTestEvents() ); Assert.Equal( @@ -383,12 +379,12 @@ public async Task returns_failure_status_when_conditionally_appending_with_versi [Fact] public async Task returns_success_status_when_conditionally_appending_with_matching_version() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - var result = await _fixture.Client.ConditionalAppendToStreamAsync( + var result = await Fixture.Streams.ConditionalAppendToStreamAsync( stream, StreamState.Any, - _fixture.CreateTestEvents() + Fixture.CreateTestEvents() ); Assert.Equal( @@ -399,23 +395,18 @@ public async Task returns_success_status_when_conditionally_appending_with_match [Fact] public async Task returns_failure_status_when_conditionally_appending_to_a_deleted_stream() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, _fixture.CreateTestEvents()); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents()); - await _fixture.Client.TombstoneAsync(stream, StreamState.Any); + await Fixture.Streams.TombstoneAsync(stream, StreamState.Any); - var result = await _fixture.Client.ConditionalAppendToStreamAsync( + var result = await Fixture.Streams.ConditionalAppendToStreamAsync( stream, StreamState.Any, - _fixture.CreateTestEvents() + Fixture.CreateTestEvents() ); Assert.Equal(ConditionalWriteResult.StreamDeleted, result); } - - 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.Streams.Tests/append_to_stream_limits.cs b/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_limits.cs similarity index 94% rename from test/EventStore.Client.Streams.Tests/append_to_stream_limits.cs rename to test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_limits.cs index 5247ae9d9..c44f64860 100644 --- a/test/EventStore.Client.Streams.Tests/append_to_stream_limits.cs +++ b/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_limits.cs @@ -34,8 +34,7 @@ public async Task fails_when_size_exceeds_max_append_size() { } } -public class StreamLimitsFixture() - : EventStoreFixture(x => x.WithMaxAppendSize(MaxAppendSize)) { +public class StreamLimitsFixture() : EventStoreFixture(x => x.WithMaxAppendSize(MaxAppendSize)) { public const uint MaxAppendSize = 64; public (IEnumerable Events, uint size) CreateTestEventsUpToMaxSize(uint maxSize) { diff --git a/test/EventStore.Client.Streams.Tests/Bugs/Issue_104.cs b/test/EventStore.Client.Streams.Tests/Bugs/Issue_104.cs index 515fdf053..9e64ff0d7 100644 --- a/test/EventStore.Client.Streams.Tests/Bugs/Issue_104.cs +++ b/test/EventStore.Client.Streams.Tests/Bugs/Issue_104.cs @@ -1,21 +1,22 @@ -namespace EventStore.Client.Streams.Tests.Bugs; +namespace EventStore.Client.Streams.Tests.Bugs; -public class Issue_104 : IClassFixture { - readonly Fixture _fixture; +public class Issue_104 : IClassFixture { + public Issue_104(ITestOutputHelper output, EventStoreFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); - public Issue_104(Fixture fixture) => _fixture = fixture; + EventStoreFixture Fixture { get; } [Fact] public async Task subscription_does_not_send_checkpoint_reached_after_disposal() { - var streamName = _fixture.GetStreamName(); + var streamName = Fixture.GetStreamName(); var ignoredStreamName = $"ignore_{streamName}"; var subscriptionDisposed = new TaskCompletionSource(); var eventAppeared = new TaskCompletionSource(); var checkpointReachAfterDisposed = new TaskCompletionSource(); - await _fixture.Client.AppendToStreamAsync(streamName, StreamRevision.None, _fixture.CreateTestEvents()); + await Fixture.Streams.AppendToStreamAsync(streamName, StreamRevision.None, Fixture.CreateTestEvents()); - var subscription = await _fixture.Client.SubscribeToAllAsync( + var subscription = await Fixture.Streams.SubscribeToAllAsync( FromAll.Start, (_, _, _) => { eventAppeared.TrySetResult(true); @@ -42,20 +43,14 @@ public async Task subscription_does_not_send_checkpoint_reached_after_disposal() subscription.Dispose(); await subscriptionDisposed.Task; - await _fixture.Client.AppendToStreamAsync( + await Fixture.Streams.AppendToStreamAsync( ignoredStreamName, StreamRevision.None, - _fixture.CreateTestEvents(50) + Fixture.CreateTestEvents(50) ); var delay = Task.Delay(300); var result = await Task.WhenAny(delay, checkpointReachAfterDisposed.Task); Assert.Equal(delay, result); // iow 300ms have passed without seeing checkpointReachAfterDisposed } - - 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.Streams.Tests/Bugs/Issue_2544.cs b/test/EventStore.Client.Streams.Tests/Bugs/Issue_2544.cs index 696836a94..aabe78bdf 100644 --- a/test/EventStore.Client.Streams.Tests/Bugs/Issue_2544.cs +++ b/test/EventStore.Client.Streams.Tests/Bugs/Issue_2544.cs @@ -2,16 +2,10 @@ namespace EventStore.Client.Streams.Tests.Bugs; -public class Issue_2544 : IAsyncLifetime { - const int BatchSize = 18; - const int Batches = 4; - readonly TaskCompletionSource _completed; - readonly Fixture _fixture; - readonly Dictionary _seen; - - public Issue_2544(ITestOutputHelper outputHelper) { - _fixture = new(); - _fixture.CaptureLogs(outputHelper); +public class Issue_2544 : IClassFixture { + public Issue_2544(ITestOutputHelper output, EventStoreFixture fixture) { + Fixture = fixture.With(x => x.CaptureTestRun(output)); + _seen = Enumerable.Range(0, 1 + Batches * BatchSize) .Select(i => new StreamPosition((ulong)i)) .ToDictionary(r => r, _ => false); @@ -19,22 +13,25 @@ public Issue_2544(ITestOutputHelper outputHelper) { _completed = new(); } - public Task InitializeAsync() => _fixture.InitializeAsync(); + EventStoreFixture Fixture { get; } - public Task DisposeAsync() => _fixture.DisposeAsync(); + 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 }); + Enumerable.Range(0, 5).Select(i => new object[] { i }); [Theory] [MemberData(nameof(TestCases))] public async Task subscribe_to_stream(int iteration) { - var streamName = $"{_fixture.GetStreamName()}_{iteration}"; + var streamName = $"{Fixture.GetStreamName()}_{iteration}"; var startFrom = FromStream.Start; async Task Subscribe() => - await _fixture.Client + await Fixture.Streams .SubscribeToStreamAsync( streamName, startFrom, @@ -53,11 +50,11 @@ await _fixture.Client [Theory] [MemberData(nameof(TestCases))] public async Task subscribe_to_all(int iteration) { - var streamName = $"{_fixture.GetStreamName()}_{iteration}"; + var streamName = $"{Fixture.GetStreamName()}_{iteration}"; var startFrom = FromAll.Start; async Task Subscribe() => - await _fixture.Client + await Fixture.Streams .SubscribeToAllAsync( startFrom, (_, e, _) => EventAppeared(e, streamName, out startFrom), @@ -75,11 +72,11 @@ await _fixture.Client [Theory] [MemberData(nameof(TestCases))] public async Task subscribe_to_all_filtered(int iteration) { - var streamName = $"{_fixture.GetStreamName()}_{iteration}"; + var streamName = $"{Fixture.GetStreamName()}_{iteration}"; var startFrom = FromAll.Start; async Task Subscribe() => - await _fixture.Client + await Fixture.Streams .SubscribeToAllAsync( startFrom, (_, e, _) => EventAppeared(e, streamName, out startFrom), @@ -102,19 +99,19 @@ async Task AppendEvents(string streamName) { for (var i = 0; i < Batches; i++) { if (expectedRevision == StreamRevision.None) { - var result = await _fixture.Client.AppendToStreamAsync( + var result = await Fixture.Streams.AppendToStreamAsync( streamName, StreamState.NoStream, - _fixture.CreateTestEvents(BatchSize) + Fixture.CreateTestEvents(BatchSize) ); expectedRevision = result.NextExpectedStreamRevision; } else { - var result = await _fixture.Client.AppendToStreamAsync( + var result = await Fixture.Streams.AppendToStreamAsync( streamName, expectedRevision, - _fixture.CreateTestEvents(BatchSize) + Fixture.CreateTestEvents(BatchSize) ); expectedRevision = result.NextExpectedStreamRevision; @@ -123,7 +120,7 @@ async Task AppendEvents(string streamName) { await Task.Delay(TimeSpan.FromMilliseconds(10)); } - await _fixture.Client.AppendToStreamAsync( + await Fixture.Streams.AppendToStreamAsync( streamName, expectedRevision, new[] { @@ -170,22 +167,17 @@ Task EventAppeared(ResolvedEvent e, string streamName) { return Task.CompletedTask; } +} - public class Fixture : EventStoreClientFixture { - public Fixture() : base( - env: new() { - ["EVENTSTORE_LOG_LEVEL"] = "Verbose" - } - ) { } - - protected override Task Given() => - Client.SetStreamMetadataAsync( +public class IssueFixture : EventStoreFixture { + public IssueFixture() { + OnSetup = async () => { + await Streams.SetStreamMetadataAsync( SystemStreams.AllStream, StreamState.Any, new(acl: new(SystemRoles.All)), userCredentials: TestCredentials.Root ); - - protected override Task When() => Task.CompletedTask; + }; } } \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/delete_stream_with_timeout.cs b/test/EventStore.Client.Streams.Tests/DeleteStream/delete_stream_with_timeout.cs similarity index 56% rename from test/EventStore.Client.Streams.Tests/delete_stream_with_timeout.cs rename to test/EventStore.Client.Streams.Tests/DeleteStream/delete_stream_with_timeout.cs index 6028153df..475db2747 100644 --- a/test/EventStore.Client.Streams.Tests/delete_stream_with_timeout.cs +++ b/test/EventStore.Client.Streams.Tests/DeleteStream/delete_stream_with_timeout.cs @@ -2,18 +2,19 @@ namespace EventStore.Client.Streams.Tests; -[Trait("Category", "Network")] -public class deleting_stream_with_timeout : IClassFixture { - readonly Fixture _fixture; +[Network] +public class deleting_stream_with_timeout : IClassFixture { + public deleting_stream_with_timeout(ITestOutputHelper output, EventStoreFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); - public deleting_stream_with_timeout(Fixture fixture) => _fixture = fixture; + EventStoreFixture Fixture { get; } [Fact] public async Task any_stream_revision_delete_fails_when_operation_expired() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); var rpcException = await Assert.ThrowsAsync( () => - _fixture.Client.DeleteAsync(stream, StreamState.Any, TimeSpan.Zero) + Fixture.Streams.DeleteAsync(stream, StreamState.Any, TimeSpan.Zero) ); Assert.Equal(StatusCode.DeadlineExceeded, rpcException.StatusCode); @@ -21,11 +22,11 @@ public async Task any_stream_revision_delete_fails_when_operation_expired() { [Fact] public async Task stream_revision_delete_fails_when_operation_expired() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); var rpcException = await Assert.ThrowsAsync( () => - _fixture.Client.DeleteAsync(stream, new StreamRevision(0), TimeSpan.Zero) + Fixture.Streams.DeleteAsync(stream, new StreamRevision(0), TimeSpan.Zero) ); Assert.Equal(StatusCode.DeadlineExceeded, rpcException.StatusCode); @@ -33,10 +34,10 @@ public async Task stream_revision_delete_fails_when_operation_expired() { [Fact] public async Task any_stream_revision_tombstoning_fails_when_operation_expired() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); var rpcException = await Assert.ThrowsAsync( () => - _fixture.Client.TombstoneAsync(stream, StreamState.Any, TimeSpan.Zero) + Fixture.Streams.TombstoneAsync(stream, StreamState.Any, TimeSpan.Zero) ); Assert.Equal(StatusCode.DeadlineExceeded, rpcException.StatusCode); @@ -44,18 +45,13 @@ public async Task any_stream_revision_tombstoning_fails_when_operation_expired() [Fact] public async Task stream_revision_tombstoning_fails_when_operation_expired() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); var rpcException = await Assert.ThrowsAsync( () => - _fixture.Client.TombstoneAsync(stream, new StreamRevision(0), TimeSpan.Zero) + Fixture.Streams.TombstoneAsync(stream, new StreamRevision(0), TimeSpan.Zero) ); Assert.Equal(StatusCode.DeadlineExceeded, rpcException.StatusCode); } - - 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.Streams.Tests/soft_deleted_stream.cs b/test/EventStore.Client.Streams.Tests/DeleteStream/soft_deleted_stream.cs similarity index 64% rename from test/EventStore.Client.Streams.Tests/soft_deleted_stream.cs rename to test/EventStore.Client.Streams.Tests/DeleteStream/soft_deleted_stream.cs index d8e82cfeb..8b3ec1f35 100644 --- a/test/EventStore.Client.Streams.Tests/soft_deleted_stream.cs +++ b/test/EventStore.Client.Streams.Tests/DeleteStream/soft_deleted_stream.cs @@ -1,14 +1,12 @@ using System.Text.Json; -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests; -[Trait("Category", "LongRunning")] -public class deleted_stream : IClassFixture { - readonly JsonDocument _customMetadata; - readonly Fixture _fixture; +[LongRunning] - public deleted_stream(Fixture fixture) { - _fixture = fixture; +public class deleted_stream : IClassFixture { + public deleted_stream(ITestOutputHelper output, EventStoreFixture fixture) { + Fixture = fixture.With(x => x.CaptureTestRun(output)); var customMetadata = new Dictionary { ["key1"] = true, @@ -16,25 +14,28 @@ public deleted_stream(Fixture fixture) { ["key3"] = "some value" }; - _customMetadata = JsonDocument.Parse(JsonSerializer.Serialize(customMetadata)); + CustomMetadata = JsonDocument.Parse(JsonSerializer.Serialize(customMetadata)); } + EventStoreFixture Fixture { get; } + JsonDocument CustomMetadata { get; } + [Fact] public async Task reading_throws() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - var writeResult = await _fixture.Client.AppendToStreamAsync( + var writeResult = await Fixture.Streams.AppendToStreamAsync( stream, StreamState.NoStream, - _fixture.CreateTestEvents() + Fixture.CreateTestEvents() ); Assert.Equal(new(0), writeResult.NextExpectedStreamRevision); - await _fixture.Client.DeleteAsync(stream, writeResult.NextExpectedStreamRevision); + await Fixture.Streams.DeleteAsync(stream, writeResult.NextExpectedStreamRevision); await Assert.ThrowsAsync( - () => _fixture.Client.ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start) + () => Fixture.Streams.ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start) .ToArrayAsync().AsTask() ); } @@ -47,27 +48,27 @@ await Assert.ThrowsAsync( [Theory] [MemberData(nameof(RecreatingTestCases))] public async Task recreated_with_any_expected_version(StreamState expectedState, string name) { - var stream = $"{_fixture.GetStreamName()}_{name}"; + var stream = $"{Fixture.GetStreamName()}_{name}"; - var writeResult = await _fixture.Client.AppendToStreamAsync( + var writeResult = await Fixture.Streams.AppendToStreamAsync( stream, StreamState.NoStream, - _fixture.CreateTestEvents() + Fixture.CreateTestEvents() ); Assert.Equal(new(0), writeResult.NextExpectedStreamRevision); - await _fixture.Client.DeleteAsync(stream, writeResult.NextExpectedStreamRevision); + await Fixture.Streams.DeleteAsync(stream, writeResult.NextExpectedStreamRevision); - var events = _fixture.CreateTestEvents(3).ToArray(); + var events = Fixture.CreateTestEvents(3).ToArray(); - writeResult = await _fixture.Client.AppendToStreamAsync(stream, expectedState, events); + writeResult = await Fixture.Streams.AppendToStreamAsync(stream, expectedState, events); Assert.Equal(new(3), writeResult.NextExpectedStreamRevision); await Task.Delay(50); //TODO: This is a workaround until github issue #1744 is fixed - var actual = await _fixture.Client.ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start) + var actual = await Fixture.Streams.ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start) .Select(x => x.Event) .ToArrayAsync(); @@ -78,28 +79,28 @@ public async Task recreated_with_any_expected_version(StreamState expectedState, actual.Select(x => x.EventNumber) ); - var metadata = await _fixture.Client.GetStreamMetadataAsync(stream); + var metadata = await Fixture.Streams.GetStreamMetadataAsync(stream); Assert.Equal(new StreamPosition(1), metadata.Metadata.TruncateBefore); Assert.Equal(new StreamPosition(1), metadata.MetastreamRevision); } [Fact] public async Task recreated_with_expected_version() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - var writeResult = await _fixture.Client.AppendToStreamAsync( + var writeResult = await Fixture.Streams.AppendToStreamAsync( stream, StreamState.NoStream, - _fixture.CreateTestEvents() + Fixture.CreateTestEvents() ); Assert.Equal(new(0), writeResult.NextExpectedStreamRevision); - await _fixture.Client.DeleteAsync(stream, writeResult.NextExpectedStreamRevision); + await Fixture.Streams.DeleteAsync(stream, writeResult.NextExpectedStreamRevision); - var events = _fixture.CreateTestEvents(3).ToArray(); + var events = Fixture.CreateTestEvents(3).ToArray(); - writeResult = await _fixture.Client.AppendToStreamAsync( + writeResult = await Fixture.Streams.AppendToStreamAsync( stream, writeResult.NextExpectedStreamRevision, events @@ -109,7 +110,7 @@ public async Task recreated_with_expected_version() { await Task.Delay(50); //TODO: This is a workaround until github issue #1744 is fixed - var actual = await _fixture.Client.ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start) + var actual = await Fixture.Streams.ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start) .Select(x => x.Event) .ToArrayAsync(); @@ -120,7 +121,7 @@ public async Task recreated_with_expected_version() { actual.Select(x => x.EventNumber) ); - var metadata = await _fixture.Client.GetStreamMetadataAsync(stream); + var metadata = await Fixture.Streams.GetStreamMetadataAsync(stream); Assert.Equal(new StreamPosition(1), metadata.Metadata.TruncateBefore); Assert.Equal(new StreamPosition(1), metadata.MetastreamRevision); } @@ -128,12 +129,12 @@ public async Task recreated_with_expected_version() { [Fact] public async Task recreated_preserves_metadata_except_truncate_before() { const int count = 2; - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - var writeResult = await _fixture.Client.AppendToStreamAsync( + var writeResult = await Fixture.Streams.AppendToStreamAsync( stream, StreamState.NoStream, - _fixture.CreateTestEvents(count) + Fixture.CreateTestEvents(count) ); Assert.Equal(new(1), writeResult.NextExpectedStreamRevision); @@ -142,10 +143,10 @@ public async Task recreated_preserves_metadata_except_truncate_before() { acl: new(deleteRole: "some-role"), maxCount: 100, truncateBefore: new StreamPosition(long.MaxValue), // 1 less than End - customMetadata: _customMetadata + customMetadata: CustomMetadata ); - writeResult = await _fixture.Client.SetStreamMetadataAsync( + writeResult = await Fixture.Streams.SetStreamMetadataAsync( stream, StreamState.NoStream, streamMetadata @@ -153,13 +154,13 @@ public async Task recreated_preserves_metadata_except_truncate_before() { Assert.Equal(new(0), writeResult.NextExpectedStreamRevision); - var events = _fixture.CreateTestEvents(3).ToArray(); + var events = Fixture.CreateTestEvents(3).ToArray(); - await _fixture.Client.AppendToStreamAsync(stream, new StreamRevision(1), events); + await Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(1), events); await Task.Delay(500); //TODO: This is a workaround until github issue #1744 is fixed - var actual = await _fixture.Client.ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start) + var actual = await Fixture.Streams.ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start) .Select(x => x.Event) .ToArrayAsync(); @@ -179,30 +180,30 @@ public async Task recreated_preserves_metadata_except_truncate_before() { streamMetadata.CustomMetadata ); - var metadataResult = await _fixture.Client.GetStreamMetadataAsync(stream); + var metadataResult = await Fixture.Streams.GetStreamMetadataAsync(stream); Assert.Equal(new StreamPosition(1), metadataResult.MetastreamRevision); Assert.Equal(expected, metadataResult.Metadata); } [Fact] public async Task can_be_hard_deleted() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); var writeResult = - await _fixture.Client.AppendToStreamAsync( + await Fixture.Streams.AppendToStreamAsync( stream, StreamState.NoStream, - _fixture.CreateTestEvents(2) + Fixture.CreateTestEvents(2) ); Assert.Equal(new(1), writeResult.NextExpectedStreamRevision); - await _fixture.Client.DeleteAsync(stream, new StreamRevision(1)); + await Fixture.Streams.DeleteAsync(stream, new StreamRevision(1)); - await _fixture.Client.TombstoneAsync(stream, StreamState.Any); + await Fixture.Streams.TombstoneAsync(stream, StreamState.Any); var ex = await Assert.ThrowsAsync( - () => _fixture.Client.ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start) + () => Fixture.Streams.ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start) .ToArrayAsync().AsTask() ); @@ -210,69 +211,71 @@ await _fixture.Client.AppendToStreamAsync( ex = await Assert.ThrowsAsync( () - => _fixture.Client.GetStreamMetadataAsync(stream) + => Fixture.Streams.GetStreamMetadataAsync(stream) ); Assert.Equal(SystemStreams.MetastreamOf(stream), ex.Stream); - await Assert.ThrowsAsync(() => _fixture.Client.AppendToStreamAsync(stream, StreamState.Any, _fixture.CreateTestEvents())); + await Assert.ThrowsAsync( + () => Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, Fixture.CreateTestEvents()) + ); } [Fact] public async Task allows_recreating_for_first_write_only_throws_wrong_expected_version() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); var writeResult = - await _fixture.Client.AppendToStreamAsync( + await Fixture.Streams.AppendToStreamAsync( stream, StreamState.NoStream, - _fixture.CreateTestEvents(2) + Fixture.CreateTestEvents(2) ); Assert.Equal(new(1), writeResult.NextExpectedStreamRevision); - await _fixture.Client.DeleteAsync(stream, new StreamRevision(1)); + await Fixture.Streams.DeleteAsync(stream, new StreamRevision(1)); - writeResult = await _fixture.Client.AppendToStreamAsync( + writeResult = await Fixture.Streams.AppendToStreamAsync( stream, StreamState.NoStream, - _fixture.CreateTestEvents(3) + Fixture.CreateTestEvents(3) ); Assert.Equal(new(4), writeResult.NextExpectedStreamRevision); await Assert.ThrowsAsync( - () => _fixture.Client.AppendToStreamAsync( + () => Fixture.Streams.AppendToStreamAsync( stream, StreamState.NoStream, - _fixture.CreateTestEvents() + Fixture.CreateTestEvents() ) ); } [Fact] public async Task allows_recreating_for_first_write_only_returns_wrong_expected_version() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); var writeResult = - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, _fixture.CreateTestEvents(2)); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents(2)); Assert.Equal(new(1), writeResult.NextExpectedStreamRevision); - await _fixture.Client.DeleteAsync(stream, new StreamRevision(1)); + await Fixture.Streams.DeleteAsync(stream, new StreamRevision(1)); - writeResult = await _fixture.Client.AppendToStreamAsync( + writeResult = await Fixture.Streams.AppendToStreamAsync( stream, StreamState.NoStream, - _fixture.CreateTestEvents(3) + Fixture.CreateTestEvents(3) ); Assert.Equal(new(4), writeResult.NextExpectedStreamRevision); - var wrongExpectedVersionResult = await _fixture.Client.AppendToStreamAsync( + var wrongExpectedVersionResult = await Fixture.Streams.AppendToStreamAsync( stream, StreamState.NoStream, - _fixture.CreateTestEvents(), + Fixture.CreateTestEvents(), options => options.ThrowOnAppendFailure = false ); @@ -281,31 +284,31 @@ public async Task allows_recreating_for_first_write_only_returns_wrong_expected_ [Fact] public async Task appends_multiple_writes_expected_version_any() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); var writeResult = - await _fixture.Client.AppendToStreamAsync( + await Fixture.Streams.AppendToStreamAsync( stream, StreamState.NoStream, - _fixture.CreateTestEvents(2) + Fixture.CreateTestEvents(2) ); Assert.Equal(new(1), writeResult.NextExpectedStreamRevision); - await _fixture.Client.DeleteAsync(stream, new StreamRevision(1)); + await Fixture.Streams.DeleteAsync(stream, new StreamRevision(1)); - var firstEvents = _fixture.CreateTestEvents(3).ToArray(); - var secondEvents = _fixture.CreateTestEvents(2).ToArray(); + var firstEvents = Fixture.CreateTestEvents(3).ToArray(); + var secondEvents = Fixture.CreateTestEvents(2).ToArray(); - writeResult = await _fixture.Client.AppendToStreamAsync(stream, StreamState.Any, firstEvents); + writeResult = await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, firstEvents); Assert.Equal(new(4), writeResult.NextExpectedStreamRevision); - writeResult = await _fixture.Client.AppendToStreamAsync(stream, StreamState.Any, secondEvents); + writeResult = await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, secondEvents); Assert.Equal(new(6), writeResult.NextExpectedStreamRevision); - var actual = await _fixture.Client.ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start) + var actual = await Fixture.Streams.ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start) .Select(x => x.Event) .ToArrayAsync(); @@ -315,7 +318,7 @@ await _fixture.Client.AppendToStreamAsync( actual.Select(x => x.EventNumber) ); - var metadataResult = await _fixture.Client.GetStreamMetadataAsync(stream); + var metadataResult = await Fixture.Streams.GetStreamMetadataAsync(stream); Assert.Equal(new StreamPosition(2), metadataResult.Metadata.TruncateBefore); Assert.Equal(new StreamPosition(1), metadataResult.MetastreamRevision); @@ -323,16 +326,16 @@ await _fixture.Client.AppendToStreamAsync( [Fact] public async Task recreated_on_empty_when_metadata_set() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); var streamMetadata = new StreamMetadata( acl: new(deleteRole: "some-role"), maxCount: 100, truncateBefore: new StreamPosition(0), - customMetadata: _customMetadata + customMetadata: CustomMetadata ); - var writeResult = await _fixture.Client.SetStreamMetadataAsync( + var writeResult = await Fixture.Streams.SetStreamMetadataAsync( stream, StreamState.NoStream, streamMetadata @@ -347,7 +350,7 @@ public async Task recreated_on_empty_when_metadata_set() { Assert.Equal(new(0), writeResult.NextExpectedStreamRevision); await Assert.ThrowsAsync( - () => _fixture.Client + () => Fixture.Streams .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start) .ToArrayAsync().AsTask() ); @@ -361,7 +364,7 @@ await Assert.ThrowsAsync( streamMetadata.CustomMetadata ); - var metadataResult = await _fixture.Client.GetStreamMetadataAsync(stream); + var metadataResult = await Fixture.Streams.GetStreamMetadataAsync(stream); Assert.Equal(new StreamPosition(0), metadataResult.MetastreamRevision); Assert.Equal(expected, metadataResult.Metadata); } @@ -369,25 +372,25 @@ await Assert.ThrowsAsync( [Fact] public async Task recreated_on_non_empty_when_metadata_set() { const int count = 2; - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); var streamMetadata = new StreamMetadata( acl: new(deleteRole: "some-role"), maxCount: 100, - customMetadata: _customMetadata + customMetadata: CustomMetadata ); - var writeResult = await _fixture.Client.AppendToStreamAsync( + var writeResult = await Fixture.Streams.AppendToStreamAsync( stream, StreamState.NoStream, - _fixture.CreateTestEvents(count) + Fixture.CreateTestEvents(count) ); Assert.Equal(new(1), writeResult.NextExpectedStreamRevision); - await _fixture.Client.DeleteAsync(stream, writeResult.NextExpectedStreamRevision); + await Fixture.Streams.DeleteAsync(stream, writeResult.NextExpectedStreamRevision); - writeResult = await _fixture.Client.SetStreamMetadataAsync( + writeResult = await Fixture.Streams.SetStreamMetadataAsync( stream, new StreamRevision(0), streamMetadata @@ -403,13 +406,13 @@ public async Task recreated_on_non_empty_when_metadata_set() { // truncated events can be read await Task.Delay(200); - var actual = await _fixture.Client + var actual = await Fixture.Streams .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start) .ToArrayAsync(); Assert.Empty(actual); - var metadataResult = await _fixture.Client.GetStreamMetadataAsync(stream); + var metadataResult = await Fixture.Streams.GetStreamMetadataAsync(stream); var expected = new StreamMetadata( streamMetadata.MaxCount, streamMetadata.MaxAge, @@ -421,9 +424,4 @@ public async Task recreated_on_non_empty_when_metadata_set() { Assert.Equal(expected, metadataResult.Metadata); } - - 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.Streams.Tests/EventStoreClientFixture.cs b/test/EventStore.Client.Streams.Tests/EventStoreClientFixture.cs deleted file mode 100644 index bb8c322cc..000000000 --- a/test/EventStore.Client.Streams.Tests/EventStoreClientFixture.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace EventStore.Client.Streams.Tests; - -public abstract class EventStoreClientFixture : EventStoreClientFixtureBase { - protected EventStoreClientFixture( - EventStoreClientSettings? settings = null, - Dictionary? env = null, bool noDefaultCredentials = false - ) - : base(settings, env, noDefaultCredentials) => - Client = new(Settings); - - public EventStoreClient Client { get; } - - protected override async Task OnServerUpAsync() => await Client.WarmUp(); - - public override async Task DisposeAsync() { - await Client.DisposeAsync(); - await base.DisposeAsync(); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/read_all_events_backward.cs b/test/EventStore.Client.Streams.Tests/ReadAll/read_all_events_backward.cs similarity index 53% rename from test/EventStore.Client.Streams.Tests/read_all_events_backward.cs rename to test/EventStore.Client.Streams.Tests/ReadAll/read_all_events_backward.cs index bd571b281..312c2464d 100644 --- a/test/EventStore.Client.Streams.Tests/read_all_events_backward.cs +++ b/test/EventStore.Client.Streams.Tests/ReadAll/read_all_events_backward.cs @@ -1,34 +1,34 @@ -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests; -[Trait("Category", "LongRunning")] -public class read_all_events_backward : IClassFixture { - const string Stream = "stream"; - readonly Fixture _fixture; +[LongRunning] +public class read_all_events_backward : IClassFixture { + public read_all_events_backward(ITestOutputHelper output, ReadAllEventsBackward fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); - public read_all_events_backward(Fixture fixture) => _fixture = fixture; + ReadAllEventsBackward Fixture { get; } [Fact] public async Task return_empty_if_reading_from_start() { - var count = await _fixture.Client.ReadAllAsync(Direction.Backwards, Position.Start, 1).CountAsync(); + var count = await Fixture.Streams.ReadAllAsync(Direction.Backwards, Position.Start, 1).CountAsync(); Assert.Equal(0, count); } [Fact] public async Task return_partial_slice_if_not_enough_events() { - var events = await _fixture.Client.ReadAllAsync(Direction.Backwards, Position.End, _fixture.Events.Length * 2) + var events = await Fixture.Streams.ReadAllAsync(Direction.Backwards, Position.End, Fixture.Events.Length * 2) .ToArrayAsync(); - Assert.True(events.Length < _fixture.Events.Length * 2); + Assert.True(events.Length < Fixture.Events.Length * 2); } [Fact] public async Task return_events_in_reversed_order_compared_to_written() { - var events = await _fixture.Client.ReadAllAsync(Direction.Backwards, Position.End, _fixture.Events.Length) + var events = await Fixture.Streams.ReadAllAsync(Direction.Backwards, Position.End, Fixture.Events.Length) .ToArrayAsync(); Assert.True( EventDataComparer.Equal( - _fixture.Events.Reverse().ToArray(), + Fixture.Events.Reverse().ToArray(), events.AsResolvedTestEvents().ToArray() ) ); @@ -36,13 +36,13 @@ public async Task return_events_in_reversed_order_compared_to_written() { [Fact] public async Task return_single_event() { - var events = await _fixture.Client.ReadAllAsync(Direction.Backwards, Position.End, 1) + var events = await Fixture.Streams.ReadAllAsync(Direction.Backwards, Position.End, 1) .ToArrayAsync(); var actualEvent = Assert.Single(events.AsResolvedTestEvents()); Assert.True( EventDataComparer.Equal( - _fixture.Events.Last(), + Fixture.Events.Last(), actualEvent ) ); @@ -59,16 +59,18 @@ public async Task return_single_event() { [Fact] public async Task max_count_is_respected() { - var maxCount = _fixture.Events.Length / 2; - var events = await _fixture.Client.ReadAllAsync(Direction.Backwards, Position.End, maxCount) - .Take(_fixture.Events.Length) + var maxCount = Fixture.Events.Length / 2; + var events = await Fixture.Streams.ReadAllAsync(Direction.Backwards, Position.End, maxCount) + .Take(Fixture.Events.Length) .ToArrayAsync(); Assert.Equal(maxCount, events.Length); } +} - public class Fixture : EventStoreClientFixture { - public Fixture() => +public class ReadAllEventsBackward : EventStoreFixture { + public ReadAllEventsBackward() { + OnSetup = async () => { Events = Enumerable .Concat( CreateTestEvents(20), @@ -76,19 +78,18 @@ public Fixture() => ) .ToArray(); - public EventData[] Events { get; } + var streamName = GetStreamName(); - protected override async Task Given() { - var result = await Client.SetStreamMetadataAsync( + var result = await Streams.SetStreamMetadataAsync( SystemStreams.AllStream, StreamState.NoStream, new(acl: new(SystemRoles.All)), userCredentials: TestCredentials.Root ); - await Client.AppendToStreamAsync(Stream, StreamState.NoStream, Events); - } - - protected override Task When() => Task.CompletedTask; + await Streams.AppendToStreamAsync(streamName, StreamState.NoStream, Events); + }; } + + public EventData[] Events { get; private set; } = Array.Empty(); } \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/read_enumeration_tests.cs b/test/EventStore.Client.Streams.Tests/ReadAll/read_enumeration_tests.cs similarity index 65% rename from test/EventStore.Client.Streams.Tests/read_enumeration_tests.cs rename to test/EventStore.Client.Streams.Tests/ReadAll/read_enumeration_tests.cs index 9e9f22847..9ac925afd 100644 --- a/test/EventStore.Client.Streams.Tests/read_enumeration_tests.cs +++ b/test/EventStore.Client.Streams.Tests/ReadAll/read_enumeration_tests.cs @@ -1,14 +1,15 @@ -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests; -[Trait("Category", "Network")] -public class read_enumeration_tests : IClassFixture { - readonly Fixture _fixture; +[Network] +public class read_enumeration_tests : IClassFixture { + public read_enumeration_tests(ITestOutputHelper output, EventStoreFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); - public read_enumeration_tests(Fixture fixture) => _fixture = fixture; + EventStoreFixture Fixture { get; } [Fact] public async Task all_referencing_messages_twice_does_not_throw() { - var result = _fixture.Client.ReadAllAsync( + var result = Fixture.Streams.ReadAllAsync( Direction.Forwards, Position.Start, 32, @@ -21,7 +22,7 @@ public async Task all_referencing_messages_twice_does_not_throw() { [Fact] public async Task all_enumerating_messages_twice_throws() { - var result = _fixture.Client.ReadAllAsync( + var result = Fixture.Streams.ReadAllAsync( Direction.Forwards, Position.Start, 32, @@ -38,7 +39,7 @@ await result.Messages.ToArrayAsync() [Fact] public async Task referencing_messages_twice_does_not_throw() { - var result = _fixture.Client.ReadStreamAsync( + var result = Fixture.Streams.ReadStreamAsync( Direction.Forwards, "$users", StreamPosition.Start, @@ -52,7 +53,7 @@ public async Task referencing_messages_twice_does_not_throw() { [Fact] public async Task enumerating_messages_twice_throws() { - var result = _fixture.Client.ReadStreamAsync( + var result = Fixture.Streams.ReadStreamAsync( Direction.Forwards, "$users", StreamPosition.Start, @@ -67,9 +68,4 @@ await Assert.ThrowsAsync( await result.Messages.ToArrayAsync() ); } - - 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.Streams.Tests/ReadStream/read_events_linked_to_deleted_stream.cs b/test/EventStore.Client.Streams.Tests/ReadStream/read_events_linked_to_deleted_stream.cs new file mode 100644 index 000000000..955dd31cc --- /dev/null +++ b/test/EventStore.Client.Streams.Tests/ReadStream/read_events_linked_to_deleted_stream.cs @@ -0,0 +1,68 @@ +using System.Text; + +namespace EventStore.Client.Streams.Tests; + +public abstract class read_events_linked_to_deleted_stream(ReadEventsLinkedToDeletedStreamFixture fixture) { + ReadEventsLinkedToDeletedStreamFixture Fixture { get; } = fixture; + + [Fact] + public void one_event_is_read() => Assert.Single(Fixture.Events ?? Array.Empty()); + + [Fact] + public void the_linked_event_is_not_resolved() => Assert.Null(Fixture.Events![0].Event); + + [Fact] + public void the_link_event_is_included() => Assert.NotNull(Fixture.Events![0].OriginalEvent); + + [Fact] + public void the_event_is_not_resolved() => Assert.False(Fixture.Events![0].IsResolved); + + public class @forwards(ReadEventsLinkedToDeletedStreamFixture fixture) + : read_events_linked_to_deleted_stream(fixture), IClassFixture { + + public class CustomFixture() : ReadEventsLinkedToDeletedStreamFixture(Direction.Forwards); + } + + public class @backwards(ReadEventsLinkedToDeletedStreamFixture fixture) + : read_events_linked_to_deleted_stream(fixture), IClassFixture { + + public class CustomFixture() : ReadEventsLinkedToDeletedStreamFixture(Direction.Backwards); + } +} + +public abstract class ReadEventsLinkedToDeletedStreamFixture : EventStoreFixture { + 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, + new[] { + new EventData( + Uuid.NewUuid(), + SystemEventTypes.LinkTo, + Encoding.UTF8.GetBytes($"0@{DeletedStream}"), + Array.Empty(), + Constants.Metadata.ContentTypes.ApplicationOctetStream + ) + } + ); + + await Streams.DeleteAsync(DeletedStream, StreamState.Any); + + Events = await Streams.ReadStreamAsync( + direction, + LinkedStream, + StreamPosition.Start, + 1, + true + ).ToArrayAsync(); + }; + } + + public ResolvedEvent[]? Events { get; private set; } +} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/read_stream_backward.cs b/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_backward.cs similarity index 57% rename from test/EventStore.Client.Streams.Tests/read_stream_backward.cs rename to test/EventStore.Client.Streams.Tests/ReadStream/read_stream_backward.cs index 56277881b..7a3d31eee 100644 --- a/test/EventStore.Client.Streams.Tests/read_stream_backward.cs +++ b/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_backward.cs @@ -1,19 +1,20 @@ -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests; -[Trait("Category", "Network")] -public class read_stream_backward : IClassFixture { - readonly Fixture _fixture; +[Network] +public class read_stream_backward : IClassFixture { + public read_stream_backward(ITestOutputHelper output, EventStoreFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); - public read_stream_backward(Fixture fixture) => _fixture = fixture; + EventStoreFixture Fixture { get; } [Theory] [InlineData(0)] public async Task count_le_equal_zero_throws(long maxCount) { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); var ex = await Assert.ThrowsAsync( () => - _fixture.Client.ReadStreamAsync(Direction.Backwards, stream, StreamPosition.Start, maxCount) + Fixture.Streams.ReadStreamAsync(Direction.Backwards, stream, StreamPosition.Start, maxCount) .ToArrayAsync().AsTask() ); @@ -22,10 +23,10 @@ public async Task count_le_equal_zero_throws(long maxCount) { [Fact] public async Task stream_does_not_exist_throws() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); var ex = await Assert.ThrowsAsync( - () => _fixture.Client + () => Fixture.Streams .ReadStreamAsync(Direction.Backwards, stream, StreamPosition.End, 1) .ToArrayAsync().AsTask() ); @@ -35,9 +36,9 @@ public async Task stream_does_not_exist_throws() { [Fact] public async Task stream_does_not_exist_can_be_checked() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - var result = _fixture.Client.ReadStreamAsync(Direction.Backwards, stream, StreamPosition.End, 1); + var result = Fixture.Streams.ReadStreamAsync(Direction.Backwards, stream, StreamPosition.End, 1); var state = await result.ReadState; Assert.Equal(ReadState.StreamNotFound, state); @@ -45,12 +46,12 @@ public async Task stream_does_not_exist_can_be_checked() { [Fact] public async Task stream_deleted_throws() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - await _fixture.Client.TombstoneAsync(stream, StreamState.NoStream); + await Fixture.Streams.TombstoneAsync(stream, StreamState.NoStream); var ex = await Assert.ThrowsAsync( - () => _fixture.Client + () => Fixture.Streams .ReadStreamAsync(Direction.Backwards, stream, StreamPosition.End, 1) .ToArrayAsync().AsTask() ); @@ -62,13 +63,13 @@ public async Task stream_deleted_throws() { [InlineData("small_events", 10, 1)] [InlineData("large_events", 2, 1_000_000)] public async Task returns_events_in_reversed_order(string suffix, int count, int metadataSize) { - var stream = $"{_fixture.GetStreamName()}_{suffix}"; + var stream = $"{Fixture.GetStreamName()}_{suffix}"; - var expected = _fixture.CreateTestEvents(count, metadataSize: metadataSize).ToArray(); + var expected = Fixture.CreateTestEvents(count, metadataSize: metadataSize).ToArray(); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, expected); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, expected); - var actual = await _fixture.Client + var actual = await Fixture.Streams .ReadStreamAsync(Direction.Backwards, stream, StreamPosition.End, expected.Length) .Select(x => x.Event).ToArrayAsync(); @@ -82,15 +83,14 @@ public async Task returns_events_in_reversed_order(string suffix, int count, int [Fact] public async Task be_able_to_read_single_event_from_arbitrary_position() { - var stream = _fixture.GetStreamName(); - - var events = _fixture.CreateTestEvents(10).ToArray(); + var stream = Fixture.GetStreamName(); + var events = Fixture.CreateTestEvents(10).ToArray(); var expected = events[7]; - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - var actual = await _fixture.Client.ReadStreamAsync(Direction.Backwards, stream, new(7), 1) + var actual = await Fixture.Streams.ReadStreamAsync(Direction.Backwards, stream, new(7), 1) .Select(x => x.Event) .SingleAsync(); @@ -99,13 +99,13 @@ public async Task be_able_to_read_single_event_from_arbitrary_position() { [Fact] public async Task be_able_to_read_from_arbitrary_position() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - var events = _fixture.CreateTestEvents(10).ToArray(); + var events = Fixture.CreateTestEvents(10).ToArray(); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - var actual = await _fixture.Client.ReadStreamAsync(Direction.Backwards, stream, new(3), 2) + var actual = await Fixture.Streams.ReadStreamAsync(Direction.Backwards, stream, new(3), 2) .Select(x => x.Event) .ToArrayAsync(); @@ -114,13 +114,13 @@ public async Task be_able_to_read_from_arbitrary_position() { [Fact] public async Task be_able_to_read_first_event() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - var testEvents = _fixture.CreateTestEvents(10).ToArray(); + var testEvents = Fixture.CreateTestEvents(10).ToArray(); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, testEvents); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, testEvents); - var events = await _fixture.Client.ReadStreamAsync(Direction.Backwards, stream, StreamPosition.Start, 1) + var events = await Fixture.Streams.ReadStreamAsync(Direction.Backwards, stream, StreamPosition.Start, 1) .Select(x => x.Event) .ToArrayAsync(); @@ -130,13 +130,12 @@ public async Task be_able_to_read_first_event() { [Fact] public async Task be_able_to_read_last_event() { - var stream = _fixture.GetStreamName(); - - var testEvents = _fixture.CreateTestEvents(10).ToArray(); + var stream = Fixture.GetStreamName(); + var testEvents = Fixture.CreateTestEvents(10).ToArray(); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, testEvents); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, testEvents); - var events = await _fixture.Client.ReadStreamAsync(Direction.Backwards, stream, StreamPosition.End, 1) + var events = await Fixture.Streams.ReadStreamAsync(Direction.Backwards, stream, StreamPosition.End, 1) .Select(x => x.Event) .ToArrayAsync(); @@ -146,17 +145,18 @@ public async Task be_able_to_read_last_event() { [Fact] public async Task max_count_is_respected() { - var streamName = _fixture.GetStreamName(); - const int count = 20; - const long maxCount = count / 2; + const int count = 20; + const long maxCount = count / 2; + + var streamName = Fixture.GetStreamName(); - await _fixture.Client.AppendToStreamAsync( + await Fixture.Streams.AppendToStreamAsync( streamName, StreamState.NoStream, - _fixture.CreateTestEvents(count) + Fixture.CreateTestEvents(count) ); - var events = await _fixture.Client + var events = await Fixture.Streams .ReadStreamAsync(Direction.Backwards, streamName, StreamPosition.End, maxCount) .Take(count) .ToArrayAsync(); @@ -169,13 +169,12 @@ public async Task populates_log_position_of_event() { if (EventStoreTestServer.Version.Major < 22) return; - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); + var events = Fixture.CreateTestEvents(1).ToArray(); - var events = _fixture.CreateTestEvents(1).ToArray(); + var writeResult = await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - var writeResult = await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, events); - - var actual = await _fixture.Client.ReadStreamAsync(Direction.Backwards, stream, StreamPosition.End, 1) + var actual = await Fixture.Streams.ReadStreamAsync(Direction.Backwards, stream, StreamPosition.End, 1) .Select(x => x.Event) .ToArrayAsync(); @@ -183,9 +182,4 @@ public async Task populates_log_position_of_event() { Assert.Equal(writeResult.LogPosition.PreparePosition, writeResult.LogPosition.CommitPosition); Assert.Equal(writeResult.LogPosition, actual.First().Position); } - - 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.Streams.Tests/ReadStream/read_stream_backward_messages.cs b/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_backward_messages.cs new file mode 100644 index 000000000..a163874da --- /dev/null +++ b/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_backward_messages.cs @@ -0,0 +1,48 @@ +namespace EventStore.Client.Streams.Tests; + +[Network] +public class read_stream_backward_messages : IClassFixture { + public read_stream_backward_messages(ITestOutputHelper output, EventStoreFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); + + EventStoreFixture Fixture { get; } + + int EventCount { get; } = 32; + + [Fact] + public async Task stream_not_found() { + var result = await Fixture.Streams.ReadStreamAsync( + Direction.Backwards, + Fixture.GetStreamName(), + StreamPosition.End + ).Messages.SingleAsync(); + + Assert.Equal(StreamMessage.NotFound.Instance, result); + } + + [Fact] + public async Task stream_found() { + var events = Fixture.CreateTestEvents(EventCount).ToArray(); + + var streamName = Fixture.GetStreamName(); + + await Fixture.Streams.AppendToStreamAsync(streamName, StreamState.NoStream, events); + + var result = await Fixture.Streams.ReadStreamAsync( + Direction.Backwards, + streamName, + StreamPosition.End + ).Messages.ToArrayAsync(); + + Assert.Equal( + EventCount + (Fixture.EventStoreHasLastStreamPosition ? 2 : 1), + result.Length + ); + + Assert.Equal(StreamMessage.Ok.Instance, result[0]); + Assert.Equal(EventCount, result.OfType().Count()); + + 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_stream_forward.cs b/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_forward.cs similarity index 58% rename from test/EventStore.Client.Streams.Tests/read_stream_forward.cs rename to test/EventStore.Client.Streams.Tests/ReadStream/read_stream_forward.cs index a48a94a2e..b91465a23 100644 --- a/test/EventStore.Client.Streams.Tests/read_stream_forward.cs +++ b/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_forward.cs @@ -1,19 +1,20 @@ namespace EventStore.Client.Streams.Tests; -[Trait("Category", "Network")] -public class read_stream_forward : IClassFixture { - readonly Fixture _fixture; +[Network] +public class read_stream_forward : IClassFixture { + public read_stream_forward(ITestOutputHelper output, EventStoreFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); - public read_stream_forward(Fixture fixture) => _fixture = fixture; + EventStoreFixture Fixture { get; } [Theory] [InlineData(0)] public async Task count_le_equal_zero_throws(long maxCount) { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); var ex = await Assert.ThrowsAsync( () => - _fixture.Client.ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, maxCount) + Fixture.Streams.ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, maxCount) .ToArrayAsync().AsTask() ); @@ -22,10 +23,10 @@ public async Task count_le_equal_zero_throws(long maxCount) { [Fact] public async Task stream_does_not_exist_throws() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); var ex = await Assert.ThrowsAsync( - () => _fixture.Client + () => Fixture.Streams .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, 1) .ToArrayAsync().AsTask() ); @@ -35,9 +36,9 @@ public async Task stream_does_not_exist_throws() { [Fact] public async Task stream_does_not_exist_can_be_checked() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - var result = _fixture.Client.ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, 1); + var result = Fixture.Streams.ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, 1); var state = await result.ReadState; Assert.Equal(ReadState.StreamNotFound, state); @@ -45,12 +46,12 @@ public async Task stream_does_not_exist_can_be_checked() { [Fact] public async Task stream_deleted_throws() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - await _fixture.Client.TombstoneAsync(stream, StreamState.NoStream); + await Fixture.Streams.TombstoneAsync(stream, StreamState.NoStream); var ex = await Assert.ThrowsAsync( - () => _fixture.Client + () => Fixture.Streams .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, 1) .ToArrayAsync().AsTask() ); @@ -62,13 +63,13 @@ public async Task stream_deleted_throws() { [InlineData("small_events", 10, 1)] [InlineData("large_events", 2, 1_000_000)] public async Task returns_events_in_order(string suffix, int count, int metadataSize) { - var stream = $"{_fixture.GetStreamName()}_{suffix}"; + var stream = $"{Fixture.GetStreamName()}_{suffix}"; - var expected = _fixture.CreateTestEvents(count, metadataSize: metadataSize).ToArray(); + var expected = Fixture.CreateTestEvents(count, metadataSize: metadataSize).ToArray(); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, expected); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, expected); - var actual = await _fixture.Client + var actual = await Fixture.Streams .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, expected.Length) .Select(x => x.Event).ToArrayAsync(); @@ -77,15 +78,15 @@ public async Task returns_events_in_order(string suffix, int count, int metadata [Fact] public async Task be_able_to_read_single_event_from_arbitrary_position() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - var events = _fixture.CreateTestEvents(10).ToArray(); + var events = Fixture.CreateTestEvents(10).ToArray(); var expected = events[7]; - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - var actual = await _fixture.Client.ReadStreamAsync(Direction.Forwards, stream, new(7), 1) + var actual = await Fixture.Streams.ReadStreamAsync(Direction.Forwards, stream, new(7), 1) .Select(x => x.Event) .SingleAsync(); @@ -94,13 +95,13 @@ public async Task be_able_to_read_single_event_from_arbitrary_position() { [Fact] public async Task be_able_to_read_from_arbitrary_position() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - var events = _fixture.CreateTestEvents(10).ToArray(); + var events = Fixture.CreateTestEvents(10).ToArray(); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - var actual = await _fixture.Client.ReadStreamAsync(Direction.Forwards, stream, new(3), 2) + var actual = await Fixture.Streams.ReadStreamAsync(Direction.Forwards, stream, new(3), 2) .Select(x => x.Event) .ToArrayAsync(); @@ -109,13 +110,13 @@ public async Task be_able_to_read_from_arbitrary_position() { [Fact] public async Task be_able_to_read_first_event() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - var testEvents = _fixture.CreateTestEvents(10).ToArray(); + var testEvents = Fixture.CreateTestEvents(10).ToArray(); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, testEvents); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, testEvents); - var events = await _fixture.Client.ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, 1) + var events = await Fixture.Streams.ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, 1) .Select(x => x.Event) .ToArrayAsync(); @@ -125,17 +126,17 @@ public async Task be_able_to_read_first_event() { [Fact] public async Task max_count_is_respected() { - var streamName = _fixture.GetStreamName(); + var streamName = Fixture.GetStreamName(); const int count = 20; const long maxCount = count / 2; - await _fixture.Client.AppendToStreamAsync( + await Fixture.Streams.AppendToStreamAsync( streamName, StreamState.NoStream, - _fixture.CreateTestEvents(count) + Fixture.CreateTestEvents(count) ); - var events = await _fixture.Client.ReadStreamAsync(Direction.Forwards, streamName, StreamPosition.Start, maxCount) + var events = await Fixture.Streams.ReadStreamAsync(Direction.Forwards, streamName, StreamPosition.Start, maxCount) .Take(count) .ToArrayAsync(); @@ -144,15 +145,15 @@ await _fixture.Client.AppendToStreamAsync( [Fact] public async Task reads_all_events_by_default() { - var streamName = _fixture.GetStreamName(); + var streamName = Fixture.GetStreamName(); const int maxCount = 200; - await _fixture.Client.AppendToStreamAsync( + await Fixture.Streams.AppendToStreamAsync( streamName, StreamState.NoStream, - _fixture.CreateTestEvents(maxCount) + Fixture.CreateTestEvents(maxCount) ); - var count = await _fixture.Client + var count = await Fixture.Streams .ReadStreamAsync(Direction.Forwards, streamName, StreamPosition.Start) .CountAsync(); @@ -164,13 +165,13 @@ public async Task populates_log_position_of_event() { if (EventStoreTestServer.Version.Major < 22) return; - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - var events = _fixture.CreateTestEvents(1).ToArray(); + var events = Fixture.CreateTestEvents(1).ToArray(); - var writeResult = await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, events); + var writeResult = await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - var actual = await _fixture.Client.ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, 1) + var actual = await Fixture.Streams.ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, 1) .Select(x => x.Event) .ToArrayAsync(); @@ -178,9 +179,4 @@ public async Task populates_log_position_of_event() { Assert.Equal(writeResult.LogPosition.PreparePosition, writeResult.LogPosition.CommitPosition); Assert.Equal(writeResult.LogPosition, actual.First().Position); } - - 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.Streams.Tests/ReadStream/read_stream_forward_messages.cs b/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_forward_messages.cs new file mode 100644 index 000000000..3fcac9c87 --- /dev/null +++ b/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_forward_messages.cs @@ -0,0 +1,94 @@ +namespace EventStore.Client.Streams.Tests; + +[Network] +public class read_stream_forward_messages : IClassFixture { + public read_stream_forward_messages(ITestOutputHelper output, EventStoreFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); + + EventStoreFixture Fixture { get; } + + int EventCount { get; } = 64; + + [Fact] + public async Task stream_not_found() { + var result = await Fixture.Streams.ReadStreamAsync( + Direction.Forwards, + Fixture.GetStreamName(), + StreamPosition.Start + ).Messages.SingleAsync(); + + Assert.Equal(StreamMessage.NotFound.Instance, result); + } + + [Fact] + public async Task stream_found() { + var events = Fixture.CreateTestEvents(EventCount).ToArray(); + + var streamName = Fixture.GetStreamName(); + + await Fixture.Streams.AppendToStreamAsync(streamName, StreamState.NoStream, events); + + var result = await Fixture.Streams.ReadStreamAsync( + Direction.Forwards, + streamName, + StreamPosition.Start + ).Messages.ToArrayAsync(); + + Assert.Equal( + EventCount + (Fixture.EventStoreHasLastStreamPosition ? 2 : 1), + result.Length + ); + + Assert.Equal(StreamMessage.Ok.Instance, result[0]); + Assert.Equal(EventCount, result.OfType().Count()); + var first = Assert.IsType(result[1]); + Assert.Equal(new(0), first.ResolvedEvent.OriginalEventNumber); + var last = Assert.IsType(result[Fixture.EventStoreHasLastStreamPosition ? ^2 : ^1]); + Assert.Equal(new((ulong)EventCount - 1), last.ResolvedEvent.OriginalEventNumber); + + if (Fixture.EventStoreHasLastStreamPosition) + Assert.Equal( + new StreamMessage.LastStreamPosition(new((ulong)EventCount - 1)), + result[^1] + ); + } + + [Fact] + public async Task stream_found_truncated() { + var events = Fixture.CreateTestEvents(EventCount).ToArray(); + + var streamName = Fixture.GetStreamName(); + + await Fixture.Streams.AppendToStreamAsync(streamName, StreamState.NoStream, events); + + await Fixture.Streams.SetStreamMetadataAsync( + streamName, + StreamState.Any, + new(truncateBefore: new StreamPosition(32)) + ); + + var result = await Fixture.Streams.ReadStreamAsync( + Direction.Forwards, + streamName, + StreamPosition.Start + ).Messages.ToArrayAsync(); + + Assert.Equal( + EventCount - 32 + (Fixture.EventStoreHasLastStreamPosition ? 3 : 1), + result.Length + ); + + Assert.Equal(StreamMessage.Ok.Instance, result[0]); + + if (Fixture.EventStoreHasLastStreamPosition) + Assert.Equal(new StreamMessage.FirstStreamPosition(new(32)), result[1]); + + Assert.Equal(32, result.OfType().Count()); + + if (Fixture.EventStoreHasLastStreamPosition) + Assert.Equal( + new StreamMessage.LastStreamPosition(new((ulong)EventCount - 1)), + result[^1] + ); + } +} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/ReadStream/when_having_max_count_set_for_stream.cs b/test/EventStore.Client.Streams.Tests/ReadStream/when_having_max_count_set_for_stream.cs new file mode 100644 index 000000000..0833f04ea --- /dev/null +++ b/test/EventStore.Client.Streams.Tests/ReadStream/when_having_max_count_set_for_stream.cs @@ -0,0 +1,125 @@ +namespace EventStore.Client.Streams.Tests; + +[LongRunning] +public class when_having_max_count_set_for_stream : IClassFixture { + public when_having_max_count_set_for_stream(ITestOutputHelper output, EventStoreFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); + + EventStoreFixture Fixture { get; } + + [Fact] + public async Task read_stream_forwards_respects_max_count() { + var stream = Fixture.GetStreamName(); + + await Fixture.Streams.SetStreamMetadataAsync(stream, StreamState.NoStream, new(3)); + + var expected = Fixture.CreateTestEvents(5).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, expected); + + var actual = await Fixture.Streams.ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, 100) + .Select(x => x.Event) + .ToArrayAsync(); + + Assert.Equal(3, actual.Length); + Assert.True(EventDataComparer.Equal(expected.Skip(2).ToArray(), actual)); + } + + [Fact] + public async Task read_stream_backwards_respects_max_count() { + var stream = Fixture.GetStreamName(); + + await Fixture.Streams.SetStreamMetadataAsync(stream, StreamState.NoStream, new(3)); + + var expected = Fixture.CreateTestEvents(5).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, expected); + + var actual = await Fixture.Streams.ReadStreamAsync(Direction.Backwards, stream, StreamPosition.End, 100) + .Select(x => x.Event) + .ToArrayAsync(); + + Assert.Equal(3, actual.Length); + Assert.True(EventDataComparer.Equal(expected.Skip(2).Reverse().ToArray(), actual)); + } + + [Fact] + public async Task after_setting_less_strict_max_count_read_stream_forward_reads_more_events() { + var stream = Fixture.GetStreamName(); + + await Fixture.Streams.SetStreamMetadataAsync(stream, StreamState.NoStream, new(3)); + + var expected = Fixture.CreateTestEvents(5).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, expected); + + await Fixture.Streams.SetStreamMetadataAsync(stream, new StreamRevision(0), new(4)); + + var actual = await Fixture.Streams.ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, 100) + .Select(x => x.Event) + .ToArrayAsync(); + + Assert.Equal(4, actual.Length); + Assert.True(EventDataComparer.Equal(expected.Skip(1).ToArray(), actual)); + } + + [Fact] + public async Task after_setting_more_strict_max_count_read_stream_forward_reads_less_events() { + var stream = Fixture.GetStreamName(); + + await Fixture.Streams.SetStreamMetadataAsync(stream, StreamState.NoStream, new(3)); + + var expected = Fixture.CreateTestEvents(5).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, expected); + + await Fixture.Streams.SetStreamMetadataAsync(stream, new StreamRevision(0), new(2)); + + var actual = await Fixture.Streams.ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, 100) + .Select(x => x.Event) + .ToArrayAsync(); + + Assert.Equal(2, actual.Length); + Assert.True(EventDataComparer.Equal(expected.Skip(3).ToArray(), actual)); + } + + [Fact] + public async Task after_setting_less_strict_max_count_read_stream_backwards_reads_more_events() { + var stream = Fixture.GetStreamName(); + + await Fixture.Streams.SetStreamMetadataAsync(stream, StreamState.NoStream, new(3)); + + var expected = Fixture.CreateTestEvents(5).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, expected); + + await Fixture.Streams.SetStreamMetadataAsync(stream, new StreamRevision(0), new(4)); + + var actual = await Fixture.Streams.ReadStreamAsync(Direction.Backwards, stream, StreamPosition.End, 100) + .Select(x => x.Event) + .ToArrayAsync(); + + Assert.Equal(4, actual.Length); + Assert.True(EventDataComparer.Equal(expected.Skip(1).Reverse().ToArray(), actual)); + } + + [Fact] + public async Task after_setting_more_strict_max_count_read_stream_backwards_reads_less_events() { + var stream = Fixture.GetStreamName(); + + await Fixture.Streams.SetStreamMetadataAsync(stream, StreamState.NoStream, new(3)); + + var expected = Fixture.CreateTestEvents(5).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, expected); + + await Fixture.Streams.SetStreamMetadataAsync(stream, new StreamRevision(0), new(2)); + + var actual = await Fixture.Streams.ReadStreamAsync(Direction.Backwards, stream, StreamPosition.End, 100) + .Select(x => x.Event) + .ToArrayAsync(); + + 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/Security/SecurityFixture.cs b/test/EventStore.Client.Streams.Tests/Security/SecurityFixture.cs index 072abbead..1b30d45c9 100644 --- a/test/EventStore.Client.Streams.Tests/Security/SecurityFixture.cs +++ b/test/EventStore.Client.Streams.Tests/Security/SecurityFixture.cs @@ -1,8 +1,8 @@ using System.Runtime.CompilerServices; -namespace EventStore.Client.Streams.Tests.Security; +namespace EventStore.Client.Streams.Tests.Security; -public abstract class SecurityFixture : EventStoreClientFixture { +public abstract class SecurityFixture : InsecureClientTestFixture { public const string NoAclStream = nameof(NoAclStream); public const string ReadStream = nameof(ReadStream); public const string WriteStream = nameof(WriteStream); @@ -10,89 +10,87 @@ public abstract class SecurityFixture : EventStoreClientFixture { 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; - - protected SecurityFixture() : base(noDefaultCredentials: true) => UserManagementClient = new(Settings); - - public EventStoreUserManagementClient UserManagementClient { get; } - - protected override async Task OnServerUpAsync() { - await base.OnServerUpAsync(); - - await UserManagementClient.WarmUp(); - - await UserManagementClient.CreateUserWithRetry( - TestCredentials.TestUser1.Username!, - nameof(TestCredentials.TestUser1), - Array.Empty(), - TestCredentials.TestUser1.Password!, - TestCredentials.Root - ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - await UserManagementClient.CreateUserWithRetry( - TestCredentials.TestUser2.Username!, - nameof(TestCredentials.TestUser2), - Array.Empty(), - TestCredentials.TestUser2.Password!, - TestCredentials.Root - ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - await UserManagementClient.CreateUserWithRetry( - TestCredentials.TestAdmin.Username!, - nameof(TestCredentials.TestAdmin), - new[] { SystemRoles.Admins }, - TestCredentials.TestAdmin.Password!, - TestCredentials.Root - ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); + public const string SystemAllStream = $"${nameof(SystemAllStream)}"; + public const string SystemAdminStream = $"${nameof(SystemAdminStream)}"; + public const string SystemAclStream = $"${nameof(SystemAclStream)}"; + + const int TimeoutMs = 1000; + + public SecurityFixture() { + 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 override async Task Given() { - await Client.SetStreamMetadataAsync( + protected virtual async Task Given() { + await Streams.SetStreamMetadataAsync( NoAclStream, StreamState.NoStream, new(), userCredentials: TestCredentials.TestAdmin ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - await Client.SetStreamMetadataAsync( + await Streams.SetStreamMetadataAsync( ReadStream, StreamState.NoStream, new(acl: new(TestCredentials.TestUser1.Username)), userCredentials: TestCredentials.TestAdmin ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - await Client.SetStreamMetadataAsync( + await Streams.SetStreamMetadataAsync( WriteStream, StreamState.NoStream, new(acl: new(writeRole: TestCredentials.TestUser1.Username)), userCredentials: TestCredentials.TestAdmin ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - await Client.SetStreamMetadataAsync( + await Streams.SetStreamMetadataAsync( MetaReadStream, StreamState.NoStream, new(acl: new(metaReadRole: TestCredentials.TestUser1.Username)), userCredentials: TestCredentials.TestAdmin ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - await Client.SetStreamMetadataAsync( + await Streams.SetStreamMetadataAsync( MetaWriteStream, StreamState.NoStream, new(acl: new(metaWriteRole: TestCredentials.TestUser1.Username)), userCredentials: TestCredentials.TestAdmin ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - await Client.SetStreamMetadataAsync( + await Streams.SetStreamMetadataAsync( AllStream, StreamState.Any, new(acl: new(TestCredentials.TestUser1.Username)), userCredentials: TestCredentials.TestAdmin ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - await Client.SetStreamMetadataAsync( + await Streams.SetStreamMetadataAsync( SystemAclStream, StreamState.NoStream, new( @@ -106,7 +104,7 @@ await Client.SetStreamMetadataAsync( userCredentials: TestCredentials.TestAdmin ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - await Client.SetStreamMetadataAsync( + await Streams.SetStreamMetadataAsync( SystemAdminStream, StreamState.NoStream, new( @@ -120,7 +118,7 @@ await Client.SetStreamMetadataAsync( userCredentials: TestCredentials.TestAdmin ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - await Client.SetStreamMetadataAsync( + await Streams.SetStreamMetadataAsync( NormalAllStream, StreamState.NoStream, new( @@ -134,7 +132,7 @@ await Client.SetStreamMetadataAsync( userCredentials: TestCredentials.TestAdmin ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - await Client.SetStreamMetadataAsync( + await Streams.SetStreamMetadataAsync( SystemAllStream, StreamState.NoStream, new( @@ -149,8 +147,10 @@ await Client.SetStreamMetadataAsync( ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); } + protected virtual Task When() => Task.CompletedTask; + public Task ReadEvent(string streamId, UserCredentials? userCredentials = default) => - Client.ReadStreamAsync( + Streams.ReadStreamAsync( Direction.Forwards, streamId, StreamPosition.Start, @@ -163,7 +163,7 @@ public Task ReadEvent(string streamId, UserCredentials? userCredentials = defaul .WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); public Task ReadStreamForward(string streamId, UserCredentials? userCredentials = default) => - Client.ReadStreamAsync( + Streams.ReadStreamAsync( Direction.Forwards, streamId, StreamPosition.Start, @@ -176,7 +176,7 @@ public Task ReadStreamForward(string streamId, UserCredentials? userCredentials .WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); public Task ReadStreamBackward(string streamId, UserCredentials? userCredentials = default) => - Client.ReadStreamAsync( + Streams.ReadStreamAsync( Direction.Backwards, streamId, StreamPosition.Start, @@ -189,7 +189,7 @@ public Task ReadStreamBackward(string streamId, UserCredentials? userCredentials .WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); public Task AppendStream(string streamId, UserCredentials? userCredentials = default) => - Client.AppendToStreamAsync( + Streams.AppendToStreamAsync( streamId, StreamState.Any, CreateTestEvents(3), @@ -198,7 +198,7 @@ public Task AppendStream(string streamId, UserCredentials? userCre .WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); public Task ReadAllForward(UserCredentials? userCredentials = default) => - Client.ReadAllAsync( + Streams.ReadAllAsync( Direction.Forwards, Position.Start, 1, @@ -210,7 +210,8 @@ public Task ReadAllForward(UserCredentials? userCredentials = default) => .WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); public Task ReadAllBackward(UserCredentials? userCredentials = default) => - Client.ReadAllAsync( + Streams + .ReadAllAsync( Direction.Backwards, Position.End, 1, @@ -222,14 +223,11 @@ public Task ReadAllBackward(UserCredentials? userCredentials = default) => .WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); public Task ReadMeta(string streamId, UserCredentials? userCredentials = default) => - Client.GetStreamMetadataAsync(streamId, userCredentials: userCredentials) + Streams.GetStreamMetadataAsync(streamId, userCredentials: userCredentials) .WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - public Task WriteMeta( - string streamId, UserCredentials? userCredentials = default, - string? role = default - ) => - Client.SetStreamMetadataAsync( + public Task WriteMeta(string streamId, UserCredentials? userCredentials = default, string? role = default) => + Streams.SetStreamMetadataAsync( streamId, StreamState.Any, new( @@ -246,7 +244,7 @@ public Task WriteMeta( public async Task SubscribeToStream(string streamId, UserCredentials? userCredentials = default) { var source = new TaskCompletionSource(); - using (await Client.SubscribeToStreamAsync( + using (await Streams.SubscribeToStreamAsync( streamId, FromStream.Start, (_, _, _) => { @@ -267,7 +265,7 @@ public async Task SubscribeToStream(string streamId, UserCredentials? userCreden public async Task SubscribeToAll(UserCredentials? userCredentials = default) { var source = new TaskCompletionSource(); - using (await Client.SubscribeToAllAsync( + using (await Streams.SubscribeToAllAsync( FromAll.Start, (_, _, _) => { source.TrySetResult(true); @@ -286,12 +284,8 @@ public async Task SubscribeToAll(UserCredentials? userCredentials = default) { } } - public async Task CreateStreamWithMeta( - StreamMetadata metadata, - [CallerMemberName] - string streamId = "" - ) { - await Client.SetStreamMetadataAsync( + public async Task CreateStreamWithMeta(StreamMetadata metadata, [CallerMemberName] string streamId = "") { + await Streams.SetStreamMetadataAsync( streamId, StreamState.NoStream, metadata, @@ -303,11 +297,6 @@ await Client.SetStreamMetadataAsync( } public Task DeleteStream(string streamId, UserCredentials? userCredentials = default) => - Client.TombstoneAsync(streamId, StreamState.Any, userCredentials: userCredentials) + Streams.TombstoneAsync(streamId, StreamState.Any, userCredentials: userCredentials) .WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - public override async Task DisposeAsync() { - await UserManagementClient.DisposeAsync(); - await base.DisposeAsync(); - } } \ 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.Streams.Tests/Security/all_stream_with_no_acl_security.cs index e9d6013f9..2e833a802 100644 --- a/test/EventStore.Client.Streams.Tests/Security/all_stream_with_no_acl_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/all_stream_with_no_acl_security.cs @@ -1,71 +1,73 @@ namespace EventStore.Client.Streams.Tests.Security; -public class all_stream_with_no_acl_security - : IClassFixture { - readonly Fixture _fixture; +public class all_stream_with_no_acl_security : IClassFixture { + public all_stream_with_no_acl_security(ITestOutputHelper output, CustomFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); - public all_stream_with_no_acl_security(Fixture fixture) => _fixture = fixture; + CustomFixture Fixture { get; } + + public all_stream_with_no_acl_security(CustomFixture fixture) => Fixture = fixture; [Fact] public async Task write_to_all_is_never_allowed() { - await Assert.ThrowsAsync(() => _fixture.AppendStream(SecurityFixture.AllStream)); - await Assert.ThrowsAsync(() => _fixture.AppendStream(SecurityFixture.AllStream, TestCredentials.TestUser1)); - await Assert.ThrowsAsync(() => _fixture.AppendStream(SecurityFixture.AllStream, TestCredentials.TestAdmin)); + await Assert.ThrowsAsync(() => Fixture.AppendStream(SecurityFixture.AllStream)); + await Assert.ThrowsAsync(() => Fixture.AppendStream(SecurityFixture.AllStream, TestCredentials.TestUser1)); + await Assert.ThrowsAsync(() => Fixture.AppendStream(SecurityFixture.AllStream, TestCredentials.TestAdmin)); } [Fact] public async Task delete_of_all_is_never_allowed() { - await Assert.ThrowsAsync(() => _fixture.DeleteStream(SecurityFixture.AllStream)); - await Assert.ThrowsAsync(() => _fixture.DeleteStream(SecurityFixture.AllStream, TestCredentials.TestUser1)); - await Assert.ThrowsAsync(() => _fixture.DeleteStream(SecurityFixture.AllStream, TestCredentials.TestAdmin)); + await Assert.ThrowsAsync(() => Fixture.DeleteStream(SecurityFixture.AllStream)); + await Assert.ThrowsAsync(() => Fixture.DeleteStream(SecurityFixture.AllStream, TestCredentials.TestUser1)); + await Assert.ThrowsAsync(() => Fixture.DeleteStream(SecurityFixture.AllStream, TestCredentials.TestAdmin)); } [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.AllStream)); - await Assert.ThrowsAsync(() => _fixture.SubscribeToAll()); + await Assert.ThrowsAsync(() => Fixture.ReadAllForward()); + await Assert.ThrowsAsync(() => Fixture.ReadAllBackward()); + await Assert.ThrowsAsync(() => Fixture.ReadMeta(SecurityFixture.AllStream)); + await Assert.ThrowsAsync(() => Fixture.SubscribeToAll()); } [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.AllStream, TestCredentials.TestUser1)); - await Assert.ThrowsAsync(() => _fixture.SubscribeToAll(TestCredentials.TestUser1)); + await Assert.ThrowsAsync(() => Fixture.ReadAllForward(TestCredentials.TestUser1)); + await Assert.ThrowsAsync(() => Fixture.ReadAllBackward(TestCredentials.TestUser1)); + await Assert.ThrowsAsync(() => Fixture.ReadMeta(SecurityFixture.AllStream, TestCredentials.TestUser1)); + await Assert.ThrowsAsync(() => Fixture.SubscribeToAll(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.AllStream, TestCredentials.TestAdmin); - await _fixture.SubscribeToAll(TestCredentials.TestAdmin); + await Fixture.ReadAllForward(TestCredentials.TestAdmin); + await Fixture.ReadAllBackward(TestCredentials.TestAdmin); + await Fixture.ReadMeta(SecurityFixture.AllStream, TestCredentials.TestAdmin); + await Fixture.SubscribeToAll(TestCredentials.TestAdmin); } [Fact] public async Task meta_write_is_not_allowed_when_no_credentials_are_passed() => - await Assert.ThrowsAsync(() => _fixture.WriteMeta(SecurityFixture.AllStream)); + await Assert.ThrowsAsync(() => Fixture.WriteMeta(SecurityFixture.AllStream)); [Fact] public async Task meta_write_is_not_allowed_for_usual_user() => - await Assert.ThrowsAsync(() => _fixture.WriteMeta(SecurityFixture.AllStream, TestCredentials.TestUser1)); + await Assert.ThrowsAsync(() => Fixture.WriteMeta(SecurityFixture.AllStream, TestCredentials.TestUser1)); [Fact] - public Task meta_write_is_allowed_for_admin_user() => _fixture.WriteMeta(SecurityFixture.AllStream, TestCredentials.TestAdmin); + public Task meta_write_is_allowed_for_admin_user() => + Fixture.WriteMeta(SecurityFixture.AllStream, TestCredentials.TestAdmin); - public class Fixture : SecurityFixture { + public class CustomFixture : SecurityFixture { protected override async Task Given() { await base.Given(); - await Client.SetStreamMetadataAsync( + + await Streams.SetStreamMetadataAsync( AllStream, StreamState.Any, new(), userCredentials: TestCredentials.Root ); } - - protected override Task When() => Task.CompletedTask; } } \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/Security/delete_stream_security.cs b/test/EventStore.Client.Streams.Tests/Security/delete_stream_security.cs index 3b9132250..0478c7d70 100644 --- a/test/EventStore.Client.Streams.Tests/Security/delete_stream_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/delete_stream_security.cs @@ -1,248 +1,245 @@ namespace EventStore.Client.Streams.Tests.Security; -public class delete_stream_security : IClassFixture { - readonly Fixture _fixture; +public class delete_stream_security : IClassFixture { + public delete_stream_security(ITestOutputHelper output, SecurityFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); - public delete_stream_security(Fixture fixture) => _fixture = fixture; + SecurityFixture Fixture { get; } [Fact] public async Task delete_of_all_is_never_allowed() { - await Assert.ThrowsAsync(() => _fixture.DeleteStream(SecurityFixture.AllStream)); - await Assert.ThrowsAsync(() => _fixture.DeleteStream(SecurityFixture.AllStream, TestCredentials.TestUser1)); - await Assert.ThrowsAsync(() => _fixture.DeleteStream(SecurityFixture.AllStream, TestCredentials.TestAdmin)); + await Assert.ThrowsAsync(() => Fixture.DeleteStream(SecurityFixture.AllStream)); + await Assert.ThrowsAsync(() => Fixture.DeleteStream(SecurityFixture.AllStream, TestCredentials.TestUser1)); + await Assert.ThrowsAsync(() => Fixture.DeleteStream(SecurityFixture.AllStream, TestCredentials.TestAdmin)); } [AnonymousAccess.Fact] public async Task deleting_normal_no_acl_stream_with_no_user_is_allowed() { - var streamId = await _fixture.CreateStreamWithMeta(new()); - await _fixture.DeleteStream(streamId); + var streamId = await Fixture.CreateStreamWithMeta(new()); + await Fixture.DeleteStream(streamId); } [Fact] public async Task deleting_normal_no_acl_stream_with_existing_user_is_allowed() { - var streamId = await _fixture.CreateStreamWithMeta(new()); - await _fixture.DeleteStream(streamId, TestCredentials.TestUser1); + var streamId = await Fixture.CreateStreamWithMeta(new()); + await Fixture.DeleteStream(streamId, TestCredentials.TestUser1); } [Fact] public async Task deleting_normal_no_acl_stream_with_admin_user_is_allowed() { - var streamId = await _fixture.CreateStreamWithMeta(new()); - await _fixture.DeleteStream(streamId, TestCredentials.TestAdmin); + var streamId = await Fixture.CreateStreamWithMeta(new()); + await Fixture.DeleteStream(streamId, TestCredentials.TestAdmin); } [Fact] public async Task deleting_normal_user_stream_with_no_user_is_not_allowed() { var streamId = - await _fixture.CreateStreamWithMeta(new(acl: new(deleteRole: TestCredentials.TestUser1.Username))); + await Fixture.CreateStreamWithMeta(new(acl: new(deleteRole: TestCredentials.TestUser1.Username))); - await Assert.ThrowsAsync(() => _fixture.DeleteStream(streamId)); + await Assert.ThrowsAsync(() => Fixture.DeleteStream(streamId)); } [Fact] public async Task deleting_normal_user_stream_with_not_authorized_user_is_not_allowed() { var streamId = - await _fixture.CreateStreamWithMeta(new(acl: new(deleteRole: TestCredentials.TestUser1.Username))); + await Fixture.CreateStreamWithMeta(new(acl: new(deleteRole: TestCredentials.TestUser1.Username))); - await Assert.ThrowsAsync(() => _fixture.DeleteStream(streamId, TestCredentials.TestUser2)); + await Assert.ThrowsAsync(() => Fixture.DeleteStream(streamId, TestCredentials.TestUser2)); } [Fact] public async Task deleting_normal_user_stream_with_authorized_user_is_allowed() { var streamId = - await _fixture.CreateStreamWithMeta(new(acl: new(deleteRole: TestCredentials.TestUser1.Username))); + await Fixture.CreateStreamWithMeta(new(acl: new(deleteRole: TestCredentials.TestUser1.Username))); - await _fixture.DeleteStream(streamId, TestCredentials.TestUser1); + await Fixture.DeleteStream(streamId, TestCredentials.TestUser1); } [Fact] public async Task deleting_normal_user_stream_with_admin_user_is_allowed() { var streamId = - await _fixture.CreateStreamWithMeta(new(acl: new(deleteRole: TestCredentials.TestUser1.Username))); + await Fixture.CreateStreamWithMeta(new(acl: new(deleteRole: TestCredentials.TestUser1.Username))); - await _fixture.DeleteStream(streamId, TestCredentials.TestAdmin); + await Fixture.DeleteStream(streamId, TestCredentials.TestAdmin); } [Fact] public async Task deleting_normal_admin_stream_with_no_user_is_not_allowed() { var streamId = - await _fixture.CreateStreamWithMeta(new(acl: new(deleteRole: SystemRoles.Admins))); + await Fixture.CreateStreamWithMeta(new(acl: new(deleteRole: SystemRoles.Admins))); - await Assert.ThrowsAsync(() => _fixture.DeleteStream(streamId)); + await Assert.ThrowsAsync(() => Fixture.DeleteStream(streamId)); } [Fact] public async Task deleting_normal_admin_stream_with_existing_user_is_not_allowed() { var streamId = - await _fixture.CreateStreamWithMeta(new(acl: new(deleteRole: SystemRoles.Admins))); + await Fixture.CreateStreamWithMeta(new(acl: new(deleteRole: SystemRoles.Admins))); - await Assert.ThrowsAsync(() => _fixture.DeleteStream(streamId, TestCredentials.TestUser1)); + await Assert.ThrowsAsync(() => Fixture.DeleteStream(streamId, TestCredentials.TestUser1)); } [Fact] public async Task deleting_normal_admin_stream_with_admin_user_is_allowed() { var streamId = - await _fixture.CreateStreamWithMeta(new(acl: new(deleteRole: SystemRoles.Admins))); + await Fixture.CreateStreamWithMeta(new(acl: new(deleteRole: SystemRoles.Admins))); - await _fixture.DeleteStream(streamId, TestCredentials.TestAdmin); + await Fixture.DeleteStream(streamId, TestCredentials.TestAdmin); } [AnonymousAccess.Fact] public async Task deleting_normal_all_stream_with_no_user_is_allowed() { var streamId = - await _fixture.CreateStreamWithMeta(new(acl: new(deleteRole: SystemRoles.All))); + await Fixture.CreateStreamWithMeta(new(acl: new(deleteRole: SystemRoles.All))); - await _fixture.DeleteStream(streamId); + await Fixture.DeleteStream(streamId); } [Fact] public async Task deleting_normal_all_stream_with_existing_user_is_allowed() { var streamId = - await _fixture.CreateStreamWithMeta(new(acl: new(deleteRole: SystemRoles.All))); + await Fixture.CreateStreamWithMeta(new(acl: new(deleteRole: SystemRoles.All))); - await _fixture.DeleteStream(streamId, TestCredentials.TestUser1); + await Fixture.DeleteStream(streamId, TestCredentials.TestUser1); } [Fact] public async Task deleting_normal_all_stream_with_admin_user_is_allowed() { var streamId = - await _fixture.CreateStreamWithMeta(new(acl: new(deleteRole: SystemRoles.All))); + await Fixture.CreateStreamWithMeta(new(acl: new(deleteRole: SystemRoles.All))); - await _fixture.DeleteStream(streamId, TestCredentials.TestAdmin); + await Fixture.DeleteStream(streamId, TestCredentials.TestAdmin); } // $-stream [Fact] public async Task deleting_system_no_acl_stream_with_no_user_is_not_allowed() { - var streamId = await _fixture.CreateStreamWithMeta( - streamId: $"${_fixture.GetStreamName()}", + var streamId = await Fixture.CreateStreamWithMeta( + streamId: $"${Fixture.GetStreamName()}", metadata: new() ); - await Assert.ThrowsAsync(() => _fixture.DeleteStream(streamId)); + await Assert.ThrowsAsync(() => Fixture.DeleteStream(streamId)); } [Fact] public async Task deleting_system_no_acl_stream_with_existing_user_is_not_allowed() { - var streamId = await _fixture.CreateStreamWithMeta( - streamId: $"${_fixture.GetStreamName()}", + var streamId = await Fixture.CreateStreamWithMeta( + streamId: $"${Fixture.GetStreamName()}", metadata: new() ); - await Assert.ThrowsAsync(() => _fixture.DeleteStream(streamId, TestCredentials.TestUser1)); + await Assert.ThrowsAsync(() => Fixture.DeleteStream(streamId, TestCredentials.TestUser1)); } [Fact] public async Task deleting_system_no_acl_stream_with_admin_user_is_allowed() { - var streamId = await _fixture.CreateStreamWithMeta( - streamId: $"${_fixture.GetStreamName()}", + var streamId = await Fixture.CreateStreamWithMeta( + streamId: $"${Fixture.GetStreamName()}", metadata: new() ); - await _fixture.DeleteStream(streamId, TestCredentials.TestAdmin); + await Fixture.DeleteStream(streamId, TestCredentials.TestAdmin); } [Fact] public async Task deleting_system_user_stream_with_no_user_is_not_allowed() { - var streamId = await _fixture.CreateStreamWithMeta( - streamId: $"${_fixture.GetStreamName()}", + var streamId = await Fixture.CreateStreamWithMeta( + streamId: $"${Fixture.GetStreamName()}", metadata: new(acl: new(deleteRole: TestCredentials.TestUser1.Username)) ); - await Assert.ThrowsAsync(() => _fixture.DeleteStream(streamId)); + await Assert.ThrowsAsync(() => Fixture.DeleteStream(streamId)); } [Fact] public async Task deleting_system_user_stream_with_not_authorized_user_is_not_allowed() { - var streamId = await _fixture.CreateStreamWithMeta( - streamId: $"${_fixture.GetStreamName()}", + var streamId = await Fixture.CreateStreamWithMeta( + streamId: $"${Fixture.GetStreamName()}", metadata: new(acl: new(deleteRole: TestCredentials.TestUser1.Username)) ); - await Assert.ThrowsAsync(() => _fixture.DeleteStream(streamId, TestCredentials.TestUser2)); + await Assert.ThrowsAsync(() => Fixture.DeleteStream(streamId, TestCredentials.TestUser2)); } [Fact] public async Task deleting_system_user_stream_with_authorized_user_is_allowed() { - var streamId = await _fixture.CreateStreamWithMeta( - streamId: $"${_fixture.GetStreamName()}", + var streamId = await Fixture.CreateStreamWithMeta( + streamId: $"${Fixture.GetStreamName()}", metadata: new(acl: new(deleteRole: TestCredentials.TestUser1.Username)) ); - await _fixture.DeleteStream(streamId, TestCredentials.TestUser1); + await Fixture.DeleteStream(streamId, TestCredentials.TestUser1); } [Fact] public async Task deleting_system_user_stream_with_admin_user_is_allowed() { - var streamId = await _fixture.CreateStreamWithMeta( - streamId: $"${_fixture.GetStreamName()}", + var streamId = await Fixture.CreateStreamWithMeta( + streamId: $"${Fixture.GetStreamName()}", metadata: new(acl: new(deleteRole: TestCredentials.TestUser1.Username)) ); - await _fixture.DeleteStream(streamId, TestCredentials.TestAdmin); + await Fixture.DeleteStream(streamId, TestCredentials.TestAdmin); } [Fact] public async Task deleting_system_admin_stream_with_no_user_is_not_allowed() { - var streamId = await _fixture.CreateStreamWithMeta( - streamId: $"${_fixture.GetStreamName()}", + var streamId = await Fixture.CreateStreamWithMeta( + streamId: $"${Fixture.GetStreamName()}", metadata: new(acl: new(deleteRole: SystemRoles.Admins)) ); - await Assert.ThrowsAsync(() => _fixture.DeleteStream(streamId)); + await Assert.ThrowsAsync(() => Fixture.DeleteStream(streamId)); } [Fact] public async Task deleting_system_admin_stream_with_existing_user_is_not_allowed() { - var streamId = await _fixture.CreateStreamWithMeta( - streamId: $"${_fixture.GetStreamName()}", + var streamId = await Fixture.CreateStreamWithMeta( + streamId: $"${Fixture.GetStreamName()}", metadata: new(acl: new(deleteRole: SystemRoles.Admins)) ); - await Assert.ThrowsAsync(() => _fixture.DeleteStream(streamId, TestCredentials.TestUser1)); + await Assert.ThrowsAsync(() => Fixture.DeleteStream(streamId, TestCredentials.TestUser1)); } [Fact] public async Task deleting_system_admin_stream_with_admin_user_is_allowed() { - var streamId = await _fixture.CreateStreamWithMeta( - streamId: $"${_fixture.GetStreamName()}", + var streamId = await Fixture.CreateStreamWithMeta( + streamId: $"${Fixture.GetStreamName()}", metadata: new(acl: new(deleteRole: SystemRoles.Admins)) ); - await _fixture.DeleteStream(streamId, TestCredentials.TestAdmin); + await Fixture.DeleteStream(streamId, TestCredentials.TestAdmin); } [AnonymousAccess.Fact] public async Task deleting_system_all_stream_with_no_user_is_allowed() { - var streamId = await _fixture.CreateStreamWithMeta( - streamId: $"${_fixture.GetStreamName()}", + var streamId = await Fixture.CreateStreamWithMeta( + streamId: $"${Fixture.GetStreamName()}", metadata: new(acl: new(deleteRole: SystemRoles.All)) ); - await _fixture.DeleteStream(streamId); + await Fixture.DeleteStream(streamId); } [Fact] public async Task deleting_system_all_stream_with_existing_user_is_allowed() { - var streamId = await _fixture.CreateStreamWithMeta( - streamId: $"${_fixture.GetStreamName()}", + var streamId = await Fixture.CreateStreamWithMeta( + streamId: $"${Fixture.GetStreamName()}", metadata: new(acl: new(deleteRole: SystemRoles.All)) ); - await _fixture.DeleteStream(streamId, TestCredentials.TestUser1); + await Fixture.DeleteStream(streamId, TestCredentials.TestUser1); } [Fact] public async Task deleting_system_all_stream_with_admin_user_is_allowed() { - var streamId = await _fixture.CreateStreamWithMeta( - streamId: $"${_fixture.GetStreamName()}", + var streamId = await Fixture.CreateStreamWithMeta( + streamId: $"${Fixture.GetStreamName()}", metadata: new(acl: new(deleteRole: SystemRoles.All)) ); - await _fixture.DeleteStream(streamId, TestCredentials.TestAdmin); - } - - public class Fixture : SecurityFixture { - protected override Task When() => Task.CompletedTask; + 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.Streams.Tests/Security/multiple_role_security.cs index 209e48b22..22d52fa1b 100644 --- a/test/EventStore.Client.Streams.Tests/Security/multiple_role_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/multiple_role_security.cs @@ -1,32 +1,34 @@ namespace EventStore.Client.Streams.Tests.Security; -public class multiple_role_security : IClassFixture { - readonly Fixture _fixture; +public class multiple_role_security : IClassFixture { + public multiple_role_security(ITestOutputHelper output, CustomFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); - public multiple_role_security(Fixture fixture) => _fixture = fixture; + CustomFixture Fixture { get; } [Fact] public async Task multiple_roles_are_handled_correctly() { - await Assert.ThrowsAsync(() => _fixture.ReadEvent("usr-stream")); - await Assert.ThrowsAsync(() => _fixture.ReadEvent("usr-stream", TestCredentials.TestUser1)); - await Assert.ThrowsAsync(() => _fixture.ReadEvent("usr-stream", TestCredentials.TestUser2)); - await Assert.ThrowsAsync(() => _fixture.ReadEvent("usr-stream", TestCredentials.TestAdmin)); - - await Assert.ThrowsAsync(() => _fixture.AppendStream("usr-stream")); - await _fixture.AppendStream("usr-stream", TestCredentials.TestUser1); - await Assert.ThrowsAsync(() => _fixture.AppendStream("usr-stream", TestCredentials.TestUser2)); - await _fixture.AppendStream("usr-stream", TestCredentials.TestAdmin); - - await _fixture.DeleteStream("usr-stream2", TestCredentials.TestUser1); - await _fixture.DeleteStream("usr-stream3", TestCredentials.TestUser2); - await _fixture.DeleteStream("usr-stream4", TestCredentials.TestAdmin); + await Assert.ThrowsAsync(() => Fixture.ReadEvent("usr-stream")); + await Assert.ThrowsAsync(() => Fixture.ReadEvent("usr-stream", TestCredentials.TestUser1)); + await Assert.ThrowsAsync(() => Fixture.ReadEvent("usr-stream", TestCredentials.TestUser2)); + await Assert.ThrowsAsync(() => Fixture.ReadEvent("usr-stream", TestCredentials.TestAdmin)); + + await Assert.ThrowsAsync(() => Fixture.AppendStream("usr-stream")); + await Fixture.AppendStream("usr-stream", TestCredentials.TestUser1); + await Assert.ThrowsAsync(() => Fixture.AppendStream("usr-stream", TestCredentials.TestUser2)); + await Fixture.AppendStream("usr-stream", TestCredentials.TestAdmin); + + await Fixture.DeleteStream("usr-stream2", TestCredentials.TestUser1); + await Fixture.DeleteStream("usr-stream3", TestCredentials.TestUser2); + await Fixture.DeleteStream("usr-stream4", TestCredentials.TestAdmin); } [AnonymousAccess.Fact] - public async Task multiple_roles_are_handled_correctly_without_authentication() => await _fixture.DeleteStream("usr-stream1"); + public async Task multiple_roles_are_handled_correctly_without_authentication() => + await Fixture.DeleteStream("usr-stream1"); - public class Fixture : SecurityFixture { - protected override Task When() { + public class CustomFixture : SecurityFixture { + protected override async Task When() { var settings = new SystemSettings( new( new[] { "user1", "user2" }, @@ -35,7 +37,7 @@ protected override Task When() { ) ); - return Client.SetSystemSettingsAsync(settings, userCredentials: TestCredentials.TestAdmin); + 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.cs b/test/EventStore.Client.Streams.Tests/Security/overriden_system_stream_security.cs index 87af193ab..dbb6cb469 100644 --- a/test/EventStore.Client.Streams.Tests/Security/overriden_system_stream_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/overriden_system_stream_security.cs @@ -1,89 +1,90 @@ -namespace EventStore.Client.Streams.Tests.Security; +namespace EventStore.Client.Streams.Tests.Security; -public class overriden_system_stream_security : IClassFixture { - readonly Fixture _fixture; +public class overriden_system_stream_security : IClassFixture { + public overriden_system_stream_security(ITestOutputHelper output, CustomFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); - public overriden_system_stream_security(Fixture fixture) => _fixture = fixture; + CustomFixture Fixture { get; } [Fact] public async Task operations_on_system_stream_succeed_for_authorized_user() { - var stream = $"${_fixture.GetStreamName()}"; - await _fixture.AppendStream(stream, TestCredentials.TestUser1); + 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.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.ReadMeta(stream, TestCredentials.TestUser1); + await Fixture.WriteMeta(stream, TestCredentials.TestUser1); - await _fixture.SubscribeToStream(stream, TestCredentials.TestUser1); + await Fixture.SubscribeToStream(stream, TestCredentials.TestUser1); - await _fixture.DeleteStream(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)); + 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) + Fixture.ReadStreamBackward(stream, TestCredentials.TestUser2) ); - await Assert.ThrowsAsync(() => _fixture.AppendStream(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.ReadMeta(stream, TestCredentials.TestUser2)); + await Assert.ThrowsAsync(() => Fixture.WriteMeta(stream, TestCredentials.TestUser2)); - await Assert.ThrowsAsync(() => _fixture.SubscribeToStream(stream, TestCredentials.TestUser2)); + await Assert.ThrowsAsync(() => Fixture.SubscribeToStream(stream, TestCredentials.TestUser2)); - await Assert.ThrowsAsync(() => _fixture.DeleteStream(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)); + 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.AppendStream(stream)); - await Assert.ThrowsAsync(() => _fixture.ReadMeta(stream)); - await Assert.ThrowsAsync(() => _fixture.WriteMeta(stream)); + await Assert.ThrowsAsync(() => Fixture.ReadMeta(stream)); + await Assert.ThrowsAsync(() => Fixture.WriteMeta(stream)); - await Assert.ThrowsAsync(() => _fixture.SubscribeToStream(stream)); + await Assert.ThrowsAsync(() => Fixture.SubscribeToStream(stream)); - await Assert.ThrowsAsync(() => _fixture.DeleteStream(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); + 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.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.ReadMeta(stream, TestCredentials.TestAdmin); + await Fixture.WriteMeta(stream, TestCredentials.TestAdmin); - await _fixture.SubscribeToStream(stream, TestCredentials.TestAdmin); + await Fixture.SubscribeToStream(stream, TestCredentials.TestAdmin); - await _fixture.DeleteStream(stream, TestCredentials.TestAdmin); + await Fixture.DeleteStream(stream, TestCredentials.TestAdmin); } - public class Fixture : SecurityFixture { + public class CustomFixture : SecurityFixture { protected override Task When() { var settings = new SystemSettings( systemStreamAcl: new("user1", "user1", "user1", "user1", "user1"), userStreamAcl: default ); - return Client.SetSystemSettingsAsync(settings, userCredentials: TestCredentials.TestAdmin); + return 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.Streams.Tests/Security/overriden_system_stream_security_for_all.cs index cbb11e0d6..e525c550b 100644 --- a/test/EventStore.Client.Streams.Tests/Security/overriden_system_stream_security_for_all.cs +++ b/test/EventStore.Client.Streams.Tests/Security/overriden_system_stream_security_for_all.cs @@ -1,61 +1,61 @@ namespace EventStore.Client.Streams.Tests.Security; -public class overriden_system_stream_security_for_all - : IClassFixture { - readonly Fixture _fixture; +public class overriden_system_stream_security_for_all : IClassFixture { + public overriden_system_stream_security_for_all(ITestOutputHelper output, CustomFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); - public overriden_system_stream_security_for_all(Fixture fixture) => _fixture = fixture; + CustomFixture Fixture { get; } [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); + 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.ReadMeta(stream, TestCredentials.TestUser1); + await Fixture.WriteMeta(stream, TestCredentials.TestUser1); - await _fixture.SubscribeToStream(stream, TestCredentials.TestUser1); + await Fixture.SubscribeToStream(stream, TestCredentials.TestUser1); - await _fixture.DeleteStream(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); + 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.ReadMeta(stream); + await Fixture.WriteMeta(stream); - await _fixture.SubscribeToStream(stream); + await Fixture.SubscribeToStream(stream); - await _fixture.DeleteStream(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); + 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.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.ReadMeta(stream, TestCredentials.TestAdmin); + await Fixture.WriteMeta(stream, TestCredentials.TestAdmin); - await _fixture.SubscribeToStream(stream, TestCredentials.TestAdmin); + await Fixture.SubscribeToStream(stream, TestCredentials.TestAdmin); - await _fixture.DeleteStream(stream, TestCredentials.TestAdmin); + await Fixture.DeleteStream(stream, TestCredentials.TestAdmin); } - public class Fixture : SecurityFixture { + public class CustomFixture : SecurityFixture { protected override Task When() { var settings = new SystemSettings( systemStreamAcl: new( @@ -67,7 +67,7 @@ protected override Task When() { ) ); - return Client.SetSystemSettingsAsync(settings, userCredentials: TestCredentials.TestAdmin); + return Streams.SetSystemSettingsAsync(settings, userCredentials: TestCredentials.TestAdmin); } } } \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/Security/overriden_user_stream_security.cs b/test/EventStore.Client.Streams.Tests/Security/overriden_user_stream_security.cs index b969f2115..5951cad5f 100644 --- a/test/EventStore.Client.Streams.Tests/Security/overriden_user_stream_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/overriden_user_stream_security.cs @@ -1,80 +1,80 @@ namespace EventStore.Client.Streams.Tests.Security; -public class overriden_user_stream_security : IClassFixture { - readonly Fixture _fixture; +public class overriden_user_stream_security : IClassFixture { + public overriden_user_stream_security(ITestOutputHelper output, CustomFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); - public overriden_user_stream_security(Fixture fixture) => _fixture = fixture; + CustomFixture Fixture { get; } [Fact] public async Task operations_on_user_stream_succeeds_for_authorized_user() { - var stream = _fixture.GetStreamName(); - await _fixture.AppendStream(stream, TestCredentials.TestUser1); + 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.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.ReadMeta(stream, TestCredentials.TestUser1); + await Fixture.WriteMeta(stream, TestCredentials.TestUser1); - await _fixture.SubscribeToStream(stream, TestCredentials.TestUser1); + await Fixture.SubscribeToStream(stream, TestCredentials.TestUser1); - await _fixture.DeleteStream(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)); + 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.AppendStream(stream, TestCredentials.TestUser2)); + await Assert.ThrowsAsync(() => Fixture.ReadMeta(stream, TestCredentials.TestUser2)); + await Assert.ThrowsAsync(() => Fixture.WriteMeta(stream, TestCredentials.TestUser2)); - await Assert.ThrowsAsync(() => _fixture.SubscribeToStream(stream, TestCredentials.TestUser2)); + await Assert.ThrowsAsync(() => Fixture.SubscribeToStream(stream, TestCredentials.TestUser2)); - await Assert.ThrowsAsync(() => _fixture.DeleteStream(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)); + 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.AppendStream(stream)); + await Assert.ThrowsAsync(() => Fixture.ReadMeta(stream)); + await Assert.ThrowsAsync(() => Fixture.WriteMeta(stream)); - await Assert.ThrowsAsync(() => _fixture.SubscribeToStream(stream)); + await Assert.ThrowsAsync(() => Fixture.SubscribeToStream(stream)); - await Assert.ThrowsAsync(() => _fixture.DeleteStream(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); + 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.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.ReadMeta(stream, TestCredentials.TestAdmin); + await Fixture.WriteMeta(stream, TestCredentials.TestAdmin); - await _fixture.SubscribeToStream(stream, TestCredentials.TestAdmin); + await Fixture.SubscribeToStream(stream, TestCredentials.TestAdmin); - await _fixture.DeleteStream(stream, TestCredentials.TestAdmin); + await Fixture.DeleteStream(stream, TestCredentials.TestAdmin); } - public class Fixture : SecurityFixture { + public class CustomFixture : SecurityFixture { protected override Task When() { var settings = new SystemSettings(new("user1", "user1", "user1", "user1", "user1")); - return Client.SetSystemSettingsAsync(settings, userCredentials: TestCredentials.TestAdmin); + return Streams.SetSystemSettingsAsync(settings, userCredentials: TestCredentials.TestAdmin); } } } \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/Security/read_all_security.cs b/test/EventStore.Client.Streams.Tests/Security/read_all_security.cs index 6b6e5539f..ba05ac78e 100644 --- a/test/EventStore.Client.Streams.Tests/Security/read_all_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/read_all_security.cs @@ -1,41 +1,38 @@ namespace EventStore.Client.Streams.Tests.Security; -public class read_all_security : IClassFixture { - readonly Fixture _fixture; +public class read_all_security : IClassFixture { + public read_all_security(ITestOutputHelper output, SecurityFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); - public read_all_security(Fixture fixture) => _fixture = fixture; + SecurityFixture Fixture { get; } [Fact] public async Task reading_all_with_not_existing_credentials_is_not_authenticated() { - await Assert.ThrowsAsync(() => _fixture.ReadAllForward(TestCredentials.TestBadUser)); - await Assert.ThrowsAsync(() => _fixture.ReadAllBackward(TestCredentials.TestBadUser)); + await Assert.ThrowsAsync(() => Fixture.ReadAllForward(TestCredentials.TestBadUser)); + await Assert.ThrowsAsync(() => Fixture.ReadAllBackward(TestCredentials.TestBadUser)); } [Fact] public async Task reading_all_with_no_credentials_is_denied() { - await Assert.ThrowsAsync(() => _fixture.ReadAllForward()); - await Assert.ThrowsAsync(() => _fixture.ReadAllBackward()); + await Assert.ThrowsAsync(() => Fixture.ReadAllForward()); + await Assert.ThrowsAsync(() => Fixture.ReadAllBackward()); } [Fact] public async Task reading_all_with_not_authorized_user_credentials_is_denied() { - await Assert.ThrowsAsync(() => _fixture.ReadAllForward(TestCredentials.TestUser2)); - await Assert.ThrowsAsync(() => _fixture.ReadAllBackward(TestCredentials.TestUser2)); + await Assert.ThrowsAsync(() => Fixture.ReadAllForward(TestCredentials.TestUser2)); + await Assert.ThrowsAsync(() => Fixture.ReadAllBackward(TestCredentials.TestUser2)); } [Fact] public async Task reading_all_with_authorized_user_credentials_succeeds() { - await _fixture.ReadAllForward(TestCredentials.TestUser1); - await _fixture.ReadAllBackward(TestCredentials.TestUser1); + await Fixture.ReadAllForward(TestCredentials.TestUser1); + await Fixture.ReadAllBackward(TestCredentials.TestUser1); } [Fact] public async Task reading_all_with_admin_credentials_succeeds() { - await _fixture.ReadAllForward(TestCredentials.TestAdmin); - await _fixture.ReadAllBackward(TestCredentials.TestAdmin); - } - - public class Fixture : SecurityFixture { - protected override Task When() => Task.CompletedTask; + 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.Streams.Tests/Security/read_stream_meta_security.cs index 0192fe371..ee7302456 100644 --- a/test/EventStore.Client.Streams.Tests/Security/read_stream_meta_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/read_stream_meta_security.cs @@ -1,80 +1,72 @@ namespace EventStore.Client.Streams.Tests.Security; -public class read_stream_meta_security : IClassFixture { - readonly Fixture _fixture; +public class read_stream_meta_security : IClassFixture { + public read_stream_meta_security(ITestOutputHelper output, SecurityFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); - public read_stream_meta_security(Fixture fixture) => _fixture = fixture; + SecurityFixture Fixture { get; } [Fact] public async Task reading_stream_meta_with_not_existing_credentials_is_not_authenticated() => await Assert.ThrowsAsync( - () => - _fixture.ReadMeta(SecurityFixture.MetaReadStream, TestCredentials.TestBadUser) + () => Fixture.ReadMeta(SecurityFixture.MetaReadStream, TestCredentials.TestBadUser) ); [Fact] public async Task reading_stream_meta_with_no_credentials_is_denied() => - await Assert.ThrowsAsync(() => _fixture.ReadMeta(SecurityFixture.MetaReadStream)); + await Assert.ThrowsAsync(() => Fixture.ReadMeta(SecurityFixture.MetaReadStream)); [Fact] public async Task reading_stream_meta_with_not_authorized_user_credentials_is_denied() => await Assert.ThrowsAsync( - () => - _fixture.ReadMeta(SecurityFixture.MetaReadStream, TestCredentials.TestUser2) + () => Fixture.ReadMeta(SecurityFixture.MetaReadStream, TestCredentials.TestUser2) ); [Fact] public async Task reading_stream_meta_with_authorized_user_credentials_succeeds() => - await _fixture.ReadMeta(SecurityFixture.MetaReadStream, TestCredentials.TestUser1); + await Fixture.ReadMeta(SecurityFixture.MetaReadStream, TestCredentials.TestUser1); [Fact] public async Task reading_stream_meta_with_admin_user_credentials_succeeds() => - await _fixture.ReadMeta(SecurityFixture.MetaReadStream, TestCredentials.TestAdmin); + await Fixture.ReadMeta(SecurityFixture.MetaReadStream, TestCredentials.TestAdmin); [AnonymousAccess.Fact] - public async Task reading_no_acl_stream_meta_succeeds_when_no_credentials_are_passed() => await _fixture.ReadMeta(SecurityFixture.NoAclStream); + public async Task reading_no_acl_stream_meta_succeeds_when_no_credentials_are_passed() => await Fixture.ReadMeta(SecurityFixture.NoAclStream); [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) + () => Fixture.ReadMeta(SecurityFixture.NoAclStream, TestCredentials.TestBadUser) ); [Fact] public async Task reading_no_acl_stream_meta_succeeds_when_any_existing_user_credentials_are_passed() { - await _fixture.ReadMeta(SecurityFixture.NoAclStream, TestCredentials.TestUser1); - await _fixture.ReadMeta(SecurityFixture.NoAclStream, TestCredentials.TestUser2); + await Fixture.ReadMeta(SecurityFixture.NoAclStream, TestCredentials.TestUser1); + await Fixture.ReadMeta(SecurityFixture.NoAclStream, TestCredentials.TestUser2); } [Fact] public async Task reading_no_acl_stream_meta_succeeds_when_admin_user_credentials_are_passed() => - await _fixture.ReadMeta(SecurityFixture.NoAclStream, TestCredentials.TestAdmin); + await Fixture.ReadMeta(SecurityFixture.NoAclStream, TestCredentials.TestAdmin); [AnonymousAccess.Fact] public async Task reading_all_access_normal_stream_meta_succeeds_when_no_credentials_are_passed() => - await _fixture.ReadMeta(SecurityFixture.NormalAllStream); + await Fixture.ReadMeta(SecurityFixture.NormalAllStream); [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) + () => Fixture.ReadMeta(SecurityFixture.NormalAllStream, TestCredentials.TestBadUser) ); [Fact] public async Task reading_all_access_normal_stream_meta_succeeds_when_any_existing_user_credentials_are_passed() { - await _fixture.ReadMeta(SecurityFixture.NormalAllStream, TestCredentials.TestUser1); - await _fixture.ReadMeta(SecurityFixture.NormalAllStream, TestCredentials.TestUser2); + await Fixture.ReadMeta(SecurityFixture.NormalAllStream, TestCredentials.TestUser1); + await Fixture.ReadMeta(SecurityFixture.NormalAllStream, TestCredentials.TestUser2); } [Fact] public async Task reading_all_access_normal_stream_meta_succeeds_when_admin_user_credentials_are_passed() => - await _fixture.ReadMeta(SecurityFixture.NormalAllStream, TestCredentials.TestAdmin); - - public class Fixture : SecurityFixture { - protected override Task When() => Task.CompletedTask; - } + 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.Streams.Tests/Security/read_stream_security.cs index a5d4e6c60..59879019f 100644 --- a/test/EventStore.Client.Streams.Tests/Security/read_stream_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/read_stream_security.cs @@ -1,164 +1,116 @@ namespace EventStore.Client.Streams.Tests.Security; -public class read_stream_security : IClassFixture { - readonly Fixture _fixture; +public class read_stream_security : IClassFixture { + public read_stream_security(ITestOutputHelper output, SecurityFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); - public read_stream_security(Fixture fixture) => _fixture = fixture; + SecurityFixture Fixture { get; } [Fact] public async Task reading_stream_with_not_existing_credentials_is_not_authenticated() { - await Assert.ThrowsAsync( - () => - _fixture.ReadEvent(SecurityFixture.ReadStream, TestCredentials.TestBadUser) - ); - - await Assert.ThrowsAsync( - () => - _fixture.ReadStreamForward(SecurityFixture.ReadStream, TestCredentials.TestBadUser) - ); - - await Assert.ThrowsAsync( - () => - _fixture.ReadStreamBackward(SecurityFixture.ReadStream, TestCredentials.TestBadUser) - ); + await Assert.ThrowsAsync(() => Fixture.ReadEvent(SecurityFixture.ReadStream, TestCredentials.TestBadUser)); + await Assert.ThrowsAsync(() => Fixture.ReadStreamForward(SecurityFixture.ReadStream, TestCredentials.TestBadUser)); + await Assert.ThrowsAsync(() => Fixture.ReadStreamBackward(SecurityFixture.ReadStream, TestCredentials.TestBadUser)); } [Fact] public async Task reading_stream_with_no_credentials_is_denied() { - await Assert.ThrowsAsync(() => _fixture.ReadEvent(SecurityFixture.ReadStream)); - await Assert.ThrowsAsync(() => _fixture.ReadStreamForward(SecurityFixture.ReadStream)); - await Assert.ThrowsAsync( - () => - _fixture.ReadStreamBackward(SecurityFixture.ReadStream) - ); + await Assert.ThrowsAsync(() => Fixture.ReadEvent(SecurityFixture.ReadStream)); + await Assert.ThrowsAsync(() => Fixture.ReadStreamForward(SecurityFixture.ReadStream)); + await Assert.ThrowsAsync(() => Fixture.ReadStreamBackward(SecurityFixture.ReadStream)); } [Fact] public async Task reading_stream_with_not_authorized_user_credentials_is_denied() { - await Assert.ThrowsAsync( - () => - _fixture.ReadEvent(SecurityFixture.ReadStream, TestCredentials.TestUser2) - ); - - await Assert.ThrowsAsync( - () => - _fixture.ReadStreamForward(SecurityFixture.ReadStream, TestCredentials.TestUser2) - ); - - await Assert.ThrowsAsync( - () => - _fixture.ReadStreamBackward(SecurityFixture.ReadStream, TestCredentials.TestUser2) - ); + await Assert.ThrowsAsync(() => Fixture.ReadEvent(SecurityFixture.ReadStream, TestCredentials.TestUser2)); + await Assert.ThrowsAsync(() => Fixture.ReadStreamForward(SecurityFixture.ReadStream, TestCredentials.TestUser2)); + await Assert.ThrowsAsync(() => Fixture.ReadStreamBackward(SecurityFixture.ReadStream, TestCredentials.TestUser2)); } [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); + 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); } [Fact] public async Task reading_stream_with_admin_user_credentials_succeeds() { - await _fixture.AppendStream(SecurityFixture.ReadStream, TestCredentials.TestAdmin); + await Fixture.AppendStream(SecurityFixture.ReadStream, TestCredentials.TestAdmin); - await _fixture.ReadEvent(SecurityFixture.ReadStream, TestCredentials.TestAdmin); - await _fixture.ReadStreamForward(SecurityFixture.ReadStream, TestCredentials.TestAdmin); - await _fixture.ReadStreamBackward(SecurityFixture.ReadStream, TestCredentials.TestAdmin); + await Fixture.ReadEvent(SecurityFixture.ReadStream, TestCredentials.TestAdmin); + await Fixture.ReadStreamForward(SecurityFixture.ReadStream, TestCredentials.TestAdmin); + await Fixture.ReadStreamBackward(SecurityFixture.ReadStream, TestCredentials.TestAdmin); } [AnonymousAccess.Fact] public async Task reading_no_acl_stream_succeeds_when_no_credentials_are_passed() { - await _fixture.AppendStream(SecurityFixture.NoAclStream); + await Fixture.AppendStream(SecurityFixture.NoAclStream); - await _fixture.ReadEvent(SecurityFixture.NoAclStream); - await _fixture.ReadStreamForward(SecurityFixture.NoAclStream); - await _fixture.ReadStreamBackward(SecurityFixture.NoAclStream); + await Fixture.ReadEvent(SecurityFixture.NoAclStream); + await Fixture.ReadStreamForward(SecurityFixture.NoAclStream); + await Fixture.ReadStreamBackward(SecurityFixture.NoAclStream); } [Fact] public async Task reading_no_acl_stream_is_not_authenticated_when_not_existing_credentials_are_passed() { - await Assert.ThrowsAsync(() => _fixture.ReadEvent(SecurityFixture.NoAclStream, TestCredentials.TestBadUser)); - await Assert.ThrowsAsync( - () => - _fixture.ReadStreamForward(SecurityFixture.NoAclStream, TestCredentials.TestBadUser) - ); - - await Assert.ThrowsAsync( - () => - _fixture.ReadStreamBackward(SecurityFixture.NoAclStream, TestCredentials.TestBadUser) - ); + await Assert.ThrowsAsync(() => Fixture.ReadEvent(SecurityFixture.NoAclStream, TestCredentials.TestBadUser)); + await Assert.ThrowsAsync(() => Fixture.ReadStreamForward(SecurityFixture.NoAclStream, TestCredentials.TestBadUser)); + await Assert.ThrowsAsync(() => Fixture.ReadStreamBackward(SecurityFixture.NoAclStream, TestCredentials.TestBadUser)); } [Fact] public async Task reading_no_acl_stream_succeeds_when_any_existing_user_credentials_are_passed() { - await _fixture.AppendStream(SecurityFixture.NoAclStream, TestCredentials.TestUser1); - - await _fixture.ReadEvent(SecurityFixture.NoAclStream, TestCredentials.TestUser1); - await _fixture.ReadStreamForward(SecurityFixture.NoAclStream, TestCredentials.TestUser1); - await _fixture.ReadStreamBackward(SecurityFixture.NoAclStream, TestCredentials.TestUser1); - await _fixture.ReadEvent(SecurityFixture.NoAclStream, TestCredentials.TestUser2); - await _fixture.ReadStreamForward(SecurityFixture.NoAclStream, TestCredentials.TestUser2); - await _fixture.ReadStreamBackward(SecurityFixture.NoAclStream, TestCredentials.TestUser2); + await Fixture.AppendStream(SecurityFixture.NoAclStream, TestCredentials.TestUser1); + + await Fixture.ReadEvent(SecurityFixture.NoAclStream, TestCredentials.TestUser1); + await Fixture.ReadStreamForward(SecurityFixture.NoAclStream, TestCredentials.TestUser1); + await Fixture.ReadStreamBackward(SecurityFixture.NoAclStream, TestCredentials.TestUser1); + await Fixture.ReadEvent(SecurityFixture.NoAclStream, TestCredentials.TestUser2); + await Fixture.ReadStreamForward(SecurityFixture.NoAclStream, TestCredentials.TestUser2); + await Fixture.ReadStreamBackward(SecurityFixture.NoAclStream, TestCredentials.TestUser2); } [Fact] public async Task reading_no_acl_stream_succeeds_when_admin_user_credentials_are_passed() { - await _fixture.AppendStream(SecurityFixture.NoAclStream, TestCredentials.TestAdmin); - await _fixture.ReadEvent(SecurityFixture.NoAclStream, TestCredentials.TestAdmin); - await _fixture.ReadStreamForward(SecurityFixture.NoAclStream, TestCredentials.TestAdmin); - await _fixture.ReadStreamBackward(SecurityFixture.NoAclStream, TestCredentials.TestAdmin); + await Fixture.AppendStream(SecurityFixture.NoAclStream, TestCredentials.TestAdmin); + await Fixture.ReadEvent(SecurityFixture.NoAclStream, TestCredentials.TestAdmin); + await Fixture.ReadStreamForward(SecurityFixture.NoAclStream, TestCredentials.TestAdmin); + await Fixture.ReadStreamBackward(SecurityFixture.NoAclStream, TestCredentials.TestAdmin); } [AnonymousAccess.Fact] public async Task reading_all_access_normal_stream_succeeds_when_no_credentials_are_passed() { - await _fixture.AppendStream(SecurityFixture.NormalAllStream); - await _fixture.ReadEvent(SecurityFixture.NormalAllStream); - await _fixture.ReadStreamForward(SecurityFixture.NormalAllStream); - await _fixture.ReadStreamBackward(SecurityFixture.NormalAllStream); + await Fixture.AppendStream(SecurityFixture.NormalAllStream); + await Fixture.ReadEvent(SecurityFixture.NormalAllStream); + await Fixture.ReadStreamForward(SecurityFixture.NormalAllStream); + await Fixture.ReadStreamBackward(SecurityFixture.NormalAllStream); } [Fact] - public async Task - reading_all_access_normal_stream_is_not_authenticated_when_not_existing_credentials_are_passed() { - await Assert.ThrowsAsync( - () => - _fixture.ReadEvent(SecurityFixture.NormalAllStream, TestCredentials.TestBadUser) - ); - - await Assert.ThrowsAsync( - () => - _fixture.ReadStreamForward(SecurityFixture.NormalAllStream, TestCredentials.TestBadUser) - ); - - await Assert.ThrowsAsync( - () => - _fixture.ReadStreamBackward(SecurityFixture.NormalAllStream, TestCredentials.TestBadUser) - ); + public async Task reading_all_access_normal_stream_is_not_authenticated_when_not_existing_credentials_are_passed() { + await Assert.ThrowsAsync(() => Fixture.ReadEvent(SecurityFixture.NormalAllStream, TestCredentials.TestBadUser)); + await Assert.ThrowsAsync(() => Fixture.ReadStreamForward(SecurityFixture.NormalAllStream, TestCredentials.TestBadUser)); + await Assert.ThrowsAsync(() => Fixture.ReadStreamBackward(SecurityFixture.NormalAllStream, TestCredentials.TestBadUser)); } [Fact] public async Task reading_all_access_normal_stream_succeeds_when_any_existing_user_credentials_are_passed() { - await _fixture.AppendStream(SecurityFixture.NormalAllStream, TestCredentials.TestUser1); - await _fixture.ReadEvent(SecurityFixture.NormalAllStream, TestCredentials.TestUser1); - await _fixture.ReadStreamForward(SecurityFixture.NormalAllStream, TestCredentials.TestUser1); - await _fixture.ReadStreamBackward(SecurityFixture.NormalAllStream, TestCredentials.TestUser1); - await _fixture.ReadEvent(SecurityFixture.NormalAllStream, TestCredentials.TestUser2); - await _fixture.ReadStreamForward(SecurityFixture.NormalAllStream, TestCredentials.TestUser2); - await _fixture.ReadStreamBackward(SecurityFixture.NormalAllStream, TestCredentials.TestUser2); + await Fixture.AppendStream(SecurityFixture.NormalAllStream, TestCredentials.TestUser1); + await Fixture.ReadEvent(SecurityFixture.NormalAllStream, TestCredentials.TestUser1); + await Fixture.ReadStreamForward(SecurityFixture.NormalAllStream, TestCredentials.TestUser1); + await Fixture.ReadStreamBackward(SecurityFixture.NormalAllStream, TestCredentials.TestUser1); + await Fixture.ReadEvent(SecurityFixture.NormalAllStream, TestCredentials.TestUser2); + await Fixture.ReadStreamForward(SecurityFixture.NormalAllStream, TestCredentials.TestUser2); + await Fixture.ReadStreamBackward(SecurityFixture.NormalAllStream, TestCredentials.TestUser2); } [Fact] public async Task reading_all_access_normal_stream_succeeds_when_admin_user_credentials_are_passed() { - await _fixture.AppendStream(SecurityFixture.NormalAllStream, TestCredentials.TestAdmin); - await _fixture.ReadEvent(SecurityFixture.NormalAllStream, TestCredentials.TestAdmin); - await _fixture.ReadStreamForward(SecurityFixture.NormalAllStream, TestCredentials.TestAdmin); - await _fixture.ReadStreamBackward(SecurityFixture.NormalAllStream, TestCredentials.TestAdmin); - } - - public class Fixture : SecurityFixture { - protected override Task When() => Task.CompletedTask; + await Fixture.AppendStream(SecurityFixture.NormalAllStream, TestCredentials.TestAdmin); + await Fixture.ReadEvent(SecurityFixture.NormalAllStream, TestCredentials.TestAdmin); + 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/stream_security_inheritance.cs b/test/EventStore.Client.Streams.Tests/Security/stream_security_inheritance.cs index 32a0798d2..292752f70 100644 --- a/test/EventStore.Client.Streams.Tests/Security/stream_security_inheritance.cs +++ b/test/EventStore.Client.Streams.Tests/Security/stream_security_inheritance.cs @@ -1,223 +1,182 @@ namespace EventStore.Client.Streams.Tests.Security; -public class stream_security_inheritance : IClassFixture { - readonly Fixture _fixture; +public class stream_security_inheritance : IClassFixture { + public stream_security_inheritance(ITestOutputHelper output, CustomFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); - public stream_security_inheritance(Fixture fixture) => _fixture = fixture; + CustomFixture Fixture { get; } [Fact] 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); - await Assert.ThrowsAsync( - () => - _fixture.AppendStream("user-no-acl", TestCredentials.TestUser2) - ); - - await _fixture.AppendStream("user-no-acl", TestCredentials.TestAdmin); - - await Assert.ThrowsAsync(() => _fixture.AppendStream("user-w-diff")); - await Assert.ThrowsAsync( - () => - _fixture.AppendStream("user-w-diff", TestCredentials.TestUser1) - ); - - await _fixture.AppendStream("user-w-diff", TestCredentials.TestUser2); - await _fixture.AppendStream("user-w-diff", TestCredentials.TestAdmin); - - await Assert.ThrowsAsync(() => _fixture.AppendStream("user-w-multiple")); - await _fixture.AppendStream("user-w-multiple", TestCredentials.TestUser1); - await _fixture.AppendStream("user-w-multiple", TestCredentials.TestUser2); - await _fixture.AppendStream("user-w-multiple", TestCredentials.TestAdmin); - - await Assert.ThrowsAsync( - () => - _fixture.AppendStream("user-w-restricted") - ); - - await Assert.ThrowsAsync( - () => - _fixture.AppendStream("user-w-restricted", TestCredentials.TestUser1) - ); - - await Assert.ThrowsAsync( - () => - _fixture.AppendStream("user-w-restricted", TestCredentials.TestUser2) - ); - - await _fixture.AppendStream("user-w-restricted", TestCredentials.TestAdmin); - - await _fixture.AppendStream("user-w-all", TestCredentials.TestUser1); - await _fixture.AppendStream("user-w-all", TestCredentials.TestUser2); - await _fixture.AppendStream("user-w-all", TestCredentials.TestAdmin); - - await _fixture.ReadEvent("user-no-acl", TestCredentials.TestUser1); - await _fixture.ReadEvent("user-no-acl", TestCredentials.TestUser2); - await _fixture.ReadEvent("user-no-acl", TestCredentials.TestAdmin); - - await Assert.ThrowsAsync(() => _fixture.ReadEvent("user-r-restricted")); - await _fixture.AppendStream("user-r-restricted", TestCredentials.TestUser1); - await _fixture.ReadEvent("user-r-restricted", TestCredentials.TestUser1); - await Assert.ThrowsAsync( - () => - _fixture.ReadEvent("user-r-restricted", TestCredentials.TestUser2) - ); - - await _fixture.ReadEvent("user-r-restricted", TestCredentials.TestAdmin); + await Assert.ThrowsAsync(() => Fixture.AppendStream("user-no-acl")); + await Fixture.AppendStream("user-no-acl", TestCredentials.TestUser1); + await Assert.ThrowsAsync(() => Fixture.AppendStream("user-no-acl", TestCredentials.TestUser2)); + + await Fixture.AppendStream("user-no-acl", TestCredentials.TestAdmin); + + await Assert.ThrowsAsync(() => Fixture.AppendStream("user-w-diff")); + await Assert.ThrowsAsync(() => Fixture.AppendStream("user-w-diff", TestCredentials.TestUser1)); + + await Fixture.AppendStream("user-w-diff", TestCredentials.TestUser2); + await Fixture.AppendStream("user-w-diff", TestCredentials.TestAdmin); + + await Assert.ThrowsAsync(() => Fixture.AppendStream("user-w-multiple")); + await Fixture.AppendStream("user-w-multiple", TestCredentials.TestUser1); + await Fixture.AppendStream("user-w-multiple", TestCredentials.TestUser2); + await Fixture.AppendStream("user-w-multiple", TestCredentials.TestAdmin); + + await Assert.ThrowsAsync(() => Fixture.AppendStream("user-w-restricted")); + + await Assert.ThrowsAsync(() => Fixture.AppendStream("user-w-restricted", TestCredentials.TestUser1)); + + await Assert.ThrowsAsync(() => Fixture.AppendStream("user-w-restricted", TestCredentials.TestUser2)); + + await Fixture.AppendStream("user-w-restricted", TestCredentials.TestAdmin); + + await Fixture.AppendStream("user-w-all", TestCredentials.TestUser1); + await Fixture.AppendStream("user-w-all", TestCredentials.TestUser2); + await Fixture.AppendStream("user-w-all", TestCredentials.TestAdmin); + + await Fixture.ReadEvent("user-no-acl", TestCredentials.TestUser1); + await Fixture.ReadEvent("user-no-acl", TestCredentials.TestUser2); + await Fixture.ReadEvent("user-no-acl", TestCredentials.TestAdmin); + + await Assert.ThrowsAsync(() => Fixture.ReadEvent("user-r-restricted")); + await Fixture.AppendStream("user-r-restricted", TestCredentials.TestUser1); + await Fixture.ReadEvent("user-r-restricted", TestCredentials.TestUser1); + await Assert.ThrowsAsync(() => Fixture.ReadEvent("user-r-restricted", TestCredentials.TestUser2)); + + await Fixture.ReadEvent("user-r-restricted", TestCredentials.TestAdmin); } [AnonymousAccess.Fact] public async Task acl_inheritance_is_working_properly_on_user_streams_when_not_authenticated() { - await _fixture.AppendStream("user-w-all"); + await Fixture.AppendStream("user-w-all"); // make sure the stream exists before trying to read it without authentication - await _fixture.AppendStream("user-no-acl", TestCredentials.TestAdmin); - await _fixture.ReadEvent("user-no-acl"); + await Fixture.AppendStream("user-no-acl", TestCredentials.TestAdmin); + await Fixture.ReadEvent("user-no-acl"); } [Fact] 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); - await Assert.ThrowsAsync( - () => - _fixture.AppendStream("$sys-no-acl", TestCredentials.TestUser2) - ); - - await _fixture.AppendStream("$sys-no-acl", TestCredentials.TestAdmin); - - await Assert.ThrowsAsync(() => _fixture.AppendStream("$sys-w-diff")); - await Assert.ThrowsAsync( - () => - _fixture.AppendStream("$sys-w-diff", TestCredentials.TestUser1) - ); - - await _fixture.AppendStream("$sys-w-diff", TestCredentials.TestUser2); - await _fixture.AppendStream("$sys-w-diff", TestCredentials.TestAdmin); - - await Assert.ThrowsAsync(() => _fixture.AppendStream("$sys-w-multiple")); - await _fixture.AppendStream("$sys-w-multiple", TestCredentials.TestUser1); - await _fixture.AppendStream("$sys-w-multiple", TestCredentials.TestUser2); - await _fixture.AppendStream("$sys-w-multiple", TestCredentials.TestAdmin); - - await Assert.ThrowsAsync( - () => - _fixture.AppendStream("$sys-w-restricted") - ); - - await Assert.ThrowsAsync( - () => - _fixture.AppendStream("$sys-w-restricted", TestCredentials.TestUser1) - ); - - await Assert.ThrowsAsync( - () => - _fixture.AppendStream("$sys-w-restricted", TestCredentials.TestUser2) - ); - - await _fixture.AppendStream("$sys-w-restricted", TestCredentials.TestAdmin); - - await _fixture.AppendStream("$sys-w-all", TestCredentials.TestUser1); - await _fixture.AppendStream("$sys-w-all", TestCredentials.TestUser2); - await _fixture.AppendStream("$sys-w-all", TestCredentials.TestAdmin); - - await Assert.ThrowsAsync(() => _fixture.ReadEvent("$sys-no-acl")); - await Assert.ThrowsAsync( - () => - _fixture.ReadEvent("$sys-no-acl", TestCredentials.TestUser1) - ); - - await Assert.ThrowsAsync( - () => - _fixture.ReadEvent("$sys-no-acl", TestCredentials.TestUser2) - ); - - await _fixture.ReadEvent("$sys-no-acl", TestCredentials.TestAdmin); + await Assert.ThrowsAsync(() => Fixture.AppendStream("$sys-no-acl")); + await Fixture.AppendStream("$sys-no-acl", TestCredentials.TestUser1); + await Assert.ThrowsAsync(() => Fixture.AppendStream("$sys-no-acl", TestCredentials.TestUser2)); + + await Fixture.AppendStream("$sys-no-acl", TestCredentials.TestAdmin); + + await Assert.ThrowsAsync(() => Fixture.AppendStream("$sys-w-diff")); + await Assert.ThrowsAsync(() => Fixture.AppendStream("$sys-w-diff", TestCredentials.TestUser1)); + + await Fixture.AppendStream("$sys-w-diff", TestCredentials.TestUser2); + await Fixture.AppendStream("$sys-w-diff", TestCredentials.TestAdmin); + + await Assert.ThrowsAsync(() => Fixture.AppendStream("$sys-w-multiple")); + await Fixture.AppendStream("$sys-w-multiple", TestCredentials.TestUser1); + await Fixture.AppendStream("$sys-w-multiple", TestCredentials.TestUser2); + await Fixture.AppendStream("$sys-w-multiple", TestCredentials.TestAdmin); + + await Assert.ThrowsAsync(() => Fixture.AppendStream("$sys-w-restricted")); + await Assert.ThrowsAsync(() => Fixture.AppendStream("$sys-w-restricted", TestCredentials.TestUser1)); + await Assert.ThrowsAsync(() => Fixture.AppendStream("$sys-w-restricted", TestCredentials.TestUser2)); + + await Fixture.AppendStream("$sys-w-restricted", TestCredentials.TestAdmin); + + await Fixture.AppendStream("$sys-w-all", TestCredentials.TestUser1); + await Fixture.AppendStream("$sys-w-all", TestCredentials.TestUser2); + await Fixture.AppendStream("$sys-w-all", TestCredentials.TestAdmin); + + await Assert.ThrowsAsync(() => Fixture.ReadEvent("$sys-no-acl")); + await Assert.ThrowsAsync(() => Fixture.ReadEvent("$sys-no-acl", TestCredentials.TestUser1)); + + await Assert.ThrowsAsync(() => Fixture.ReadEvent("$sys-no-acl", TestCredentials.TestUser2)); + + await Fixture.ReadEvent("$sys-no-acl", TestCredentials.TestAdmin); } [AnonymousAccess.Fact] - public async Task acl_inheritance_is_working_properly_on_system_streams_when_not_authenticated() => await _fixture.AppendStream("$sys-w-all"); + public async Task acl_inheritance_is_working_properly_on_system_streams_when_not_authenticated() => await Fixture.AppendStream("$sys-w-all"); - public class Fixture : SecurityFixture { + public class CustomFixture : SecurityFixture { protected override async Task When() { var settings = new SystemSettings( new(writeRole: "user1"), new(writeRole: "user1") ); - await Client.SetSystemSettingsAsync(settings, userCredentials: TestCredentials.TestAdmin); + await Streams.SetSystemSettingsAsync(settings, userCredentials: TestCredentials.TestAdmin); - await Client.SetStreamMetadataAsync( + await Streams.SetStreamMetadataAsync( "user-no-acl", StreamState.NoStream, new(), userCredentials: TestCredentials.TestAdmin ); - await Client.SetStreamMetadataAsync( + await Streams.SetStreamMetadataAsync( "user-w-diff", StreamState.NoStream, new(acl: new(writeRole: "user2")), userCredentials: TestCredentials.TestAdmin ); - await Client.SetStreamMetadataAsync( + await Streams.SetStreamMetadataAsync( "user-w-multiple", StreamState.NoStream, new(acl: new(writeRoles: new[] { "user1", "user2" })), userCredentials: TestCredentials.TestAdmin ); - await Client.SetStreamMetadataAsync( + await Streams.SetStreamMetadataAsync( "user-w-restricted", StreamState.NoStream, - new(acl: new(writeRoles: new string[0])), + new(acl: new(writeRoles: Array.Empty())), userCredentials: TestCredentials.TestAdmin ); - await Client.SetStreamMetadataAsync( + await Streams.SetStreamMetadataAsync( "user-w-all", StreamState.NoStream, new(acl: new(writeRole: SystemRoles.All)), userCredentials: TestCredentials.TestAdmin ); - await Client.SetStreamMetadataAsync( + await Streams.SetStreamMetadataAsync( "user-r-restricted", StreamState.NoStream, new(acl: new("user1")), userCredentials: TestCredentials.TestAdmin ); - await Client.SetStreamMetadataAsync( + await Streams.SetStreamMetadataAsync( "$sys-no-acl", StreamState.NoStream, new(), userCredentials: TestCredentials.TestAdmin ); - await Client.SetStreamMetadataAsync( + await Streams.SetStreamMetadataAsync( "$sys-w-diff", StreamState.NoStream, new(acl: new(writeRole: "user2")), userCredentials: TestCredentials.TestAdmin ); - await Client.SetStreamMetadataAsync( + await Streams.SetStreamMetadataAsync( "$sys-w-multiple", StreamState.NoStream, new(acl: new(writeRoles: new[] { "user1", "user2" })), userCredentials: TestCredentials.TestAdmin ); - await Client.SetStreamMetadataAsync( + await Streams.SetStreamMetadataAsync( "$sys-w-restricted", StreamState.NoStream, - new(acl: new(writeRoles: new string[0])), + new(acl: new(writeRoles: Array.Empty())), userCredentials: TestCredentials.TestAdmin ); - await Client.SetStreamMetadataAsync( + await Streams.SetStreamMetadataAsync( "$sys-w-all", StreamState.NoStream, new(acl: new(writeRole: SystemRoles.All)), diff --git a/test/EventStore.Client.Streams.Tests/Security/subscribe_to_all_security.cs b/test/EventStore.Client.Streams.Tests/Security/subscribe_to_all_security.cs index a8948b8e4..d9d3dd981 100644 --- a/test/EventStore.Client.Streams.Tests/Security/subscribe_to_all_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/subscribe_to_all_security.cs @@ -1,28 +1,24 @@ namespace EventStore.Client.Streams.Tests.Security; -public class subscribe_to_all_security : IClassFixture { - readonly Fixture _fixture; +public class subscribe_to_all_security : IClassFixture { + public subscribe_to_all_security(ITestOutputHelper output, SecurityFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); - public subscribe_to_all_security(Fixture fixture) => _fixture = fixture; + SecurityFixture Fixture { get; } [Fact] public async Task subscribing_to_all_with_not_existing_credentials_is_not_authenticated() => - await Assert.ThrowsAsync(() => _fixture.SubscribeToAll(TestCredentials.TestBadUser)); + await Assert.ThrowsAsync(() => Fixture.SubscribeToAll(TestCredentials.TestBadUser)); [Fact] - public async Task subscribing_to_all_with_no_credentials_is_denied() => await Assert.ThrowsAsync(() => _fixture.SubscribeToAll()); + public async Task subscribing_to_all_with_no_credentials_is_denied() => await Assert.ThrowsAsync(() => Fixture.SubscribeToAll()); [Fact] public async Task subscribing_to_all_with_not_authorized_user_credentials_is_denied() => - await Assert.ThrowsAsync(() => _fixture.SubscribeToAll(TestCredentials.TestUser2)); + await Assert.ThrowsAsync(() => Fixture.SubscribeToAll(TestCredentials.TestUser2)); [Fact] - public async Task subscribing_to_all_with_authorized_user_credentials_succeeds() => await _fixture.SubscribeToAll(TestCredentials.TestUser1); + public async Task subscribing_to_all_with_authorized_user_credentials_succeeds() => await Fixture.SubscribeToAll(TestCredentials.TestUser1); [Fact] - public async Task subscribing_to_all_with_admin_user_credentials_succeeds() => await _fixture.SubscribeToAll(TestCredentials.TestAdmin); - - public class Fixture : SecurityFixture { - protected override Task When() => Task.CompletedTask; - } + 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.Streams.Tests/Security/subscribe_to_stream_security.cs index 10f046629..f9ebc0b1a 100644 --- a/test/EventStore.Client.Streams.Tests/Security/subscribe_to_stream_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/subscribe_to_stream_security.cs @@ -1,98 +1,77 @@ namespace EventStore.Client.Streams.Tests.Security; -public class subscribe_to_stream_security : IClassFixture { - readonly Fixture _fixture; +public class subscribe_to_stream_security : IClassFixture { + public subscribe_to_stream_security(ITestOutputHelper output, SecurityFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); - public subscribe_to_stream_security(Fixture fixture) => _fixture = fixture; + SecurityFixture Fixture { get; } [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() => - await Assert.ThrowsAsync( - () => - _fixture.SubscribeToStream(SecurityFixture.ReadStream) - ); + await Assert.ThrowsAsync(() => Fixture.SubscribeToStream(SecurityFixture.ReadStream)); [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() { - await _fixture.AppendStream(SecurityFixture.ReadStream, TestCredentials.TestUser1); - await _fixture.SubscribeToStream(SecurityFixture.ReadStream, TestCredentials.TestUser1); + await Fixture.AppendStream(SecurityFixture.ReadStream, TestCredentials.TestUser1); + await Fixture.SubscribeToStream(SecurityFixture.ReadStream, TestCredentials.TestUser1); } [Fact] public async Task reading_stream_with_admin_user_credentials_succeeds() { - await _fixture.AppendStream(SecurityFixture.ReadStream, TestCredentials.TestAdmin); - await _fixture.SubscribeToStream(SecurityFixture.ReadStream, TestCredentials.TestAdmin); + await Fixture.AppendStream(SecurityFixture.ReadStream, TestCredentials.TestAdmin); + await Fixture.SubscribeToStream(SecurityFixture.ReadStream, TestCredentials.TestAdmin); } [AnonymousAccess.Fact] public async Task subscribing_to_no_acl_stream_succeeds_when_no_credentials_are_passed() { - await _fixture.AppendStream(SecurityFixture.NoAclStream); - await _fixture.SubscribeToStream(SecurityFixture.NoAclStream); + await Fixture.AppendStream(SecurityFixture.NoAclStream); + await Fixture.SubscribeToStream(SecurityFixture.NoAclStream); } [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() { - await _fixture.AppendStream(SecurityFixture.NoAclStream, TestCredentials.TestUser1); - await _fixture.SubscribeToStream(SecurityFixture.NoAclStream, TestCredentials.TestUser1); - await _fixture.SubscribeToStream(SecurityFixture.NoAclStream, TestCredentials.TestUser2); + await Fixture.AppendStream(SecurityFixture.NoAclStream, TestCredentials.TestUser1); + await Fixture.SubscribeToStream(SecurityFixture.NoAclStream, TestCredentials.TestUser1); + await Fixture.SubscribeToStream(SecurityFixture.NoAclStream, TestCredentials.TestUser2); } [Fact] public async Task subscribing_to_no_acl_stream_succeeds_when_admin_user_credentials_are_passed() { - await _fixture.AppendStream(SecurityFixture.NoAclStream, TestCredentials.TestAdmin); - await _fixture.SubscribeToStream(SecurityFixture.NoAclStream, TestCredentials.TestAdmin); + await Fixture.AppendStream(SecurityFixture.NoAclStream, TestCredentials.TestAdmin); + await Fixture.SubscribeToStream(SecurityFixture.NoAclStream, TestCredentials.TestAdmin); } [AnonymousAccess.Fact] public async Task subscribing_to_all_access_normal_stream_succeeds_when_no_credentials_are_passed() { - await _fixture.AppendStream(SecurityFixture.NormalAllStream); - await _fixture.SubscribeToStream(SecurityFixture.NormalAllStream); + await Fixture.AppendStream(SecurityFixture.NormalAllStream); + await Fixture.SubscribeToStream(SecurityFixture.NormalAllStream); } [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) - ); + 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)); [Fact] - public async Task - subscribing_to_all_access_normal_stream_succeeds_when_any_existing_user_credentials_are_passed() { - await _fixture.AppendStream(SecurityFixture.NormalAllStream, TestCredentials.TestUser1); - await _fixture.SubscribeToStream(SecurityFixture.NormalAllStream, TestCredentials.TestUser1); - await _fixture.SubscribeToStream(SecurityFixture.NormalAllStream, TestCredentials.TestUser2); + public async Task subscribing_to_all_access_normal_stream_succeeds_when_any_existing_user_credentials_are_passed() { + await Fixture.AppendStream(SecurityFixture.NormalAllStream, TestCredentials.TestUser1); + await Fixture.SubscribeToStream(SecurityFixture.NormalAllStream, TestCredentials.TestUser1); + await Fixture.SubscribeToStream(SecurityFixture.NormalAllStream, TestCredentials.TestUser2); } [Fact] public async Task subscribing_to_all_access_normal_streamm_succeeds_when_admin_user_credentials_are_passed() { - await _fixture.AppendStream(SecurityFixture.NormalAllStream, TestCredentials.TestAdmin); - await _fixture.SubscribeToStream(SecurityFixture.NormalAllStream, TestCredentials.TestAdmin); - } - - public class Fixture : SecurityFixture { - protected override Task When() => Task.CompletedTask; + await Fixture.AppendStream(SecurityFixture.NormalAllStream, TestCredentials.TestAdmin); + await Fixture.SubscribeToStream(SecurityFixture.NormalAllStream, TestCredentials.TestAdmin); } } \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/Security/system_stream_security.cs b/test/EventStore.Client.Streams.Tests/Security/system_stream_security.cs index 9b975de20..b1d217bf4 100644 --- a/test/EventStore.Client.Streams.Tests/Security/system_stream_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/system_stream_security.cs @@ -1,170 +1,148 @@ namespace EventStore.Client.Streams.Tests.Security; -public class system_stream_security : IClassFixture { - readonly Fixture _fixture; +public class system_stream_security : IClassFixture { + public system_stream_security(ITestOutputHelper output, SecurityFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); - public system_stream_security(Fixture fixture) => _fixture = fixture; + SecurityFixture Fixture { get; } [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.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.ReadStreamBackward("$system-no-acl", TestCredentials.TestUser1)); - await Assert.ThrowsAsync(() => _fixture.AppendStream("$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.ReadMeta("$system-no-acl", TestCredentials.TestUser1)); + await Assert.ThrowsAsync(() => Fixture.WriteMeta("$system-no-acl", TestCredentials.TestUser1)); - await Assert.ThrowsAsync( - () => - _fixture.SubscribeToStream("$system-no-acl", TestCredentials.TestUser1) - ); + await Assert.ThrowsAsync(() => Fixture.SubscribeToStream("$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.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.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.ReadMeta("$system-no-acl", TestCredentials.TestAdmin); + await Fixture.WriteMeta("$system-no-acl", TestCredentials.TestAdmin); - await _fixture.SubscribeToStream("$system-no-acl", TestCredentials.TestAdmin); + await Fixture.SubscribeToStream("$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.SystemAclStream, TestCredentials.TestUser2)); - await Assert.ThrowsAsync(() => _fixture.ReadStreamForward(SecurityFixture.SystemAclStream, TestCredentials.TestUser2)); - await Assert.ThrowsAsync( - () => - _fixture.ReadStreamBackward(SecurityFixture.SystemAclStream, TestCredentials.TestUser2) - ); + await Assert.ThrowsAsync(() => Fixture.ReadEvent(SecurityFixture.SystemAclStream, TestCredentials.TestUser2)); + await Assert.ThrowsAsync(() => Fixture.ReadStreamForward(SecurityFixture.SystemAclStream, TestCredentials.TestUser2)); + await Assert.ThrowsAsync(() => Fixture.ReadStreamBackward(SecurityFixture.SystemAclStream, TestCredentials.TestUser2)); - await Assert.ThrowsAsync(() => _fixture.AppendStream(SecurityFixture.SystemAclStream, TestCredentials.TestUser2)); + 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.ReadMeta(SecurityFixture.SystemAclStream, TestCredentials.TestUser2)); + await Assert.ThrowsAsync(() => Fixture.WriteMeta(SecurityFixture.SystemAclStream, TestCredentials.TestUser2, TestCredentials.TestUser1.Username)); - await Assert.ThrowsAsync(() => _fixture.SubscribeToStream(SecurityFixture.SystemAclStream, TestCredentials.TestUser2)); + await Assert.ThrowsAsync(() => Fixture.SubscribeToStream(SecurityFixture.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.SystemAclStream, TestCredentials.TestUser1); - await _fixture.ReadEvent(SecurityFixture.SystemAclStream, TestCredentials.TestUser1); - await _fixture.ReadStreamForward(SecurityFixture.SystemAclStream, TestCredentials.TestUser1); - await _fixture.ReadStreamBackward(SecurityFixture.SystemAclStream, TestCredentials.TestUser1); + await Fixture.AppendStream(SecurityFixture.SystemAclStream, TestCredentials.TestUser1); + await Fixture.ReadEvent(SecurityFixture.SystemAclStream, TestCredentials.TestUser1); + await Fixture.ReadStreamForward(SecurityFixture.SystemAclStream, TestCredentials.TestUser1); + await Fixture.ReadStreamBackward(SecurityFixture.SystemAclStream, TestCredentials.TestUser1); - await _fixture.ReadMeta(SecurityFixture.SystemAclStream, TestCredentials.TestUser1); - await _fixture.WriteMeta(SecurityFixture.SystemAclStream, TestCredentials.TestUser1, TestCredentials.TestUser1.Username); + await Fixture.ReadMeta(SecurityFixture.SystemAclStream, TestCredentials.TestUser1); + await Fixture.WriteMeta(SecurityFixture.SystemAclStream, TestCredentials.TestUser1, TestCredentials.TestUser1.Username); - await _fixture.SubscribeToStream(SecurityFixture.SystemAclStream, TestCredentials.TestUser1); + await Fixture.SubscribeToStream(SecurityFixture.SystemAclStream, TestCredentials.TestUser1); } [Fact] public async Task operations_on_system_stream_with_acl_set_to_usual_user_succeed_for_admin() { - await _fixture.AppendStream(SecurityFixture.SystemAclStream, TestCredentials.TestAdmin); - await _fixture.ReadEvent(SecurityFixture.SystemAclStream, TestCredentials.TestAdmin); - await _fixture.ReadStreamForward(SecurityFixture.SystemAclStream, TestCredentials.TestAdmin); - await _fixture.ReadStreamBackward(SecurityFixture.SystemAclStream, TestCredentials.TestAdmin); + await Fixture.AppendStream(SecurityFixture.SystemAclStream, TestCredentials.TestAdmin); + await Fixture.ReadEvent(SecurityFixture.SystemAclStream, TestCredentials.TestAdmin); + await Fixture.ReadStreamForward(SecurityFixture.SystemAclStream, TestCredentials.TestAdmin); + await Fixture.ReadStreamBackward(SecurityFixture.SystemAclStream, TestCredentials.TestAdmin); - await _fixture.ReadMeta(SecurityFixture.SystemAclStream, TestCredentials.TestAdmin); - await _fixture.WriteMeta(SecurityFixture.SystemAclStream, TestCredentials.TestAdmin, TestCredentials.TestUser1.Username); + await Fixture.ReadMeta(SecurityFixture.SystemAclStream, TestCredentials.TestAdmin); + await Fixture.WriteMeta(SecurityFixture.SystemAclStream, TestCredentials.TestAdmin, TestCredentials.TestUser1.Username); - await _fixture.SubscribeToStream(SecurityFixture.SystemAclStream, TestCredentials.TestAdmin); + await Fixture.SubscribeToStream(SecurityFixture.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.SystemAdminStream, TestCredentials.TestUser1)); - await Assert.ThrowsAsync(() => _fixture.ReadStreamForward(SecurityFixture.SystemAdminStream, TestCredentials.TestUser1)); + await Assert.ThrowsAsync(() => Fixture.ReadEvent(SecurityFixture.SystemAdminStream, TestCredentials.TestUser1)); + await Assert.ThrowsAsync(() => Fixture.ReadStreamForward(SecurityFixture.SystemAdminStream, TestCredentials.TestUser1)); await Assert.ThrowsAsync( () => - _fixture.ReadStreamBackward(SecurityFixture.SystemAdminStream, TestCredentials.TestUser1) + Fixture.ReadStreamBackward(SecurityFixture.SystemAdminStream, TestCredentials.TestUser1) ); - await Assert.ThrowsAsync(() => _fixture.AppendStream(SecurityFixture.SystemAdminStream, TestCredentials.TestUser1)); + await Assert.ThrowsAsync(() => Fixture.AppendStream(SecurityFixture.SystemAdminStream, TestCredentials.TestUser1)); - await Assert.ThrowsAsync(() => _fixture.ReadMeta(SecurityFixture.SystemAdminStream, TestCredentials.TestUser1)); + await Assert.ThrowsAsync(() => Fixture.ReadMeta(SecurityFixture.SystemAdminStream, TestCredentials.TestUser1)); await Assert.ThrowsAsync( () => - _fixture.WriteMeta(SecurityFixture.SystemAdminStream, TestCredentials.TestUser1, SystemRoles.Admins) + Fixture.WriteMeta(SecurityFixture.SystemAdminStream, TestCredentials.TestUser1, SystemRoles.Admins) ); - await Assert.ThrowsAsync(() => _fixture.SubscribeToStream(SecurityFixture.SystemAdminStream, TestCredentials.TestUser1)); + await Assert.ThrowsAsync(() => Fixture.SubscribeToStream(SecurityFixture.SystemAdminStream, TestCredentials.TestUser1)); } [Fact] public async Task operations_on_system_stream_with_acl_set_to_admins_succeed_for_admin() { - await _fixture.AppendStream(SecurityFixture.SystemAdminStream, TestCredentials.TestAdmin); - await _fixture.ReadEvent(SecurityFixture.SystemAdminStream, TestCredentials.TestAdmin); - await _fixture.ReadStreamForward(SecurityFixture.SystemAdminStream, TestCredentials.TestAdmin); - await _fixture.ReadStreamBackward(SecurityFixture.SystemAdminStream, TestCredentials.TestAdmin); + await Fixture.AppendStream(SecurityFixture.SystemAdminStream, TestCredentials.TestAdmin); + await Fixture.ReadEvent(SecurityFixture.SystemAdminStream, TestCredentials.TestAdmin); + await Fixture.ReadStreamForward(SecurityFixture.SystemAdminStream, TestCredentials.TestAdmin); + await Fixture.ReadStreamBackward(SecurityFixture.SystemAdminStream, TestCredentials.TestAdmin); - await _fixture.ReadMeta(SecurityFixture.SystemAdminStream, TestCredentials.TestAdmin); - await _fixture.WriteMeta(SecurityFixture.SystemAdminStream, TestCredentials.TestAdmin, SystemRoles.Admins); + await Fixture.ReadMeta(SecurityFixture.SystemAdminStream, TestCredentials.TestAdmin); + await Fixture.WriteMeta(SecurityFixture.SystemAdminStream, TestCredentials.TestAdmin, SystemRoles.Admins); - await _fixture.SubscribeToStream(SecurityFixture.SystemAdminStream, TestCredentials.TestAdmin); + await Fixture.SubscribeToStream(SecurityFixture.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.SystemAllStream); - await _fixture.ReadEvent(SecurityFixture.SystemAllStream); - await _fixture.ReadStreamForward(SecurityFixture.SystemAllStream); - await _fixture.ReadStreamBackward(SecurityFixture.SystemAllStream); + await Fixture.AppendStream(SecurityFixture.SystemAllStream); + await Fixture.ReadEvent(SecurityFixture.SystemAllStream); + await Fixture.ReadStreamForward(SecurityFixture.SystemAllStream); + await Fixture.ReadStreamBackward(SecurityFixture.SystemAllStream); - await _fixture.ReadMeta(SecurityFixture.SystemAllStream); - await _fixture.WriteMeta(SecurityFixture.SystemAllStream, role: SystemRoles.All); + await Fixture.ReadMeta(SecurityFixture.SystemAllStream); + await Fixture.WriteMeta(SecurityFixture.SystemAllStream, role: SystemRoles.All); - await _fixture.SubscribeToStream(SecurityFixture.SystemAllStream); + await Fixture.SubscribeToStream(SecurityFixture.SystemAllStream); } [Fact] public async Task operations_on_system_stream_with_acl_set_to_all_succeed_for_usual_user() { - await _fixture.AppendStream(SecurityFixture.SystemAllStream, TestCredentials.TestUser1); - await _fixture.ReadEvent(SecurityFixture.SystemAllStream, TestCredentials.TestUser1); - await _fixture.ReadStreamForward(SecurityFixture.SystemAllStream, TestCredentials.TestUser1); - await _fixture.ReadStreamBackward(SecurityFixture.SystemAllStream, TestCredentials.TestUser1); + await Fixture.AppendStream(SecurityFixture.SystemAllStream, TestCredentials.TestUser1); + await Fixture.ReadEvent(SecurityFixture.SystemAllStream, TestCredentials.TestUser1); + await Fixture.ReadStreamForward(SecurityFixture.SystemAllStream, TestCredentials.TestUser1); + await Fixture.ReadStreamBackward(SecurityFixture.SystemAllStream, TestCredentials.TestUser1); - await _fixture.ReadMeta(SecurityFixture.SystemAllStream, TestCredentials.TestUser1); - await _fixture.WriteMeta(SecurityFixture.SystemAllStream, TestCredentials.TestUser1, SystemRoles.All); + await Fixture.ReadMeta(SecurityFixture.SystemAllStream, TestCredentials.TestUser1); + await Fixture.WriteMeta(SecurityFixture.SystemAllStream, TestCredentials.TestUser1, SystemRoles.All); - await _fixture.SubscribeToStream(SecurityFixture.SystemAllStream, TestCredentials.TestUser1); + await Fixture.SubscribeToStream(SecurityFixture.SystemAllStream, TestCredentials.TestUser1); } [Fact] public async Task operations_on_system_stream_with_acl_set_to_all_succeed_for_admin() { - await _fixture.AppendStream(SecurityFixture.SystemAllStream, TestCredentials.TestAdmin); - await _fixture.ReadEvent(SecurityFixture.SystemAllStream, TestCredentials.TestAdmin); - await _fixture.ReadStreamForward(SecurityFixture.SystemAllStream, TestCredentials.TestAdmin); - await _fixture.ReadStreamBackward(SecurityFixture.SystemAllStream, TestCredentials.TestAdmin); + await Fixture.AppendStream(SecurityFixture.SystemAllStream, TestCredentials.TestAdmin); + await Fixture.ReadEvent(SecurityFixture.SystemAllStream, TestCredentials.TestAdmin); + await Fixture.ReadStreamForward(SecurityFixture.SystemAllStream, TestCredentials.TestAdmin); + await Fixture.ReadStreamBackward(SecurityFixture.SystemAllStream, TestCredentials.TestAdmin); - await _fixture.ReadMeta(SecurityFixture.SystemAllStream, TestCredentials.TestAdmin); - await _fixture.WriteMeta(SecurityFixture.SystemAllStream, TestCredentials.TestAdmin, SystemRoles.All); - - await _fixture.SubscribeToStream(SecurityFixture.SystemAllStream, TestCredentials.TestAdmin); - } + await Fixture.ReadMeta(SecurityFixture.SystemAllStream, TestCredentials.TestAdmin); + await Fixture.WriteMeta(SecurityFixture.SystemAllStream, TestCredentials.TestAdmin, SystemRoles.All); - public class Fixture : SecurityFixture { - protected override Task When() => Task.CompletedTask; + await Fixture.SubscribeToStream(SecurityFixture.SystemAllStream, TestCredentials.TestAdmin); } } \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/Security/write_stream_meta_security.cs b/test/EventStore.Client.Streams.Tests/Security/write_stream_meta_security.cs index 5a072214e..f53678604 100644 --- a/test/EventStore.Client.Streams.Tests/Security/write_stream_meta_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/write_stream_meta_security.cs @@ -1,15 +1,15 @@ namespace EventStore.Client.Streams.Tests.Security; -public class write_stream_meta_security : IClassFixture { - readonly Fixture _fixture; +public class write_stream_meta_security : IClassFixture { + public write_stream_meta_security(ITestOutputHelper output, SecurityFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); - public write_stream_meta_security(Fixture fixture) => _fixture = fixture; + SecurityFixture Fixture { get; } [Fact] public async Task writing_meta_with_not_existing_credentials_is_not_authenticated() => await Assert.ThrowsAsync( () => - _fixture.WriteMeta( + Fixture.WriteMeta( SecurityFixture.MetaWriteStream, TestCredentials.TestBadUser, TestCredentials.TestUser1.Username @@ -18,16 +18,12 @@ await Assert.ThrowsAsync( [Fact] public async Task writing_meta_to_stream_with_no_credentials_is_denied() => - await Assert.ThrowsAsync( - () => - _fixture.WriteMeta(SecurityFixture.MetaWriteStream, role: TestCredentials.TestUser1.Username) - ); + await Assert.ThrowsAsync(() => Fixture.WriteMeta(SecurityFixture.MetaWriteStream, role: TestCredentials.TestUser1.Username)); [Fact] public async Task writing_meta_to_stream_with_not_authorized_user_credentials_is_denied() => - await Assert.ThrowsAsync( - () => - _fixture.WriteMeta( + await Assert.ThrowsAsync(() => + Fixture.WriteMeta( SecurityFixture.MetaWriteStream, TestCredentials.TestUser2, TestCredentials.TestUser1.Username @@ -36,7 +32,7 @@ await Assert.ThrowsAsync( [Fact] public async Task writing_meta_to_stream_with_authorized_user_credentials_succeeds() => - await _fixture.WriteMeta( + await Fixture.WriteMeta( SecurityFixture.MetaWriteStream, TestCredentials.TestUser1, TestCredentials.TestUser1.Username @@ -44,57 +40,45 @@ await _fixture.WriteMeta( [Fact] public async Task writing_meta_to_stream_with_admin_user_credentials_succeeds() => - await _fixture.WriteMeta( + await Fixture.WriteMeta( SecurityFixture.MetaWriteStream, TestCredentials.TestAdmin, TestCredentials.TestUser1.Username ); [AnonymousAccess.Fact] - public async Task writing_meta_to_no_acl_stream_succeeds_when_no_credentials_are_passed() => await _fixture.WriteMeta(SecurityFixture.NoAclStream); + public async Task writing_meta_to_no_acl_stream_succeeds_when_no_credentials_are_passed() => await Fixture.WriteMeta(SecurityFixture.NoAclStream); [Fact] - public async Task - writing_meta_to_no_acl_stream_is_not_authenticated_when_not_existing_credentials_are_passed() => - await Assert.ThrowsAsync( - () => - _fixture.WriteMeta(SecurityFixture.NoAclStream, TestCredentials.TestBadUser) - ); + public async Task writing_meta_to_no_acl_stream_is_not_authenticated_when_not_existing_credentials_are_passed() => + await Assert.ThrowsAsync(() => Fixture.WriteMeta(SecurityFixture.NoAclStream, TestCredentials.TestBadUser)); [Fact] public async Task writing_meta_to_no_acl_stream_succeeds_when_any_existing_user_credentials_are_passed() { - await _fixture.WriteMeta(SecurityFixture.NoAclStream, TestCredentials.TestUser1); - await _fixture.WriteMeta(SecurityFixture.NoAclStream, TestCredentials.TestUser2); + await Fixture.WriteMeta(SecurityFixture.NoAclStream, TestCredentials.TestUser1); + await Fixture.WriteMeta(SecurityFixture.NoAclStream, TestCredentials.TestUser2); } [Fact] public async Task writing_meta_to_no_acl_stream_succeeds_when_admin_user_credentials_are_passed() => - await _fixture.WriteMeta(SecurityFixture.NoAclStream, TestCredentials.TestAdmin); + await Fixture.WriteMeta(SecurityFixture.NoAclStream, TestCredentials.TestAdmin); [AnonymousAccess.Fact] public async Task writing_meta_to_all_access_normal_stream_succeeds_when_no_credentials_are_passed() => - await _fixture.WriteMeta(SecurityFixture.NormalAllStream, role: SystemRoles.All); + await Fixture.WriteMeta(SecurityFixture.NormalAllStream, role: SystemRoles.All); [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) - ); + 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)); [Fact] public async Task writing_meta_to_all_access_normal_stream_succeeds_when_any_existing_user_credentials_are_passed() { - await _fixture.WriteMeta(SecurityFixture.NormalAllStream, TestCredentials.TestUser1, SystemRoles.All); - await _fixture.WriteMeta(SecurityFixture.NormalAllStream, TestCredentials.TestUser2, SystemRoles.All); + await Fixture.WriteMeta(SecurityFixture.NormalAllStream, TestCredentials.TestUser1, SystemRoles.All); + await Fixture.WriteMeta(SecurityFixture.NormalAllStream, TestCredentials.TestUser2, SystemRoles.All); } [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); - - public class Fixture : SecurityFixture { - protected override Task When() => Task.CompletedTask; - } + 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.Streams.Tests/Security/write_stream_security.cs index 44ac88aa7..36a4085a5 100644 --- a/test/EventStore.Client.Streams.Tests/Security/write_stream_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/write_stream_security.cs @@ -1,89 +1,70 @@ namespace EventStore.Client.Streams.Tests.Security; -public class write_stream_security : IClassFixture { - readonly Fixture _fixture; +public class write_stream_security : IClassFixture { + public write_stream_security(ITestOutputHelper output, SecurityFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); - public write_stream_security(Fixture fixture, ITestOutputHelper outputHelper) { - _fixture = fixture; - _fixture.CaptureLogs(outputHelper); - } + SecurityFixture Fixture { get; } [Fact] public async Task writing_to_all_is_never_allowed() { - await Assert.ThrowsAsync(() => _fixture.AppendStream(SecurityFixture.AllStream)); - await Assert.ThrowsAsync( - () => _fixture.AppendStream(SecurityFixture.AllStream, TestCredentials.TestUser1) - ); - - await Assert.ThrowsAsync( - () => _fixture.AppendStream(SecurityFixture.AllStream, TestCredentials.TestAdmin) - ); + await Assert.ThrowsAsync(() => Fixture.AppendStream(SecurityFixture.AllStream)); + await Assert.ThrowsAsync(() => Fixture.AppendStream(SecurityFixture.AllStream, TestCredentials.TestUser1)); + await Assert.ThrowsAsync(() => Fixture.AppendStream(SecurityFixture.AllStream, TestCredentials.TestAdmin)); } [Fact] public async Task writing_with_not_existing_credentials_is_not_authenticated() => - await Assert.ThrowsAsync( - () => _fixture.AppendStream(SecurityFixture.WriteStream, TestCredentials.TestBadUser) - ); + await Assert.ThrowsAsync(() => Fixture.AppendStream(SecurityFixture.WriteStream, TestCredentials.TestBadUser)); [Fact] public async Task writing_to_stream_with_no_credentials_is_denied() => - await Assert.ThrowsAsync(() => _fixture.AppendStream(SecurityFixture.WriteStream)); + await Assert.ThrowsAsync(() => Fixture.AppendStream(SecurityFixture.WriteStream)); [Fact] public async Task writing_to_stream_with_not_authorized_user_credentials_is_denied() => - await Assert.ThrowsAsync( - () => _fixture.AppendStream(SecurityFixture.WriteStream, TestCredentials.TestUser2) - ); + await Assert.ThrowsAsync(() => Fixture.AppendStream(SecurityFixture.WriteStream, TestCredentials.TestUser2)); [Fact] public async Task writing_to_stream_with_authorized_user_credentials_succeeds() => - await _fixture.AppendStream(SecurityFixture.WriteStream, TestCredentials.TestUser1); + await Fixture.AppendStream(SecurityFixture.WriteStream, TestCredentials.TestUser1); [Fact] public async Task writing_to_stream_with_admin_user_credentials_succeeds() => - await _fixture.AppendStream(SecurityFixture.WriteStream, TestCredentials.TestAdmin); + await Fixture.AppendStream(SecurityFixture.WriteStream, TestCredentials.TestAdmin); [AnonymousAccess.Fact] - public async Task writing_to_no_acl_stream_succeeds_when_no_credentials_are_passed() => await _fixture.AppendStream(SecurityFixture.NoAclStream); + public async Task writing_to_no_acl_stream_succeeds_when_no_credentials_are_passed() => await Fixture.AppendStream(SecurityFixture.NoAclStream); [Fact] public async Task writing_to_no_acl_stream_is_not_authenticated_when_not_existing_credentials_are_passed() => - await Assert.ThrowsAsync( - () => - _fixture.AppendStream(SecurityFixture.NoAclStream, TestCredentials.TestBadUser) - ); + await Assert.ThrowsAsync(() => Fixture.AppendStream(SecurityFixture.NoAclStream, TestCredentials.TestBadUser)); [Fact] public async Task writing_to_no_acl_stream_succeeds_when_any_existing_user_credentials_are_passed() { - await _fixture.AppendStream(SecurityFixture.NoAclStream, TestCredentials.TestUser1); - await _fixture.AppendStream(SecurityFixture.NoAclStream, TestCredentials.TestUser2); + await Fixture.AppendStream(SecurityFixture.NoAclStream, TestCredentials.TestUser1); + await Fixture.AppendStream(SecurityFixture.NoAclStream, TestCredentials.TestUser2); } [Fact] public async Task writing_to_no_acl_stream_succeeds_when_any_admin_user_credentials_are_passed() => - await _fixture.AppendStream(SecurityFixture.NoAclStream, TestCredentials.TestAdmin); + await Fixture.AppendStream(SecurityFixture.NoAclStream, TestCredentials.TestAdmin); [AnonymousAccess.Fact] public async Task writing_to_all_access_normal_stream_succeeds_when_no_credentials_are_passed() => - await _fixture.AppendStream(SecurityFixture.NormalAllStream); + await Fixture.AppendStream(SecurityFixture.NormalAllStream); [Fact] public async Task writing_to_all_access_normal_stream_is_not_authenticated_when_not_existing_credentials_are_passed() => - await Assert.ThrowsAsync(() => _fixture.AppendStream(SecurityFixture.NormalAllStream, TestCredentials.TestBadUser)); + await Assert.ThrowsAsync(() => Fixture.AppendStream(SecurityFixture.NormalAllStream, TestCredentials.TestBadUser)); [Fact] public async Task writing_to_all_access_normal_stream_succeeds_when_any_existing_user_credentials_are_passed() { - await _fixture.AppendStream(SecurityFixture.NormalAllStream, TestCredentials.TestUser1); - await _fixture.AppendStream(SecurityFixture.NormalAllStream, TestCredentials.TestUser2); + await Fixture.AppendStream(SecurityFixture.NormalAllStream, TestCredentials.TestUser1); + await Fixture.AppendStream(SecurityFixture.NormalAllStream, TestCredentials.TestUser2); } [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); - - public class Fixture : SecurityFixture { - protected override Task When() => Task.CompletedTask; - } + await Fixture.AppendStream(SecurityFixture.NormalAllStream, TestCredentials.TestAdmin); } \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/stream_metadata.cs b/test/EventStore.Client.Streams.Tests/StreamMetadata/stream_metadata.cs similarity index 69% rename from test/EventStore.Client.Streams.Tests/stream_metadata.cs rename to test/EventStore.Client.Streams.Tests/StreamMetadata/stream_metadata.cs index 4f57b3c86..be0179577 100644 --- a/test/EventStore.Client.Streams.Tests/stream_metadata.cs +++ b/test/EventStore.Client.Streams.Tests/StreamMetadata/stream_metadata.cs @@ -1,31 +1,32 @@ using System.Text.Json; -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests; -[Trait("Category", "LongRunning")] -public class stream_metadata : IClassFixture { - readonly Fixture _fixture; +[LongRunning] +public class stream_metadata : IClassFixture { + public stream_metadata(ITestOutputHelper output, EventStoreFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); - public stream_metadata(Fixture fixture) => _fixture = fixture; + EventStoreFixture Fixture { get; } [Fact] public async Task getting_for_an_existing_stream_and_no_metadata_exists() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, _fixture.CreateTestEvents()); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents()); - var actual = await _fixture.Client.GetStreamMetadataAsync(stream); + var actual = await Fixture.Streams.GetStreamMetadataAsync(stream); Assert.Equal(StreamMetadataResult.None(stream), actual); } [Fact] public async Task empty_metadata() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - await _fixture.Client.SetStreamMetadataAsync(stream, StreamState.NoStream, new()); + await Fixture.Streams.SetStreamMetadataAsync(stream, StreamState.NoStream, new()); - var actual = await _fixture.Client.GetStreamMetadataAsync(stream); + var actual = await Fixture.Streams.GetStreamMetadataAsync(stream); Assert.Equal(stream, actual.StreamName); Assert.Equal(StreamPosition.Start, actual.MetastreamRevision); @@ -43,7 +44,7 @@ public async Task empty_metadata() { [Fact] public async Task latest_metadata_is_returned() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); var expected = new StreamMetadata( 17, @@ -52,9 +53,9 @@ public async Task latest_metadata_is_returned() { TimeSpan.FromSeconds(0xABACABA) ); - await _fixture.Client.SetStreamMetadataAsync(stream, StreamState.NoStream, expected); + await Fixture.Streams.SetStreamMetadataAsync(stream, StreamState.NoStream, expected); - var actual = await _fixture.Client.GetStreamMetadataAsync(stream); + var actual = await Fixture.Streams.GetStreamMetadataAsync(stream); Assert.Equal(stream, actual.StreamName); Assert.False(actual.StreamDeleted); @@ -72,9 +73,9 @@ public async Task latest_metadata_is_returned() { TimeSpan.FromSeconds(0xDABACABAD) ); - await _fixture.Client.SetStreamMetadataAsync(stream, new StreamRevision(0), expected); + await Fixture.Streams.SetStreamMetadataAsync(stream, new StreamRevision(0), expected); - actual = await _fixture.Client.GetStreamMetadataAsync(stream); + actual = await Fixture.Streams.GetStreamMetadataAsync(stream); Assert.Equal(stream, actual.StreamName); Assert.False(actual.StreamDeleted); @@ -88,18 +89,18 @@ public async Task latest_metadata_is_returned() { [Fact] public async Task setting_with_wrong_expected_version_throws() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); await Assert.ThrowsAsync( () => - _fixture.Client.SetStreamMetadataAsync(stream, new StreamRevision(2), new()) + Fixture.Streams.SetStreamMetadataAsync(stream, new StreamRevision(2), new()) ); } [Fact] public async Task setting_with_wrong_expected_version_returns() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); var writeResult = - await _fixture.Client.SetStreamMetadataAsync( + await Fixture.Streams.SetStreamMetadataAsync( stream, new StreamRevision(2), new(), @@ -111,7 +112,7 @@ await _fixture.Client.SetStreamMetadataAsync( [Fact] public async Task latest_metadata_returned_stream_revision_any() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); var expected = new StreamMetadata( 17, @@ -120,9 +121,9 @@ public async Task latest_metadata_returned_stream_revision_any() { TimeSpan.FromSeconds(0xABACABA) ); - await _fixture.Client.SetStreamMetadataAsync(stream, StreamState.Any, expected); + await Fixture.Streams.SetStreamMetadataAsync(stream, StreamState.Any, expected); - var actual = await _fixture.Client.GetStreamMetadataAsync(stream); + var actual = await Fixture.Streams.GetStreamMetadataAsync(stream); Assert.Equal(stream, actual.StreamName); Assert.False(actual.StreamDeleted); @@ -140,9 +141,9 @@ public async Task latest_metadata_returned_stream_revision_any() { TimeSpan.FromSeconds(0xDABACABAD) ); - await _fixture.Client.SetStreamMetadataAsync(stream, StreamState.Any, expected); + await Fixture.Streams.SetStreamMetadataAsync(stream, StreamState.Any, expected); - actual = await _fixture.Client.GetStreamMetadataAsync(stream); + actual = await Fixture.Streams.GetStreamMetadataAsync(stream); Assert.Equal(stream, actual.StreamName); Assert.False(actual.StreamDeleted); @@ -153,9 +154,4 @@ public async Task latest_metadata_returned_stream_revision_any() { Assert.Equal(expected.CacheControl, actual.Metadata.CacheControl); Assert.Equal(expected.Acl, actual.Metadata.Acl); } - - 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.Streams.Tests/stream_metadata_with_timeout.cs b/test/EventStore.Client.Streams.Tests/StreamMetadata/stream_metadata_with_timeout.cs similarity index 53% rename from test/EventStore.Client.Streams.Tests/stream_metadata_with_timeout.cs rename to test/EventStore.Client.Streams.Tests/StreamMetadata/stream_metadata_with_timeout.cs index e7c57df03..77b1e3c95 100644 --- a/test/EventStore.Client.Streams.Tests/stream_metadata_with_timeout.cs +++ b/test/EventStore.Client.Streams.Tests/StreamMetadata/stream_metadata_with_timeout.cs @@ -1,19 +1,20 @@ using Grpc.Core; -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests; -[Trait("Category", "Network")] -public class stream_metadata_with_timeout : IClassFixture { - readonly Fixture _fixture; +[Network] +public class stream_metadata_with_timeout : IClassFixture { + public stream_metadata_with_timeout(ITestOutputHelper output, EventStoreFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); - public stream_metadata_with_timeout(Fixture fixture) => _fixture = fixture; + EventStoreFixture Fixture { get; } [Fact] public async Task set_with_any_stream_revision_fails_when_operation_expired() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); var rpcException = await Assert.ThrowsAsync( () => - _fixture.Client.SetStreamMetadataAsync( + Fixture.Streams.SetStreamMetadataAsync( stream, StreamState.Any, new(), @@ -26,11 +27,11 @@ public async Task set_with_any_stream_revision_fails_when_operation_expired() { [Fact] public async Task set_with_stream_revision_fails_when_operation_expired() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); var rpcException = await Assert.ThrowsAsync( () => - _fixture.Client.SetStreamMetadataAsync( + Fixture.Streams.SetStreamMetadataAsync( stream, new StreamRevision(0), new(), @@ -43,15 +44,10 @@ public async Task set_with_stream_revision_fails_when_operation_expired() { [Fact] public async Task get_fails_when_operation_expired() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); var rpcException = await Assert.ThrowsAsync( () => - _fixture.Client.GetStreamMetadataAsync(stream, TimeSpan.Zero) + Fixture.Streams.GetStreamMetadataAsync(stream, TimeSpan.Zero) ); } - - 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.Streams.Tests/reconnection.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/reconnection.cs similarity index 99% rename from test/EventStore.Client.Streams.Tests/reconnection.cs rename to test/EventStore.Client.Streams.Tests/Subscriptions/reconnection.cs index 8843b1c46..9e2bfdcd5 100644 --- a/test/EventStore.Client.Streams.Tests/reconnection.cs +++ b/test/EventStore.Client.Streams.Tests/Subscriptions/reconnection.cs @@ -47,8 +47,6 @@ public class ReconnectionFixture() .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 { diff --git a/test/EventStore.Client.Streams.Tests/subscribe_resolve_link_to.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_resolve_link_to.cs similarity index 69% rename from test/EventStore.Client.Streams.Tests/subscribe_resolve_link_to.cs rename to test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_resolve_link_to.cs index 51be702a0..58798a392 100644 --- a/test/EventStore.Client.Streams.Tests/subscribe_resolve_link_to.cs +++ b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_resolve_link_to.cs @@ -1,21 +1,16 @@ -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests; -public class subscribe_resolve_link_to : IAsyncLifetime { - readonly Fixture _fixture; +public class subscribe_resolve_link_to : IClassFixture { + public subscribe_resolve_link_to(ITestOutputHelper output, RunProjectionsTestFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); - public subscribe_resolve_link_to(ITestOutputHelper outputHelper) { - _fixture = new(); - _fixture.CaptureLogs(outputHelper); - } - - public Task InitializeAsync() => _fixture.InitializeAsync(); - public Task DisposeAsync() => _fixture.DisposeAsync(); + RunProjectionsTestFixture Fixture { get; } [Fact] public async Task stream_subscription() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - var events = _fixture.CreateTestEvents(20).ToArray(); + var events = Fixture.CreateTestEvents(20).ToArray(); var appeared = new TaskCompletionSource(); var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); @@ -27,10 +22,10 @@ public async Task stream_subscription() { enumerator.MoveNext(); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, beforeEvents) + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, beforeEvents) .WithTimeout(); - using var subscription = await _fixture.Client + using var subscription = await Fixture.Streams .SubscribeToStreamAsync( $"$et-{EventStoreClientFixtureBase.TestEventType}", FromStream.Start, @@ -41,7 +36,7 @@ await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, beforeEv ) .WithTimeout(); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.Any, afterEvents) + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, afterEvents) .WithTimeout(); await appeared.Task.WithTimeout(); @@ -67,14 +62,15 @@ Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) return Task.CompletedTask; } - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); + void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => + dropped.SetResult((reason, ex)); } [Fact] public async Task all_subscription() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - var events = _fixture.CreateTestEvents(20).ToArray(); + var events = Fixture.CreateTestEvents(20).ToArray(); var appeared = new TaskCompletionSource(); var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); @@ -86,10 +82,10 @@ public async Task all_subscription() { enumerator.MoveNext(); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, beforeEvents) + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, beforeEvents) .WithTimeout(); - using var subscription = await _fixture.Client.SubscribeToAllAsync( + using var subscription = await Fixture.Streams.SubscribeToAllAsync( FromAll.Start, EventAppeared, true, @@ -98,7 +94,7 @@ await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, beforeEv ) .WithTimeout(); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.Any, afterEvents).WithTimeout(); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, afterEvents).WithTimeout(); await appeared.Task.WithTimeout(); @@ -126,14 +122,15 @@ Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) return Task.CompletedTask; } - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); + void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => + dropped.SetResult((reason, ex)); } [Fact] public async Task all_filtered_subscription() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - var events = _fixture.CreateTestEvents(20).ToArray(); + var events = Fixture.CreateTestEvents(20).ToArray(); var appeared = new TaskCompletionSource(); var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); @@ -145,10 +142,10 @@ public async Task all_filtered_subscription() { enumerator.MoveNext(); - var result = await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, beforeEvents) + var result = await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, beforeEvents) .WithTimeout(); - using var subscription = await _fixture.Client.SubscribeToAllAsync( + using var subscription = await Fixture.Streams.SubscribeToAllAsync( FromAll.Start, EventAppeared, true, @@ -158,7 +155,7 @@ public async Task all_filtered_subscription() { ) .WithTimeout(); - result = await _fixture.Client.AppendToStreamAsync(stream, StreamState.Any, afterEvents) + result = await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, afterEvents) .WithTimeout(); await appeared.Task.WithTimeout(); @@ -187,18 +184,7 @@ Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) return Task.CompletedTask; } - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); - } - - public class Fixture : EventStoreClientFixture { - public Fixture() : base( - env: new() { - ["EVENTSTORE_RUN_PROJECTIONS"] = "All", - ["EVENTSTORE_START_STANDARD_PROJECTIONS"] = "True" - } - ) { } - - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; + void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => + dropped.SetResult((reason, ex)); } } \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/subscribe_to_all.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all.cs similarity index 67% rename from test/EventStore.Client.Streams.Tests/subscribe_to_all.cs rename to test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all.cs index 68435b980..9b7fbc68f 100644 --- a/test/EventStore.Client.Streams.Tests/subscribe_to_all.cs +++ b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all.cs @@ -1,25 +1,20 @@ -namespace EventStore.Client.Streams.Tests; - -[Trait("Category", "LongRunning")] -public class subscribe_to_all : IAsyncLifetime { - readonly Fixture _fixture; +namespace EventStore.Client.Streams.Tests; +[DedicatedDatabase, LongRunning] +public class subscribe_to_all : IClassFixture { /// - /// This class does not implement IClassFixture because it checks $all, and we want a fresh Node for each test. + /// This class because it checks $all, requires a dedicated db node for each test. /// - public subscribe_to_all(ITestOutputHelper outputHelper) { - _fixture = new(); - _fixture.CaptureLogs(outputHelper); - } + public subscribe_to_all(ITestOutputHelper output, CustomFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); - public Task InitializeAsync() => _fixture.InitializeAsync(); - public Task DisposeAsync() => _fixture.DisposeAsync(); + CustomFixture Fixture { get; } [Fact] public async Task calls_subscription_dropped_when_disposed() { var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - using var subscription = await _fixture.Client.SubscribeToAllAsync( + using var subscription = await Fixture.Streams.SubscribeToAllAsync( FromAll.Start, EventAppeared, false, @@ -39,16 +34,17 @@ public async Task calls_subscription_dropped_when_disposed() { Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) => Task.CompletedTask; - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); + void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => + dropped.SetResult((reason, ex)); } [Fact] public async Task calls_subscription_dropped_when_error_processing_event() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); var expectedException = new Exception("Error"); - using var subscription = await _fixture.Client.SubscribeToAllAsync( + using var subscription = await Fixture.Streams.SubscribeToAllAsync( FromAll.Start, EventAppeared, false, @@ -56,16 +52,18 @@ public async Task calls_subscription_dropped_when_error_processing_event() { ) .WithTimeout(); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, _fixture.CreateTestEvents()); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents()); var (reason, ex) = await dropped.Task.WithTimeout(); Assert.Equal(SubscriptionDroppedReason.SubscriberError, reason); Assert.Same(expectedException, ex); - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) => Task.FromException(expectedException); + Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) => + Task.FromException(expectedException); - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); + void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => + dropped.SetResult((reason, ex)); } [Fact] @@ -73,7 +71,7 @@ public async Task subscribe_to_empty_database() { var appeared = new TaskCompletionSource(); var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - using var subscription = await _fixture.Client.SubscribeToAllAsync( + using var subscription = await Fixture.Streams.SubscribeToAllAsync( FromAll.Start, EventAppeared, false, @@ -100,7 +98,8 @@ Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) return Task.CompletedTask; } - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); + void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => + dropped.SetResult((reason, ex)); } [Fact] @@ -108,17 +107,17 @@ public async Task reads_all_existing_events_and_keep_listening_to_new_ones() { var appeared = new TaskCompletionSource(); var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); var appearedEvents = new List(); - var beforeEvents = _fixture.CreateTestEvents(10).ToArray(); - var afterEvents = _fixture.CreateTestEvents(10).ToArray(); + var beforeEvents = Fixture.CreateTestEvents(10).ToArray(); + var afterEvents = Fixture.CreateTestEvents(10).ToArray(); foreach (var @event in beforeEvents) - await _fixture.Client.AppendToStreamAsync( + await Fixture.Streams.AppendToStreamAsync( $"stream-{@event.EventId:n}", StreamState.NoStream, new[] { @event } ); - using var subscription = await _fixture.Client.SubscribeToAllAsync( + using var subscription = await Fixture.Streams.SubscribeToAllAsync( FromAll.Start, EventAppeared, false, @@ -127,7 +126,7 @@ await _fixture.Client.AppendToStreamAsync( .WithTimeout(); foreach (var @event in afterEvents) - await _fixture.Client.AppendToStreamAsync( + await Fixture.Streams.AppendToStreamAsync( $"stream-{@event.EventId:n}", StreamState.NoStream, new[] { @event } @@ -161,18 +160,20 @@ Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) return Task.CompletedTask; } - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); + void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => + dropped.SetResult((reason, ex)); } - public class Fixture : EventStoreClientFixture { - protected override Task Given() => - Client.SetStreamMetadataAsync( - SystemStreams.AllStream, - StreamState.NoStream, - new(acl: new(SystemRoles.All)), - userCredentials: TestCredentials.Root - ); - - protected override Task When() => Task.CompletedTask; + public class CustomFixture : EventStoreFixture { + public CustomFixture() { + OnSetup = async () => { + await Streams.SetStreamMetadataAsync( + SystemStreams.AllStream, + StreamState.NoStream, + new(acl: new(SystemRoles.All)), + userCredentials: TestCredentials.Root + ); + }; + } } } \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/subscribe_to_all_filtered.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all_filtered.cs similarity index 74% rename from test/EventStore.Client.Streams.Tests/subscribe_to_all_filtered.cs rename to test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all_filtered.cs index 5e33b781f..c17adf0d2 100644 --- a/test/EventStore.Client.Streams.Tests/subscribe_to_all_filtered.cs +++ b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all_filtered.cs @@ -1,49 +1,45 @@ -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests; -public class subscribe_to_all_filtered : IAsyncLifetime { - readonly Fixture _fixture; +[DedicatedDatabase] +public class subscribe_to_all_filtered : IClassFixture { + public subscribe_to_all_filtered(ITestOutputHelper output, CustomFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); - public subscribe_to_all_filtered(ITestOutputHelper outputHelper) { - _fixture = new(); - _fixture.CaptureLogs(outputHelper); - } - - public Task InitializeAsync() => _fixture.InitializeAsync(); - - public Task DisposeAsync() => _fixture.DisposeAsync(); + CustomFixture Fixture { get; } public static IEnumerable FilterCases() => Filters.All.Select(filter => new object[] { filter }); [Theory] [MemberData(nameof(FilterCases))] public async Task reads_all_existing_events(string filterName) { - var streamPrefix = _fixture.GetStreamName(); + var streamPrefix = Fixture.GetStreamName(); var (getFilter, prepareEvent) = Filters.GetFilter(filterName); var appeared = new TaskCompletionSource(); var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); var checkpointSeen = new TaskCompletionSource(); var filter = getFilter(streamPrefix); - var events = _fixture.CreateTestEvents(20).Select(e => prepareEvent(streamPrefix, e)) + + var events = Fixture.CreateTestEvents(20).Select(e => prepareEvent(streamPrefix, e)) .ToArray(); using var enumerator = events.OfType().GetEnumerator(); enumerator.MoveNext(); - await _fixture.Client.AppendToStreamAsync( + await Fixture.Streams.AppendToStreamAsync( Guid.NewGuid().ToString(), StreamState.NoStream, - _fixture.CreateTestEvents(256) + Fixture.CreateTestEvents(256) ); foreach (var e in events) - await _fixture.Client.AppendToStreamAsync( + await Fixture.Streams.AppendToStreamAsync( $"{streamPrefix}_{Guid.NewGuid():n}", StreamState.NoStream, new[] { e } ); - using var subscription = await _fixture.Client.SubscribeToAllAsync( + using var subscription = await Fixture.Streams.SubscribeToAllAsync( FromAll.Start, EventAppeared, false, @@ -95,14 +91,14 @@ Task CheckpointReached(StreamSubscription _, Position position, CancellationToke [Theory] [MemberData(nameof(FilterCases))] public async Task reads_all_existing_events_and_keep_listening_to_new_ones(string filterName) { - var streamPrefix = _fixture.GetStreamName(); + var streamPrefix = Fixture.GetStreamName(); var (getFilter, prepareEvent) = Filters.GetFilter(filterName); var appeared = new TaskCompletionSource(); var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); var checkpointSeen = new TaskCompletionSource(); var filter = getFilter(streamPrefix); - var events = _fixture.CreateTestEvents(20).Select(e => prepareEvent(streamPrefix, e)) + var events = Fixture.CreateTestEvents(20).Select(e => prepareEvent(streamPrefix, e)) .ToArray(); var beforeEvents = events.Take(10); @@ -111,20 +107,20 @@ public async Task reads_all_existing_events_and_keep_listening_to_new_ones(strin using var enumerator = events.OfType().GetEnumerator(); enumerator.MoveNext(); - await _fixture.Client.AppendToStreamAsync( + await Fixture.Streams.AppendToStreamAsync( Guid.NewGuid().ToString(), StreamState.NoStream, - _fixture.CreateTestEvents(256) + Fixture.CreateTestEvents(256) ); foreach (var e in beforeEvents) - await _fixture.Client.AppendToStreamAsync( + await Fixture.Streams.AppendToStreamAsync( $"{streamPrefix}_{Guid.NewGuid():n}", StreamState.NoStream, new[] { e } ); - using var subscription = await _fixture.Client.SubscribeToAllAsync( + using var subscription = await Fixture.Streams.SubscribeToAllAsync( FromAll.Start, EventAppeared, false, @@ -134,7 +130,7 @@ await _fixture.Client.AppendToStreamAsync( .WithTimeout(); foreach (var e in afterEvents) - await _fixture.Client.AppendToStreamAsync( + await Fixture.Streams.AppendToStreamAsync( $"{streamPrefix}_{Guid.NewGuid():n}", StreamState.NoStream, new[] { e } @@ -180,17 +176,20 @@ Task CheckpointReached(StreamSubscription _, Position position, CancellationToke } } - public class Fixture : EventStoreClientFixture { + public class CustomFixture : EventStoreFixture { public const string FilteredOutStream = nameof(FilteredOutStream); - protected override Task Given() => - Client.SetStreamMetadataAsync( - SystemStreams.AllStream, - StreamState.Any, - new(acl: new(SystemRoles.All)), - userCredentials: TestCredentials.Root - ); - - protected override Task When() => Client.AppendToStreamAsync(FilteredOutStream, StreamState.NoStream, CreateTestEvents(10)); + public CustomFixture() { + OnSetup = async () => { + await Streams.SetStreamMetadataAsync( + SystemStreams.AllStream, + StreamState.NoStream, + new(acl: new(SystemRoles.All)), + userCredentials: TestCredentials.Root + ); + + await Streams.AppendToStreamAsync(FilteredOutStream, StreamState.NoStream, CreateTestEvents(10)); + }; + } } } \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/subscribe_to_all_filtered_live.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all_filtered_live.cs similarity index 58% rename from test/EventStore.Client.Streams.Tests/subscribe_to_all_filtered_live.cs rename to test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all_filtered_live.cs index 2e20cb523..af9b6105d 100644 --- a/test/EventStore.Client.Streams.Tests/subscribe_to_all_filtered_live.cs +++ b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all_filtered_live.cs @@ -1,30 +1,40 @@ -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests; -public class subscribe_to_all_filtered_live : IAsyncLifetime { - readonly Fixture _fixture; +[DedicatedDatabase] +public class subscribe_to_all_filtered_live : IClassFixture { + public subscribe_to_all_filtered_live(ITestOutputHelper output, EventStoreFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); - public subscribe_to_all_filtered_live(ITestOutputHelper outputHelper) { - _fixture = new(); - _fixture.CaptureLogs(outputHelper); - } - - public Task InitializeAsync() => _fixture.InitializeAsync(); - - public Task DisposeAsync() => _fixture.DisposeAsync(); + EventStoreFixture Fixture { get; } public static IEnumerable FilterCases() => Filters.All.Select(filter => new object[] { filter }); [Theory] [MemberData(nameof(FilterCases))] public async Task does_not_read_all_events_but_keep_listening_to_new_ones(string filterName) { - var streamPrefix = _fixture.GetStreamName(); + const string filteredOutStream = nameof(filteredOutStream); + + await Fixture.Streams.SetStreamMetadataAsync( + SystemStreams.AllStream, + StreamState.Any, + new(acl: new(SystemRoles.All)), + userCredentials: TestCredentials.Root + ); + + await Fixture.Streams.AppendToStreamAsync( + filteredOutStream, + StreamState.NoStream, + Fixture.CreateTestEvents(10) + ); + + var streamPrefix = Fixture.GetStreamName(); var (getFilter, prepareEvent) = Filters.GetFilter(filterName); var appeared = new TaskCompletionSource(); var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); var filter = getFilter(streamPrefix); - var events = _fixture.CreateTestEvents(20).Select(e => prepareEvent(streamPrefix, e)) + var events = Fixture.CreateTestEvents(20).Select(e => prepareEvent(streamPrefix, e)) .ToArray(); var beforeEvents = events.Take(10); @@ -34,13 +44,13 @@ public async Task does_not_read_all_events_but_keep_listening_to_new_ones(string enumerator.MoveNext(); foreach (var e in beforeEvents) - await _fixture.Client.AppendToStreamAsync( + await Fixture.Streams.AppendToStreamAsync( $"{streamPrefix}_{Guid.NewGuid():n}", StreamState.NoStream, new[] { e } ); - using var subscription = await _fixture.Client.SubscribeToAllAsync( + using var subscription = await Fixture.Streams.SubscribeToAllAsync( FromAll.End, EventAppeared, false, @@ -50,7 +60,7 @@ await _fixture.Client.AppendToStreamAsync( .WithTimeout(); foreach (var e in afterEvents) - await _fixture.Client.AppendToStreamAsync( + await Fixture.Streams.AppendToStreamAsync( $"{streamPrefix}_{Guid.NewGuid():n}", StreamState.NoStream, new[] { e } @@ -81,20 +91,7 @@ Task EventAppeared(StreamSubscription _, ResolvedEvent e, CancellationToken ct) return Task.CompletedTask; } - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); - } - - public class Fixture : EventStoreClientFixture { - public const string FilteredOutStream = nameof(FilteredOutStream); - - protected override Task Given() => - Client.SetStreamMetadataAsync( - SystemStreams.AllStream, - StreamState.Any, - new(acl: new(SystemRoles.All)), - userCredentials: TestCredentials.Root - ); - - protected override Task When() => Client.AppendToStreamAsync(FilteredOutStream, StreamState.NoStream, CreateTestEvents(10)); + void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => + dropped.SetResult((reason, ex)); } } \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/subscribe_to_all_filtered_with_position.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all_filtered_with_position.cs similarity index 62% rename from test/EventStore.Client.Streams.Tests/subscribe_to_all_filtered_with_position.cs rename to test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all_filtered_with_position.cs index 978be0474..3c7cbe79f 100644 --- a/test/EventStore.Client.Streams.Tests/subscribe_to_all_filtered_with_position.cs +++ b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all_filtered_with_position.cs @@ -1,30 +1,40 @@ -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests; -public class subscribe_to_all_filtered_with_position : IAsyncLifetime { - readonly Fixture _fixture; +[DedicatedDatabase] +public class subscribe_to_all_filtered_with_position : IClassFixture { + public subscribe_to_all_filtered_with_position(ITestOutputHelper output, EventStoreFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); - public subscribe_to_all_filtered_with_position(ITestOutputHelper outputHelper) { - _fixture = new(); - _fixture.CaptureLogs(outputHelper); - } - - public Task InitializeAsync() => _fixture.InitializeAsync(); - - public Task DisposeAsync() => _fixture.DisposeAsync(); + EventStoreFixture Fixture { get; } public static IEnumerable FilterCases() => Filters.All.Select(filter => new object[] { filter }); [Theory] [MemberData(nameof(FilterCases))] public async Task reads_all_existing_events_and_keep_listening_to_new_ones(string filterName) { - var streamPrefix = _fixture.GetStreamName(); + const string filteredOutStream = nameof(filteredOutStream); + + await Fixture.Streams.SetStreamMetadataAsync( + SystemStreams.AllStream, + StreamState.Any, + new(acl: new(SystemRoles.All)), + userCredentials: TestCredentials.Root + ); + + await Fixture.Streams.AppendToStreamAsync( + filteredOutStream, + StreamState.NoStream, + Fixture.CreateTestEvents(10) + ); + + var streamPrefix = Fixture.GetStreamName(); var (getFilter, prepareEvent) = Filters.GetFilter(filterName); var appeared = new TaskCompletionSource(); var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); var checkpointSeen = new TaskCompletionSource(); var filter = getFilter(streamPrefix); - var events = _fixture.CreateTestEvents(20).Select(e => prepareEvent(streamPrefix, e)) + var events = Fixture.CreateTestEvents(20).Select(e => prepareEvent(streamPrefix, e)) .ToArray(); var beforeEvents = events.Take(10); @@ -34,25 +44,25 @@ public async Task reads_all_existing_events_and_keep_listening_to_new_ones(strin enumerator.MoveNext(); foreach (var e in beforeEvents) - await _fixture.Client.AppendToStreamAsync( + await Fixture.Streams.AppendToStreamAsync( $"{streamPrefix}_{Guid.NewGuid():n}", StreamState.NoStream, new[] { e } ); - var writeResult = await _fixture.Client.AppendToStreamAsync( + var writeResult = await Fixture.Streams.AppendToStreamAsync( "checkpoint", StreamState.NoStream, - _fixture.CreateTestEvents() + Fixture.CreateTestEvents() ); - await _fixture.Client.AppendToStreamAsync( + await Fixture.Streams.AppendToStreamAsync( Guid.NewGuid().ToString(), StreamState.NoStream, - _fixture.CreateTestEvents(256) + Fixture.CreateTestEvents(256) ); - using var subscription = await _fixture.Client.SubscribeToAllAsync( + using var subscription = await Fixture.Streams.SubscribeToAllAsync( FromAll.After(writeResult.LogPosition), EventAppeared, false, @@ -62,7 +72,7 @@ await _fixture.Client.AppendToStreamAsync( .WithTimeout(); foreach (var e in afterEvents) - await _fixture.Client.AppendToStreamAsync( + await Fixture.Streams.AppendToStreamAsync( $"{streamPrefix}_{Guid.NewGuid():n}", StreamState.NoStream, new[] { e } @@ -93,7 +103,8 @@ Task EventAppeared(StreamSubscription _, ResolvedEvent e, CancellationToken ct) return Task.CompletedTask; } - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); + void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => + dropped.SetResult((reason, ex)); Task CheckpointReached(StreamSubscription _, Position position, CancellationToken ct) { checkpointSeen.TrySetResult(true); @@ -101,18 +112,4 @@ Task CheckpointReached(StreamSubscription _, Position position, CancellationToke return Task.CompletedTask; } } - - public class Fixture : EventStoreClientFixture { - public const string FilteredOutStream = nameof(FilteredOutStream); - - protected override Task Given() => - Client.SetStreamMetadataAsync( - SystemStreams.AllStream, - StreamState.Any, - new(acl: new(SystemRoles.All)), - userCredentials: TestCredentials.Root - ); - - protected override Task When() => Client.AppendToStreamAsync(FilteredOutStream, StreamState.NoStream, CreateTestEvents(10)); - } } \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/subscribe_to_all_live.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all_live.cs similarity index 66% rename from test/EventStore.Client.Streams.Tests/subscribe_to_all_live.cs rename to test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all_live.cs index f64cf8dd0..185b893b7 100644 --- a/test/EventStore.Client.Streams.Tests/subscribe_to_all_live.cs +++ b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all_live.cs @@ -1,25 +1,27 @@ -namespace EventStore.Client.Streams.Tests; - -[Trait("Category", "LongRunning")] -public class subscribe_to_all_live : IAsyncLifetime { - readonly Fixture _fixture; +namespace EventStore.Client.Streams.Tests; +[DedicatedDatabase, LongRunning] +public class subscribe_to_all_live : IClassFixture { /// /// This class does not implement IClassFixture because it checks $all, and we want a fresh Node for each test. /// - public subscribe_to_all_live(ITestOutputHelper outputHelper) { - _fixture = new(); - _fixture.CaptureLogs(outputHelper); - } + public subscribe_to_all_live(ITestOutputHelper output, EventStoreFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); - public Task InitializeAsync() => _fixture.InitializeAsync(); - public Task DisposeAsync() => _fixture.DisposeAsync(); + EventStoreFixture Fixture { get; } [Fact] public async Task calls_subscription_dropped_when_disposed() { + await Fixture.Streams.SetStreamMetadataAsync( + SystemStreams.AllStream, + StreamState.NoStream, + new(acl: new(SystemRoles.All)), + userCredentials: TestCredentials.Root + ); + var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - using var subscription = await _fixture.Client + using var subscription = await Fixture.Streams .SubscribeToAllAsync(FromAll.End, EventAppeared, false, SubscriptionDropped) .WithTimeout(); @@ -35,37 +37,54 @@ public async Task calls_subscription_dropped_when_disposed() { Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) => Task.CompletedTask; - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); + void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => + dropped.SetResult((reason, ex)); } [Fact] public async Task calls_subscription_dropped_when_error_processing_event() { - var stream = _fixture.GetStreamName(); + await Fixture.Streams.SetStreamMetadataAsync( + SystemStreams.AllStream, + StreamState.NoStream, + new(acl: new(SystemRoles.All)), + userCredentials: TestCredentials.Root + ); + + var stream = Fixture.GetStreamName(); var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); var expectedException = new Exception("Error"); - using var subscription = await _fixture.Client + using var subscription = await Fixture.Streams .SubscribeToAllAsync(FromAll.End, EventAppeared, false, SubscriptionDropped) .WithTimeout(); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, _fixture.CreateTestEvents()); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents()); var (reason, ex) = await dropped.Task.WithTimeout(); Assert.Equal(SubscriptionDroppedReason.SubscriberError, reason); Assert.Same(expectedException, ex); - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) => Task.FromException(expectedException); + Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) => + Task.FromException(expectedException); - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); + void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => + dropped.SetResult((reason, ex)); } [Fact] public async Task subscribe_to_empty_database() { + await Fixture.Streams.SetStreamMetadataAsync( + SystemStreams.AllStream, + StreamState.NoStream, + new(acl: new(SystemRoles.All)), + userCredentials: TestCredentials.Root + ); + var appeared = new TaskCompletionSource(); var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - using var subscription = await _fixture.Client + using var subscription = await Fixture.Streams .SubscribeToAllAsync(FromAll.End, EventAppeared, false, SubscriptionDropped) .WithTimeout(); @@ -88,22 +107,30 @@ Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) return Task.CompletedTask; } - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); + void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => + dropped.SetResult((reason, ex)); } [Fact] public async Task does_not_read_existing_events_but_keep_listening_to_new_ones() { + await Fixture.Streams.SetStreamMetadataAsync( + SystemStreams.AllStream, + StreamState.NoStream, + new(acl: new(SystemRoles.All)), + userCredentials: TestCredentials.Root + ); + var appeared = new TaskCompletionSource(); var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); var appearedEvents = new List(); - var afterEvents = _fixture.CreateTestEvents(10).ToArray(); + var afterEvents = Fixture.CreateTestEvents(10).ToArray(); - using var subscription = await _fixture.Client + using var subscription = await Fixture.Streams .SubscribeToAllAsync(FromAll.End, EventAppeared, false, SubscriptionDropped) .WithTimeout(); foreach (var @event in afterEvents) - await _fixture.Client.AppendToStreamAsync( + await Fixture.Streams.AppendToStreamAsync( $"stream-{@event.EventId:n}", StreamState.NoStream, new[] { @event } @@ -134,18 +161,7 @@ Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) return Task.CompletedTask; } - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => - Client.SetStreamMetadataAsync( - SystemStreams.AllStream, - StreamState.NoStream, - new(acl: new(SystemRoles.All)), - userCredentials: TestCredentials.Root - ); - - protected override Task When() => Task.CompletedTask; + void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => + dropped.SetResult((reason, ex)); } } \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/subscribe_to_all_with_position.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all_with_position.cs similarity index 53% rename from test/EventStore.Client.Streams.Tests/subscribe_to_all_with_position.cs rename to test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all_with_position.cs index d732e7808..d5fa9594e 100644 --- a/test/EventStore.Client.Streams.Tests/subscribe_to_all_with_position.cs +++ b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all_with_position.cs @@ -1,38 +1,62 @@ -namespace EventStore.Client.Streams.Tests; - -[Trait("Category", "LongRunning")] -public class subscribe_to_all_with_position : IAsyncLifetime { - readonly Fixture _fixture; - - /// - /// This class does not implement IClassFixture because it checks $all, and we want a fresh Node for each test. - /// - public subscribe_to_all_with_position(ITestOutputHelper outputHelper) { - _fixture = new(); - _fixture.CaptureLogs(outputHelper); - } +namespace EventStore.Client.Streams.Tests; + +[DedicatedDatabase, LongRunning] +public class subscribe_to_all_with_position : IClassFixture { + public subscribe_to_all_with_position(ITestOutputHelper output, EventStoreFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); - public Task InitializeAsync() => _fixture.InitializeAsync(); - public Task DisposeAsync() => _fixture.DisposeAsync(); + EventStoreFixture Fixture { get; } [Fact] - public async Task calls_subscription_dropped_when_disposed() { - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); + public async Task reads_all_existing_events_after_position_and_keep_listening_to_new_ones() { + await Fixture.Streams.SetStreamMetadataAsync( + SystemStreams.AllStream, + StreamState.NoStream, + new(acl: new(SystemRoles.All)), + userCredentials: TestCredentials.Root + ); - var firstEvent = await _fixture.Client.ReadAllAsync(Direction.Forwards, Position.Start, 1) - .FirstOrDefaultAsync(); + var events = Fixture.CreateTestEvents(20).ToArray(); - using var subscription = await _fixture.Client - .SubscribeToAllAsync( - FromAll.After(firstEvent.OriginalEvent.Position), + var appeared = new TaskCompletionSource(); + var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); + + var beforeEvents = events.Take(10); + var afterEvents = events.Skip(10); + + using var enumerator = events.AsEnumerable().GetEnumerator(); + + enumerator.MoveNext(); + + var position = await Fixture.Streams.ReadAllAsync(Direction.Forwards, Position.Start, 1) + .Select(x => x.OriginalEvent.Position) + .FirstAsync(); + + foreach (var @event in beforeEvents) + await Fixture.Streams.AppendToStreamAsync( + $"stream-{@event.EventId:n}", + StreamState.NoStream, + new[] { @event } + ); + + using var subscription = await Fixture.Streams.SubscribeToAllAsync( + FromAll.After(position), EventAppeared, false, SubscriptionDropped ) .WithTimeout(); - if (dropped.Task.IsCompleted) - Assert.False(dropped.Task.IsCompleted, dropped.Task.Result.ToString()); + foreach (var @event in afterEvents) + await Fixture.Streams.AppendToStreamAsync( + $"stream-{@event.EventId:n}", + StreamState.NoStream, + new[] { @event } + ); + + await appeared.Task.WithTimeout(); + + Assert.False(dropped.Task.IsCompleted); subscription.Dispose(); @@ -41,50 +65,53 @@ public async Task calls_subscription_dropped_when_disposed() { Assert.Equal(SubscriptionDroppedReason.Disposed, reason); Assert.Null(ex); - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) => Task.CompletedTask; - - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); - } - - [Fact] - public async Task calls_subscription_dropped_when_error_processing_event() { - var stream = _fixture.GetStreamName(); - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - var expectedException = new Exception("Error"); - - var firstEvent = await _fixture.Client.ReadAllAsync(Direction.Forwards, Position.Start, 1) - .FirstOrDefaultAsync(); - - using var subscription = await _fixture.Client - .SubscribeToAllAsync( - FromAll.After(firstEvent.OriginalEvent.Position), - EventAppeared, - false, - SubscriptionDropped - ) - .WithTimeout(); + Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) { + if (position >= e.OriginalEvent.Position) + appeared.TrySetException(new Exception()); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, _fixture.CreateTestEvents(2)); + if (!SystemStreams.IsSystemStream(e.OriginalStreamId)) + try { + Assert.Equal(enumerator.Current.EventId, e.OriginalEvent.EventId); + if (!enumerator.MoveNext()) + appeared.TrySetResult(true); + } + catch (Exception ex) { + appeared.TrySetException(ex); + throw; + } - var (reason, ex) = await dropped.Task.WithTimeout(); + return Task.CompletedTask; + } - Assert.Equal(SubscriptionDroppedReason.SubscriberError, reason); - Assert.Same(expectedException, ex); + void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => + dropped.SetResult((reason, ex)); + } +} - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) => Task.FromException(expectedException); +[DedicatedDatabase, LongRunning] +public class subscribe_to_all_with_position_to_empty_database : IClassFixture { + + public subscribe_to_all_with_position_to_empty_database(ITestOutputHelper output, EventStoreFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); - } + EventStoreFixture Fixture { get; } [Fact] - public async Task subscribe_to_empty_database() { + public async Task verified() { + await Fixture.Streams.SetStreamMetadataAsync( + SystemStreams.AllStream, + StreamState.NoStream, + new(acl: new(SystemRoles.All)), + userCredentials: TestCredentials.Root + ); + var appeared = new TaskCompletionSource(); var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - var firstEvent = await _fixture.Client.ReadAllAsync(Direction.Forwards, Position.Start, 1) + var firstEvent = await Fixture.Streams.ReadAllAsync(Direction.Forwards, Position.Start, 1) .FirstOrDefaultAsync(); - using var subscription = await _fixture.Client + using var subscription = await Fixture.Streams .SubscribeToAllAsync( FromAll.After(firstEvent.OriginalEvent.Position), EventAppeared, @@ -117,52 +144,43 @@ Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) return Task.CompletedTask; } - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); + void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => + dropped.SetResult((reason, ex)); } +} - [Fact] - public async Task reads_all_existing_events_after_position_and_keep_listening_to_new_ones() { - var events = _fixture.CreateTestEvents(20).ToArray(); - - var appeared = new TaskCompletionSource(); - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); +[DedicatedDatabase, LongRunning] +public class subscribe_to_all_with_position_calls_subscription_dropped_when_disposed : IClassFixture { + public subscribe_to_all_with_position_calls_subscription_dropped_when_disposed(ITestOutputHelper output, EventStoreFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); - var beforeEvents = events.Take(10); - var afterEvents = events.Skip(10); + EventStoreFixture Fixture { get; } - using var enumerator = events.AsEnumerable().GetEnumerator(); - - enumerator.MoveNext(); + [Fact] + public async Task verified() { + await Fixture.Streams.SetStreamMetadataAsync( + SystemStreams.AllStream, + StreamState.NoStream, + new(acl: new(SystemRoles.All)), + userCredentials: TestCredentials.Root + ); - var position = await _fixture.Client.ReadAllAsync(Direction.Forwards, Position.Start, 1) - .Select(x => x.OriginalEvent.Position) - .FirstAsync(); + var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - foreach (var @event in beforeEvents) - await _fixture.Client.AppendToStreamAsync( - $"stream-{@event.EventId:n}", - StreamState.NoStream, - new[] { @event } - ); + var firstEvent = await Fixture.Streams.ReadAllAsync(Direction.Forwards, Position.Start, 1) + .FirstOrDefaultAsync(); - using var subscription = await _fixture.Client.SubscribeToAllAsync( - FromAll.After(position), + using var subscription = await Fixture.Streams + .SubscribeToAllAsync( + FromAll.After(firstEvent.OriginalEvent.Position), EventAppeared, false, SubscriptionDropped ) .WithTimeout(); - foreach (var @event in afterEvents) - await _fixture.Client.AppendToStreamAsync( - $"stream-{@event.EventId:n}", - StreamState.NoStream, - new[] { @event } - ); - - await appeared.Task.WithTimeout(); - - Assert.False(dropped.Task.IsCompleted); + if (dropped.Task.IsCompleted) + Assert.False(dropped.Task.IsCompleted, dropped.Task.Result.ToString()); subscription.Dispose(); @@ -171,36 +189,57 @@ await _fixture.Client.AppendToStreamAsync( Assert.Equal(SubscriptionDroppedReason.Disposed, reason); Assert.Null(ex); - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) { - if (position >= e.OriginalEvent.Position) - appeared.TrySetException(new Exception()); + Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) => Task.CompletedTask; - if (!SystemStreams.IsSystemStream(e.OriginalStreamId)) - try { - Assert.Equal(enumerator.Current.EventId, e.OriginalEvent.EventId); - if (!enumerator.MoveNext()) - appeared.TrySetResult(true); - } - catch (Exception ex) { - appeared.TrySetException(ex); - throw; - } + void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => + dropped.SetResult((reason, ex)); + } +} - return Task.CompletedTask; - } +[DedicatedDatabase, LongRunning] +public class subscribe_to_all_with_position_calls_subscription_dropped_when_error_processing_event : IClassFixture { + public subscribe_to_all_with_position_calls_subscription_dropped_when_error_processing_event(ITestOutputHelper output, EventStoreFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); - } + EventStoreFixture Fixture { get; } - public class Fixture : EventStoreClientFixture { - protected override Task Given() => - Client.SetStreamMetadataAsync( - SystemStreams.AllStream, - StreamState.NoStream, - new(acl: new(SystemRoles.All)), - userCredentials: TestCredentials.Root - ); + [Fact] + public async Task verified() { + await Fixture.Streams.SetStreamMetadataAsync( + SystemStreams.AllStream, + StreamState.NoStream, + new(acl: new(SystemRoles.All)), + userCredentials: TestCredentials.Root + ); + + var stream = Fixture.GetStreamName(); + var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); + + var expectedException = new Exception("Error"); + + var firstEvent = await Fixture.Streams.ReadAllAsync(Direction.Forwards, Position.Start, 1) + .FirstOrDefaultAsync(); + + using var subscription = await Fixture.Streams + .SubscribeToAllAsync( + FromAll.After(firstEvent.OriginalEvent.Position), + EventAppeared, + false, + SubscriptionDropped + ) + .WithTimeout(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents(2)); + + var (reason, ex) = await dropped.Task.WithTimeout(); + + Assert.Equal(SubscriptionDroppedReason.SubscriberError, reason); + Assert.Same(expectedException, ex); + + Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) => + Task.FromException(expectedException); - protected override Task When() => Task.CompletedTask; + void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => + dropped.SetResult((reason, ex)); } } \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/subscribe_to_stream.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream.cs similarity index 71% rename from test/EventStore.Client.Streams.Tests/subscribe_to_stream.cs rename to test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream.cs index f2a9df7a5..a0a8a6226 100644 --- a/test/EventStore.Client.Streams.Tests/subscribe_to_stream.cs +++ b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream.cs @@ -1,21 +1,19 @@ -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests; -[Trait("Category", "LongRunning")] -public class subscribe_to_stream : IClassFixture { - readonly Fixture _fixture; +[LongRunning] +public class subscribe_to_stream : IClassFixture { + public subscribe_to_stream(ITestOutputHelper output, EventStoreFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); - public subscribe_to_stream(Fixture fixture, ITestOutputHelper outputHelper) { - _fixture = fixture; - _fixture.CaptureLogs(outputHelper); - } + EventStoreFixture Fixture { get; } [Fact] public async Task subscribe_to_non_existing_stream() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); var appeared = new TaskCompletionSource(); var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - using var subscription = await _fixture.Client + using var subscription = await Fixture.Streams .SubscribeToStreamAsync( stream, FromStream.Start, @@ -41,16 +39,17 @@ Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) return Task.CompletedTask; } - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); + void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => + dropped.SetResult((reason, ex)); } [Fact] public async Task subscribe_to_non_existing_stream_then_get_event() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); var appeared = new TaskCompletionSource(); var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - using var subscription = await _fixture.Client + using var subscription = await Fixture.Streams .SubscribeToStreamAsync( stream, FromStream.Start, @@ -60,7 +59,7 @@ public async Task subscribe_to_non_existing_stream_then_get_event() { ) .WithTimeout(); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, _fixture.CreateTestEvents()); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents()); Assert.True(await appeared.Task.WithTimeout()); @@ -78,22 +77,23 @@ Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) return Task.CompletedTask; } - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); + void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => + dropped.SetResult((reason, ex)); } [Fact] public async Task allow_multiple_subscriptions_to_same_stream() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); var appeared = new TaskCompletionSource(); var appearedCount = 0; - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, _fixture.CreateTestEvents()); - using var s1 = await _fixture.Client + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents()); + using var s1 = await Fixture.Streams .SubscribeToStreamAsync(stream, FromStream.Start, EventAppeared).WithTimeout(); - using var s2 = await _fixture.Client + using var s2 = await Fixture.Streams .SubscribeToStreamAsync(stream, FromStream.Start, EventAppeared).WithTimeout(); Assert.True(await appeared.Task.WithTimeout()); @@ -108,10 +108,10 @@ Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) [Fact] public async Task calls_subscription_dropped_when_disposed() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - using var subscription = await _fixture.Client + using var subscription = await Fixture.Streams .SubscribeToStreamAsync( stream, FromStream.Start, @@ -133,16 +133,17 @@ public async Task calls_subscription_dropped_when_disposed() { Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) => Task.CompletedTask; - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); + void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => + dropped.SetResult((reason, ex)); } [Fact] public async Task calls_subscription_dropped_when_error_processing_event() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); var expectedException = new Exception("Error"); - using var subscription = await _fixture.Client + using var subscription = await Fixture.Streams .SubscribeToStreamAsync( stream, FromStream.Start, @@ -155,23 +156,25 @@ public async Task calls_subscription_dropped_when_error_processing_event() { if (dropped.Task.IsCompleted) Assert.False(dropped.Task.IsCompleted, dropped.Task.Result.ToString()); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, _fixture.CreateTestEvents()); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents()); var (reason, ex) = await dropped.Task.WithTimeout(); Assert.Equal(SubscriptionDroppedReason.SubscriberError, reason); Assert.Same(expectedException, ex); - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) => Task.FromException(expectedException); + Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) => + Task.FromException(expectedException); - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); + void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => + dropped.SetResult((reason, ex)); } [Fact] public async Task reads_all_existing_events_and_keep_listening_to_new_ones() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - var events = _fixture.CreateTestEvents(20).ToArray(); + var events = Fixture.CreateTestEvents(20).ToArray(); var appeared = new TaskCompletionSource(); var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); @@ -183,10 +186,10 @@ public async Task reads_all_existing_events_and_keep_listening_to_new_ones() { enumerator.MoveNext(); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, beforeEvents) + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, beforeEvents) .WithTimeout(); - using var subscription = await _fixture.Client + using var subscription = await Fixture.Streams .SubscribeToStreamAsync( stream, FromStream.Start, @@ -196,7 +199,7 @@ await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, beforeEv ) .WithTimeout(); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.Any, afterEvents) + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, afterEvents) .WithTimeout(); await appeared.Task.WithTimeout(); @@ -222,16 +225,17 @@ Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) return Task.CompletedTask; } - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); + void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => + dropped.SetResult((reason, ex)); } [Fact] public async Task catches_deletions() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - using var _ = await _fixture.Client + using var _ = await Fixture.Streams .SubscribeToStreamAsync( stream, FromStream.Start, @@ -241,7 +245,7 @@ public async Task catches_deletions() { ) .WithTimeout(); - await _fixture.Client.TombstoneAsync(stream, StreamState.NoStream); + await Fixture.Streams.TombstoneAsync(stream, StreamState.NoStream); var (reason, ex) = await dropped.Task.WithTimeout(); Assert.Equal(SubscriptionDroppedReason.ServerError, reason); @@ -250,16 +254,7 @@ public async Task catches_deletions() { Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) => Task.CompletedTask; - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); - } - - public class Fixture : EventStoreClientFixture { - public Fixture() => Events = CreateTestEvents(10).ToArray(); - - public EventData[] Events { get; } - - protected override Task Given() => Task.CompletedTask; - - protected override Task When() => Task.CompletedTask; + void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => + dropped.SetResult((reason, ex)); } } \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/subscribe_to_stream_live.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream_live.cs similarity index 69% rename from test/EventStore.Client.Streams.Tests/subscribe_to_stream_live.cs rename to test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream_live.cs index 6d7400815..1c7cca16c 100644 --- a/test/EventStore.Client.Streams.Tests/subscribe_to_stream_live.cs +++ b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream_live.cs @@ -1,27 +1,25 @@ namespace EventStore.Client.Streams.Tests; -[Trait("Category", "LongRunning")] -public class subscribe_to_stream_live : IClassFixture { - readonly Fixture _fixture; +[LongRunning] +public class subscribe_to_stream_live : IClassFixture { + public subscribe_to_stream_live(ITestOutputHelper output, EventStoreFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); - public subscribe_to_stream_live(Fixture fixture, ITestOutputHelper outputHelper) { - _fixture = fixture; - _fixture.CaptureLogs(outputHelper); - } + EventStoreFixture Fixture { get; } [Fact] public async Task does_not_read_existing_events_but_keep_listening_to_new_ones() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); var appeared = new TaskCompletionSource(); var dropped = new TaskCompletionSource(); - await _fixture.Client.AppendToStreamAsync( + await Fixture.Streams.AppendToStreamAsync( stream, StreamState.NoStream, - _fixture.CreateTestEvents() + Fixture.CreateTestEvents() ); - using var _ = await _fixture.Client + using var _ = await Fixture.Streams .SubscribeToStreamAsync( stream, FromStream.End, @@ -34,10 +32,10 @@ await _fixture.Client.AppendToStreamAsync( ) .WithTimeout(); - await _fixture.Client.AppendToStreamAsync( + await Fixture.Streams.AppendToStreamAsync( stream, new StreamRevision(0), - _fixture.CreateTestEvents() + Fixture.CreateTestEvents() ); Assert.Equal(new(1), await appeared.Task.WithTimeout()); @@ -45,11 +43,11 @@ await _fixture.Client.AppendToStreamAsync( [Fact] public async Task subscribe_to_non_existing_stream_and_then_catch_new_event() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); var appeared = new TaskCompletionSource(); var dropped = new TaskCompletionSource(); - using var _ = await _fixture.Client + using var _ = await Fixture.Streams .SubscribeToStreamAsync( stream, FromStream.End, @@ -62,10 +60,10 @@ public async Task subscribe_to_non_existing_stream_and_then_catch_new_event() { ) .WithTimeout(); - await _fixture.Client.AppendToStreamAsync( + await Fixture.Streams.AppendToStreamAsync( stream, StreamState.NoStream, - _fixture.CreateTestEvents() + Fixture.CreateTestEvents() ); Assert.True(await appeared.Task.WithTimeout()); @@ -73,21 +71,21 @@ await _fixture.Client.AppendToStreamAsync( [Fact] public async Task allow_multiple_subscriptions_to_same_stream() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); var appeared = new TaskCompletionSource(); var appearedCount = 0; - using var s1 = await _fixture.Client + using var s1 = await Fixture.Streams .SubscribeToStreamAsync(stream, FromStream.End, EventAppeared) .WithTimeout(); - using var s2 = await _fixture.Client + using var s2 = await Fixture.Streams .SubscribeToStreamAsync(stream, FromStream.End, EventAppeared) .WithTimeout(); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, _fixture.CreateTestEvents()); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents()); Assert.True(await appeared.Task.WithTimeout()); @@ -101,11 +99,11 @@ Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) [Fact] public async Task calls_subscription_dropped_when_disposed() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - using var _ = await _fixture.Client + using var _ = await Fixture.Streams .SubscribeToStreamAsync( stream, FromStream.End, @@ -115,7 +113,7 @@ public async Task calls_subscription_dropped_when_disposed() { ) .WithTimeout(); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, _fixture.CreateTestEvents()); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents()); Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) { s.Dispose(); @@ -132,11 +130,11 @@ Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) [Fact] public async Task catches_deletions() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - using var _ = await _fixture.Client + using var _ = await Fixture.Streams .SubscribeToStreamAsync( stream, FromStream.End, @@ -146,7 +144,7 @@ public async Task catches_deletions() { ) .WithTimeout(); - await _fixture.Client.TombstoneAsync(stream, StreamState.NoStream); + await Fixture.Streams.TombstoneAsync(stream, StreamState.NoStream); var (reason, ex) = await dropped.Task.WithTimeout(); Assert.Equal(SubscriptionDroppedReason.ServerError, reason); @@ -158,8 +156,5 @@ public async Task catches_deletions() { void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); } - 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.Streams.Tests/subscribe_to_stream_with_revision.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream_with_revision.cs similarity index 77% rename from test/EventStore.Client.Streams.Tests/subscribe_to_stream_with_revision.cs rename to test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream_with_revision.cs index e86535cd6..4b5f3b4b2 100644 --- a/test/EventStore.Client.Streams.Tests/subscribe_to_stream_with_revision.cs +++ b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream_with_revision.cs @@ -1,25 +1,19 @@ namespace EventStore.Client.Streams.Tests; -[Trait("Category", "LongRunning")] -public class subscribe_to_stream_with_revision : IAsyncLifetime { - readonly Fixture _fixture; +[DedicatedDatabase, LongRunning] +public class subscribe_to_stream_with_revision : IClassFixture { + public subscribe_to_stream_with_revision(ITestOutputHelper output, EventStoreFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); - public subscribe_to_stream_with_revision(ITestOutputHelper outputHelper) { - _fixture = new(); - _fixture.CaptureLogs(outputHelper); - } - - public Task InitializeAsync() => _fixture.InitializeAsync(); - - public Task DisposeAsync() => _fixture.DisposeAsync(); + EventStoreFixture Fixture { get; } [Fact] public async Task subscribe_to_non_existing_stream() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); var appeared = new TaskCompletionSource(); var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - using var subscription = await _fixture.Client + using var subscription = await Fixture.Streams .SubscribeToStreamAsync( stream, FromStream.Start, @@ -50,11 +44,11 @@ Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) [Fact] public async Task subscribe_to_non_existing_stream_then_get_event() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); var appeared = new TaskCompletionSource(); var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - using var subscription = await _fixture.Client + using var subscription = await Fixture.Streams .SubscribeToStreamAsync( stream, FromStream.After(StreamPosition.Start), @@ -64,10 +58,10 @@ public async Task subscribe_to_non_existing_stream_then_get_event() { ) .WithTimeout(); - await _fixture.Client.AppendToStreamAsync( + await Fixture.Streams.AppendToStreamAsync( stream, StreamState.NoStream, - _fixture.CreateTestEvents(2) + Fixture.CreateTestEvents(2) ); Assert.True(await appeared.Task.WithTimeout()); @@ -95,21 +89,21 @@ Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) [Fact] public async Task allow_multiple_subscriptions_to_same_stream() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); var appeared = new TaskCompletionSource(); var appearedCount = 0; - using var s1 = await _fixture.Client + using var s1 = await Fixture.Streams .SubscribeToStreamAsync(stream, FromStream.After(StreamPosition.Start), EventAppeared) .WithTimeout(); - using var s2 = await _fixture.Client + using var s2 = await Fixture.Streams .SubscribeToStreamAsync(stream, FromStream.After(StreamPosition.Start), EventAppeared) .WithTimeout(); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, _fixture.CreateTestEvents(2)); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents(2)); Assert.True(await appeared.Task.WithTimeout()); @@ -128,10 +122,10 @@ Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) [Fact] public async Task calls_subscription_dropped_when_disposed() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - using var subscription = await _fixture.Client + using var subscription = await Fixture.Streams .SubscribeToStreamAsync( stream, FromStream.Start, @@ -158,13 +152,13 @@ public async Task calls_subscription_dropped_when_disposed() { [Fact] public async Task calls_subscription_dropped_when_error_processing_event() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); var expectedException = new Exception("Error"); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, _fixture.CreateTestEvents(2)); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents(2)); - using var subscription = await _fixture.Client.SubscribeToStreamAsync( + using var subscription = await Fixture.Streams.SubscribeToStreamAsync( stream, FromStream.Start, EventAppeared, @@ -185,9 +179,9 @@ public async Task calls_subscription_dropped_when_error_processing_event() { [Fact] public async Task reads_all_existing_events_and_keep_listening_to_new_ones() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - var events = _fixture.CreateTestEvents(20).ToArray(); + var events = Fixture.CreateTestEvents(20).ToArray(); var appeared = new TaskCompletionSource(); var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); @@ -199,11 +193,11 @@ public async Task reads_all_existing_events_and_keep_listening_to_new_ones() { enumerator.MoveNext(); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, _fixture.CreateTestEvents()); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents()); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.Any, beforeEvents); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, beforeEvents); - using var subscription = await _fixture.Client + using var subscription = await Fixture.Streams .SubscribeToStreamAsync( stream, FromStream.After(StreamPosition.Start), @@ -213,7 +207,7 @@ public async Task reads_all_existing_events_and_keep_listening_to_new_ones() { ) .WithTimeout(); - var writeResult = await _fixture.Client.AppendToStreamAsync(stream, StreamState.Any, afterEvents); + var writeResult = await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, afterEvents); await appeared.Task.WithTimeout(); @@ -240,9 +234,4 @@ Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); } - - 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.Streams.Tests/append_to_stream_expected_version_no_stream.cs b/test/EventStore.Client.Streams.Tests/append_to_stream_expected_version_no_stream.cs index 25590ebd1..792bb642a 100644 --- a/test/EventStore.Client.Streams.Tests/append_to_stream_expected_version_no_stream.cs +++ b/test/EventStore.Client.Streams.Tests/append_to_stream_expected_version_no_stream.cs @@ -1,26 +1,31 @@ -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests; -public class append_to_stream_expected_version_no_stream : IClassFixture { - readonly Fixture _fixture; - - public append_to_stream_expected_version_no_stream(Fixture fixture) => _fixture = fixture; +public class append_to_stream_expected_version_no_stream : IClassFixture { + public append_to_stream_expected_version_no_stream(ITestOutputHelper output, EventStoreFixture fixture) { + Fixture = fixture.With(x => x.CaptureTestRun(output)); + } - [Fact] - public void succeeds() => Assert.Equal(new(0), _fixture.Result!.NextExpectedStreamRevision); + EventStoreFixture Fixture { get; } [Fact] - public void returns_position() => Assert.True(_fixture.Result!.LogPosition > Position.Start); + public async Task succeeds() { + var result = await Fixture.Streams.AppendToStreamAsync( + Fixture.GetStreamName(), + StreamState.NoStream, + Fixture.CreateTestEvents() + ); - public class Fixture : EventStoreClientFixture { - public IWriteResult? Result { get; private set; } + Assert.Equal(new(0), result!.NextExpectedStreamRevision); + } - protected override Task Given() => Task.CompletedTask; + [Fact] + public async Task returns_position() { + var result = await Fixture.Streams.AppendToStreamAsync( + Fixture.GetStreamName(), + StreamState.NoStream, + Fixture.CreateTestEvents() + ); - protected override async Task When() => - Result = await Client.AppendToStreamAsync( - "stream-1", - StreamState.NoStream, - CreateTestEvents() - ); + Assert.True(result.LogPosition > Position.Start); } } \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/append_to_stream_retry.cs b/test/EventStore.Client.Streams.Tests/append_to_stream_retry.cs index 9db0343e0..cf2c3c92e 100644 --- a/test/EventStore.Client.Streams.Tests/append_to_stream_retry.cs +++ b/test/EventStore.Client.Streams.Tests/append_to_stream_retry.cs @@ -1,61 +1,46 @@ -using Grpc.Core; -using Polly; +using Polly; -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests; -[Trait("Category", "Network")] -public class append_to_stream_retry : IClassFixture { - readonly Fixture _fixture; +[Network] +[DedicatedDatabase] +public class append_to_stream_retry : IClassFixture { + public append_to_stream_retry(ITestOutputHelper output, EventStoreFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); - public append_to_stream_retry(Fixture fixture) => _fixture = fixture; + EventStoreFixture Fixture { get; } [Fact] public async Task can_retry() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); // can definitely write without throwing - var nextExpected = (await WriteAnEventAsync(StreamRevision.None)).NextExpectedStreamRevision; - Assert.Equal(new(0), nextExpected); - - _fixture.TestServer.Stop(); - - // writeTask cannot complete because ES is stopped - var ex = await Assert.ThrowsAnyAsync(() => WriteAnEventAsync(new(0))); - Assert.True( - ex is RpcException { - Status.StatusCode: StatusCode.Unavailable - } or DiscoveryException + var result = await Fixture.Streams.AppendToStreamAsync( + stream, + StreamRevision.None, + Fixture.CreateTestEvents() ); - await _fixture.TestServer.StartAsync().WithTimeout(); + result.NextExpectedStreamRevision.ShouldBe(new(0)); + + await Fixture.Service.Restart(); // write can be retried var writeResult = await Policy .Handle() .WaitAndRetryAsync(2, _ => TimeSpan.FromSeconds(1)) - .ExecuteAsync(async () => await WriteAnEventAsync(new(0))); - - Assert.Equal(new(1), writeResult.NextExpectedStreamRevision); - - return; - - Task WriteAnEventAsync(StreamRevision expectedRevision) => - _fixture.Client.AppendToStreamAsync( - stream, - expectedRevision, - _fixture.CreateTestEvents(1) + .ExecuteAsync( + async () => await Fixture.Streams.AppendToStreamAsync( + stream, + result.NextExpectedStreamRevision, + Fixture.CreateTestEvents() + ) ); - } - public class Fixture : EventStoreClientFixture { - public Fixture() : base( - env: new() { - ["EVENTSTORE_MEM_DB"] = "false" - } - ) => - Settings.ConnectivitySettings.MaxDiscoverAttempts = 2; - - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; + writeResult.NextExpectedStreamRevision.ShouldBe(new(1)); } -} \ No newline at end of file +} + +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_to_stream_when_events_enumerator_throws.cs b/test/EventStore.Client.Streams.Tests/append_to_stream_when_events_enumerator_throws.cs index 70844f57e..67b8d3991 100644 --- a/test/EventStore.Client.Streams.Tests/append_to_stream_when_events_enumerator_throws.cs +++ b/test/EventStore.Client.Streams.Tests/append_to_stream_when_events_enumerator_throws.cs @@ -1,47 +1,37 @@ namespace EventStore.Client.Streams.Tests; -public class append_to_stream_when_events_enumerator_throws - : IClassFixture { - readonly Fixture _fixture; - - public append_to_stream_when_events_enumerator_throws(Fixture fixture) => _fixture = fixture; - - [Fact] - public void throws_the_exception() => Assert.IsType(_fixture.CaughtException); +public class append_to_stream_when_events_enumerator_throws : IClassFixture { + public append_to_stream_when_events_enumerator_throws(ITestOutputHelper output, EventStoreFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); + EventStoreFixture Fixture { get; } + [Fact] public async Task the_write_does_not_succeed() { - var result = _fixture.Client.ReadStreamAsync(Direction.Forwards, _fixture.StreamName, StreamPosition.Start); - Assert.Equal(ReadState.StreamNotFound, await result.ReadState); - } + var streamName = Fixture.GetStreamName(); - class EnumerationFailedException : Exception { } + await Fixture.Streams + .AppendToStreamAsync(streamName, StreamRevision.None, GetEvents()) + .ShouldThrowAsync(); - public class Fixture : EventStoreClientFixture { - public Fixture() => StreamName = GetStreamName("stream"); + var result = Fixture.Streams.ReadStreamAsync(Direction.Forwards, streamName, StreamPosition.Start); - public string StreamName { get; } - public Exception? CaughtException { get; private set; } + var state = await result.ReadState; - protected override async Task Given() { - try { - await Client.AppendToStreamAsync(StreamName, StreamRevision.None, Events()); - } - catch (Exception ex) { - CaughtException = ex; - } + state.ShouldBe(ReadState.StreamNotFound); + + return; - IEnumerable Events() { - var i = 0; - foreach (var e in CreateTestEvents(5)) { - if (i++ % 3 == 0) - throw new EnumerationFailedException(); + IEnumerable GetEvents() { + var i = 0; + foreach (var evt in Fixture.CreateTestEvents(5)) { + if (i++ % 3 == 0) + throw new EnumerationFailedException(); - yield return e; - } + yield return evt; } } - - protected override Task When() => Task.CompletedTask; } + + class EnumerationFailedException : Exception { } } \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/append_to_stream_with_timeout.cs b/test/EventStore.Client.Streams.Tests/append_to_stream_with_timeout.cs index 11189a163..5df05c065 100644 --- a/test/EventStore.Client.Streams.Tests/append_to_stream_with_timeout.cs +++ b/test/EventStore.Client.Streams.Tests/append_to_stream_with_timeout.cs @@ -1,51 +1,46 @@ using Grpc.Core; -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests; -[Trait("Category", "Network")] -public class append_to_stream_with_timeout : IClassFixture { - readonly Fixture _fixture; +[Network] +public class append_to_stream_with_timeout : IClassFixture { + public append_to_stream_with_timeout(ITestOutputHelper output, EventStoreFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); - public append_to_stream_with_timeout(Fixture fixture) => _fixture = fixture; + EventStoreFixture Fixture { get; } - [Fact] - public async Task any_stream_revision_fails_when_operation_expired() { - var stream = _fixture.GetStreamName(); - - var ex = await Assert.ThrowsAsync( - () => - _fixture.Client.AppendToStreamAsync( - stream, - StreamState.Any, - _fixture.CreateTestEvents(100), - deadline: TimeSpan.FromTicks(1) - ) - ); - - Assert.Equal(StatusCode.DeadlineExceeded, ex.StatusCode); + public static IEnumerable ArgumentOutOfRangeTestCases() { + yield return new object?[] { StreamState.Any }; + yield return new object?[] { ulong.MaxValue - 1UL }; } - + [Fact] - public async Task stream_revision_fails_when_operation_expired() { - var stream = _fixture.GetStreamName(); - - await _fixture.Client.AppendToStreamAsync(stream, StreamState.Any, _fixture.CreateTestEvents()); + public async Task any_stream_revision_fails_when_operation_expired() { + var stream = Fixture.GetStreamName(); - var ex = await Assert.ThrowsAsync( - () => - _fixture.Client.AppendToStreamAsync( - stream, - new StreamRevision(0), - _fixture.CreateTestEvents(100), - deadline: TimeSpan.Zero - ) - ); + var ex = await Fixture.Streams.AppendToStreamAsync( + stream, + StreamState.Any, + Fixture.CreateTestEvents(100), + deadline: TimeSpan.FromTicks(1) + ).ShouldThrowAsync(); - Assert.Equal(StatusCode.DeadlineExceeded, ex.StatusCode); + ex.StatusCode.ShouldBe(StatusCode.DeadlineExceeded); } - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; + [Fact] + public async Task stream_revision_fails_when_operation_expired() { + var stream = Fixture.GetStreamName(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, Fixture.CreateTestEvents()); + + var ex = await Fixture.Streams.AppendToStreamAsync( + stream, + new StreamRevision(0), + Fixture.CreateTestEvents(10), + deadline: TimeSpan.Zero + ).ShouldThrowAsync(); + + ex.StatusCode.ShouldBe(StatusCode.DeadlineExceeded); } } \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/appending_to_implicitly_created_stream.cs b/test/EventStore.Client.Streams.Tests/appending_to_implicitly_created_stream.cs index 99081b0a5..4b5846b47 100644 --- a/test/EventStore.Client.Streams.Tests/appending_to_implicitly_created_stream.cs +++ b/test/EventStore.Client.Streams.Tests/appending_to_implicitly_created_stream.cs @@ -1,22 +1,23 @@ namespace EventStore.Client.Streams.Tests; -[Trait("Category", "LongRunning")] +[LongRunning] public class appending_to_implicitly_created_stream - : IClassFixture { - readonly Fixture _fixture; + : IClassFixture { + public appending_to_implicitly_created_stream(ITestOutputHelper output, EventStoreFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); - public appending_to_implicitly_created_stream(Fixture fixture) => _fixture = fixture; + EventStoreFixture Fixture { get; } [Fact] public async Task sequence_0em1_1e0_2e1_3e2_4e3_5e4_0em1_idempotent() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - var events = _fixture.CreateTestEvents(6).ToArray(); + var events = Fixture.CreateTestEvents(6).ToArray(); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, events); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(1)); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(1)); - var count = await _fixture.Client + var count = await Fixture.Streams .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); Assert.Equal(events.Length, count); @@ -24,14 +25,14 @@ public async Task sequence_0em1_1e0_2e1_3e2_4e3_5e4_0em1_idempotent() { [Fact] public async Task sequence_0em1_1e0_2e1_3e2_4e3_4e4_0any_idempotent() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - var events = _fixture.CreateTestEvents(6).ToArray(); + var events = Fixture.CreateTestEvents(6).ToArray(); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, events); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.Any, events.Take(1)); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, events.Take(1)); - var count = await _fixture.Client + var count = await Fixture.Streams .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); Assert.Equal(events.Length, count); @@ -39,14 +40,14 @@ public async Task sequence_0em1_1e0_2e1_3e2_4e3_4e4_0any_idempotent() { [Fact] public async Task sequence_0em1_1e0_2e1_3e2_4e3_5e4_0e5_non_idempotent() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - var events = _fixture.CreateTestEvents(6).ToArray(); + var events = Fixture.CreateTestEvents(6).ToArray(); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, events); - await _fixture.Client.AppendToStreamAsync(stream, new StreamRevision(5), events.Take(1)); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(5), events.Take(1)); - var count = await _fixture.Client + var count = await Fixture.Streams .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 2).CountAsync(); Assert.Equal(events.Length + 1, count); @@ -54,24 +55,24 @@ public async Task sequence_0em1_1e0_2e1_3e2_4e3_5e4_0e5_non_idempotent() { [Fact] public async Task sequence_0em1_1e0_2e1_3e2_4e3_5e4_0e6_throws_wev() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - var events = _fixture.CreateTestEvents(6).ToArray(); + var events = Fixture.CreateTestEvents(6).ToArray(); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - await Assert.ThrowsAsync(() => _fixture.Client.AppendToStreamAsync(stream, new StreamRevision(6), events.Take(1))); + 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 stream = Fixture.GetStreamName(); - var events = _fixture.CreateTestEvents(6).ToArray(); + var events = Fixture.CreateTestEvents(6).ToArray(); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - var writeResult = await _fixture.Client.AppendToStreamAsync( + var writeResult = await Fixture.Streams.AppendToStreamAsync( stream, new StreamRevision(6), events.Take(1), @@ -83,24 +84,24 @@ public async Task sequence_0em1_1e0_2e1_3e2_4e3_5e4_0e6_returns_wev() { [Fact] public async Task sequence_0em1_1e0_2e1_3e2_4e3_5e4_0e4_throws_wev() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - var events = _fixture.CreateTestEvents(6).ToArray(); + var events = Fixture.CreateTestEvents(6).ToArray(); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - await Assert.ThrowsAsync(() => _fixture.Client.AppendToStreamAsync(stream, new StreamRevision(4), events.Take(1))); + 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 stream = Fixture.GetStreamName(); - var events = _fixture.CreateTestEvents(6).ToArray(); + var events = Fixture.CreateTestEvents(6).ToArray(); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - var writeResult = await _fixture.Client.AppendToStreamAsync( + var writeResult = await Fixture.Streams.AppendToStreamAsync( stream, new StreamRevision(4), events.Take(1), @@ -112,14 +113,14 @@ public async Task sequence_0em1_1e0_2e1_3e2_4e3_5e4_0e4_returns_wev() { [Fact] public async Task sequence_0em1_0e0_non_idempotent() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - var events = _fixture.CreateTestEvents().ToArray(); + var events = Fixture.CreateTestEvents().ToArray(); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, events); - await _fixture.Client.AppendToStreamAsync(stream, new StreamRevision(0), events.Take(1)); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(0), events.Take(1)); - var count = await _fixture.Client + var count = await Fixture.Streams .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 2).CountAsync(); Assert.Equal(events.Length + 1, count); @@ -127,15 +128,15 @@ public async Task sequence_0em1_0e0_non_idempotent() { [Fact] public async Task sequence_0em1_0any_idempotent() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - var events = _fixture.CreateTestEvents().ToArray(); + var events = Fixture.CreateTestEvents().ToArray(); await Task.Delay(TimeSpan.FromSeconds(30)); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, events); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.Any, events.Take(1)); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, events.Take(1)); - var count = await _fixture.Client + var count = await Fixture.Streams .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); Assert.Equal(events.Length, count); @@ -143,14 +144,14 @@ public async Task sequence_0em1_0any_idempotent() { [Fact] public async Task sequence_0em1_0em1_idempotent() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - var events = _fixture.CreateTestEvents().ToArray(); + var events = Fixture.CreateTestEvents().ToArray(); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, events); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(1)); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(1)); - var count = await _fixture.Client + var count = await Fixture.Streams .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); Assert.Equal(events.Length, count); @@ -158,15 +159,15 @@ public async Task sequence_0em1_0em1_idempotent() { [Fact] public async Task sequence_0em1_1e0_2e1_1any_1any_idempotent() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - var events = _fixture.CreateTestEvents(3).ToArray(); + var events = Fixture.CreateTestEvents(3).ToArray(); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, events); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.Any, events.Skip(1).Take(1)); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.Any, events.Skip(1).Take(1)); + 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.Client + var count = await Fixture.Streams .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); Assert.Equal(events.Length, count); @@ -174,14 +175,14 @@ public async Task sequence_0em1_1e0_2e1_1any_1any_idempotent() { [Fact] public async Task sequence_S_0em1_1em1_E_S_0em1_E_idempotent() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - var events = _fixture.CreateTestEvents(2).ToArray(); + var events = Fixture.CreateTestEvents(2).ToArray(); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, events); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(1)); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(1)); - var count = await _fixture.Client + var count = await Fixture.Streams .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); Assert.Equal(events.Length, count); @@ -189,14 +190,14 @@ public async Task sequence_S_0em1_1em1_E_S_0em1_E_idempotent() { [Fact] public async Task sequence_S_0em1_1em1_E_S_0any_E_idempotent() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - var events = _fixture.CreateTestEvents(2).ToArray(); + var events = Fixture.CreateTestEvents(2).ToArray(); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, events); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.Any, events.Take(1)); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, events.Take(1)); - var count = await _fixture.Client + var count = await Fixture.Streams .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); Assert.Equal(events.Length, count); @@ -204,15 +205,15 @@ public async Task sequence_S_0em1_1em1_E_S_0any_E_idempotent() { [Fact] public async Task sequence_S_0em1_1em1_E_S_1e0_E_idempotent() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - var events = _fixture.CreateTestEvents(2).ToArray(); + var events = Fixture.CreateTestEvents(2).ToArray(); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - await _fixture.Client.AppendToStreamAsync(stream, new StreamRevision(0), events.Skip(1)); + await Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(0), events.Skip(1)); - var count = await _fixture.Client + var count = await Fixture.Streams .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); Assert.Equal(events.Length, count); @@ -220,14 +221,14 @@ public async Task sequence_S_0em1_1em1_E_S_1e0_E_idempotent() { [Fact] public async Task sequence_S_0em1_1em1_E_S_1any_E_idempotent() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - var events = _fixture.CreateTestEvents(2).ToArray(); + var events = Fixture.CreateTestEvents(2).ToArray(); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, events); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.Any, events.Skip(1).Take(1)); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, events.Skip(1).Take(1)); - var count = await _fixture.Client + var count = await Fixture.Streams .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); Assert.Equal(events.Length, count); @@ -235,14 +236,14 @@ public async Task sequence_S_0em1_1em1_E_S_1any_E_idempotent() { [Fact] public async Task sequence_S_0em1_1em1_E_S_0em1_1em1_2em1_E_idempotancy_fail_throws() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - var events = _fixture.CreateTestEvents(3).ToArray(); + var events = Fixture.CreateTestEvents(3).ToArray(); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(2)); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(2)); await Assert.ThrowsAsync( - () => _fixture.Client.AppendToStreamAsync( + () => Fixture.Streams.AppendToStreamAsync( stream, StreamState.NoStream, events @@ -252,13 +253,13 @@ await Assert.ThrowsAsync( [Fact] public async Task sequence_S_0em1_1em1_E_S_0em1_1em1_2em1_E_idempotancy_fail_returns() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - var events = _fixture.CreateTestEvents(3).ToArray(); + var events = Fixture.CreateTestEvents(3).ToArray(); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(2)); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(2)); - var writeResult = await _fixture.Client.AppendToStreamAsync( + var writeResult = await Fixture.Streams.AppendToStreamAsync( stream, StreamState.NoStream, events, @@ -267,9 +268,4 @@ public async Task sequence_S_0em1_1em1_E_S_0em1_1em1_2em1_E_idempotancy_fail_ret Assert.IsType(writeResult); } - - 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.Streams.Tests/deleting_stream.cs b/test/EventStore.Client.Streams.Tests/deleting_stream.cs index 98a7799e1..2f76d1d1b 100644 --- a/test/EventStore.Client.Streams.Tests/deleting_stream.cs +++ b/test/EventStore.Client.Streams.Tests/deleting_stream.cs @@ -1,10 +1,11 @@ namespace EventStore.Client.Streams.Tests; -[Trait("Category", "Network")] -public class deleting_stream : IClassFixture { - readonly Fixture _fixture; +[Network] +public class deleting_stream : IClassFixture { + public deleting_stream(ITestOutputHelper output, EventStoreFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); - public deleting_stream(Fixture fixture) => _fixture = fixture; + EventStoreFixture Fixture { get; } public static IEnumerable ExpectedStreamStateCases() { yield return new object?[] { StreamState.Any, nameof(StreamState.Any) }; @@ -14,75 +15,70 @@ public class deleting_stream : IClassFixture { [Theory] [MemberData(nameof(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}"; + var stream = $"{Fixture.GetStreamName()}_{name}"; - await _fixture.Client.TombstoneAsync(stream, expectedVersion); + await Fixture.Streams.TombstoneAsync(stream, expectedVersion); } [Regression.Fact(21, "fixed by")] public async Task soft_deleting_a_stream_that_exists() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - await _fixture.Client.AppendToStreamAsync(stream, StreamRevision.None, _fixture.CreateTestEvents()); + await Fixture.Streams.AppendToStreamAsync(stream, StreamRevision.None, Fixture.CreateTestEvents()); - await _fixture.Client.DeleteAsync(stream, StreamState.StreamExists); + await Fixture.Streams.DeleteAsync(stream, StreamState.StreamExists); } [Fact] public async Task hard_deleting_a_stream_that_does_not_exist_with_wrong_expected_version_throws() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - await Assert.ThrowsAsync(() => _fixture.Client.TombstoneAsync(stream, new StreamRevision(0))); + await Assert.ThrowsAsync(() => Fixture.Streams.TombstoneAsync(stream, new StreamRevision(0))); } [Fact] public async Task soft_deleting_a_stream_that_does_not_exist_with_wrong_expected_version_throws() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - await Assert.ThrowsAsync(() => _fixture.Client.DeleteAsync(stream, new StreamRevision(0))); + await Assert.ThrowsAsync(() => Fixture.Streams.DeleteAsync(stream, new StreamRevision(0))); } [Fact] public async Task hard_deleting_a_stream_should_return_log_position() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - var writeResult = await _fixture.Client.AppendToStreamAsync( + var writeResult = await Fixture.Streams.AppendToStreamAsync( stream, StreamState.NoStream, - _fixture.CreateTestEvents() + Fixture.CreateTestEvents() ); - var deleteResult = await _fixture.Client.TombstoneAsync(stream, writeResult.NextExpectedStreamRevision); + var deleteResult = await Fixture.Streams.TombstoneAsync(stream, writeResult.NextExpectedStreamRevision); Assert.True(deleteResult.LogPosition > writeResult.LogPosition); } [Fact] public async Task soft_deleting_a_stream_should_return_log_position() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - var writeResult = await _fixture.Client.AppendToStreamAsync( + var writeResult = await Fixture.Streams.AppendToStreamAsync( stream, StreamState.NoStream, - _fixture.CreateTestEvents() + Fixture.CreateTestEvents() ); - var deleteResult = await _fixture.Client.DeleteAsync(stream, writeResult.NextExpectedStreamRevision); + var deleteResult = await Fixture.Streams.DeleteAsync(stream, writeResult.NextExpectedStreamRevision); Assert.True(deleteResult.LogPosition > writeResult.LogPosition); } [Fact] public async Task hard_deleting_a_deleted_stream_should_throw() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - await _fixture.Client.TombstoneAsync(stream, StreamState.NoStream); + await Fixture.Streams.TombstoneAsync(stream, StreamState.NoStream); - await Assert.ThrowsAsync(() => _fixture.Client.TombstoneAsync(stream, StreamState.NoStream)); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; + await Assert.ThrowsAsync(() => Fixture.Streams.TombstoneAsync(stream, StreamState.NoStream)); } } \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/is_json.cs b/test/EventStore.Client.Streams.Tests/is_json.cs index ac0fa8ae1..8b7943811 100644 --- a/test/EventStore.Client.Streams.Tests/is_json.cs +++ b/test/EventStore.Client.Streams.Tests/is_json.cs @@ -3,12 +3,13 @@ namespace EventStore.Client.Streams.Tests; -[Trait("Category", "Network")] -[Trait("Category", "LongRunning")] -public class is_json : IClassFixture { - readonly Fixture _fixture; +[Network] +[LongRunning] +public class is_json : IClassFixture { + public is_json(ITestOutputHelper output, EventStoreFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); - public is_json(Fixture fixture) => _fixture = fixture; + EventStoreFixture Fixture { get; } public static IEnumerable TestCases() { var json = @"{""some"":""json""}"; @@ -36,9 +37,9 @@ public async Task is_preserved(bool isJson, string data, string metadata) { : Constants.Metadata.ContentTypes.ApplicationOctetStream ); - await _fixture.Client.AppendToStreamAsync(stream, StreamState.Any, new[] { eventData }); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, new[] { eventData }); - var @event = await _fixture.Client + var @event = await Fixture.Streams .ReadStreamAsync( Direction.Forwards, stream, @@ -60,10 +61,5 @@ public async Task is_preserved(bool isJson, string data, string metadata) { } 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")}"; - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } + $"{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/read_all_backward_messages.cs b/test/EventStore.Client.Streams.Tests/read_all_backward_messages.cs index 1c980605a..c4a5d9904 100644 --- a/test/EventStore.Client.Streams.Tests/read_all_backward_messages.cs +++ b/test/EventStore.Client.Streams.Tests/read_all_backward_messages.cs @@ -1,20 +1,21 @@ namespace EventStore.Client.Streams.Tests; -[Trait("Category", "Network")] -public class read_all_backward_messages : IClassFixture { - readonly Fixture _fixture; +[Network] +public class read_all_backward_messages : IClassFixture { + public read_all_backward_messages(ITestOutputHelper output, EventStoreFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); - public read_all_backward_messages(Fixture fixture) => _fixture = fixture; + EventStoreFixture Fixture { get; } [Fact] public async Task stream_found() { - var events = _fixture.CreateTestEvents(32).ToArray(); + var events = Fixture.CreateTestEvents(32).ToArray(); - var streamName = _fixture.GetStreamName(); + var streamName = Fixture.GetStreamName(); - await _fixture.Client.AppendToStreamAsync(streamName, StreamState.NoStream, events); + await Fixture.Streams.AppendToStreamAsync(streamName, StreamState.NoStream, events); - var result = await _fixture.Client.ReadAllAsync( + var result = await Fixture.Streams.ReadAllAsync( Direction.Backwards, Position.End, 32, @@ -23,9 +24,4 @@ public async Task stream_found() { Assert.Equal(32, result.OfType().Count()); } - - 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.Streams.Tests/read_all_events_forward.cs b/test/EventStore.Client.Streams.Tests/read_all_events_forward.cs index 335d3e77e..bc684d3ee 100644 --- a/test/EventStore.Client.Streams.Tests/read_all_events_forward.cs +++ b/test/EventStore.Client.Streams.Tests/read_all_events_forward.cs @@ -1,39 +1,39 @@ -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests; -[Trait("Category", "LongRunning")] -public class read_all_events_forward : IClassFixture { - const string Stream = "stream"; - readonly Fixture _fixture; +[LongRunning] +public class read_all_events_forward : IClassFixture { + public read_all_events_forward(ITestOutputHelper output, ReadAllEventsForward fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); - public read_all_events_forward(Fixture fixture) => _fixture = fixture; + ReadAllEventsForward Fixture { get; } [Fact] public async Task return_empty_if_reading_from_end() { - var count = await _fixture.Client.ReadAllAsync(Direction.Forwards, Position.End, 1).CountAsync(); + var count = await Fixture.Streams.ReadAllAsync(Direction.Forwards, Position.End, 1).CountAsync(); Assert.Equal(0, count); } [Fact] public async Task return_partial_slice_if_not_enough_events() { - var events = await _fixture.Client - .ReadAllAsync(Direction.Forwards, Position.Start, _fixture.Events.Length * 2) + var events = await Fixture.Streams + .ReadAllAsync(Direction.Forwards, Position.Start, Fixture.Events.Length * 2) .ToArrayAsync(); - Assert.True(events.Length < _fixture.Events.Length * 2); + Assert.True(events.Length < Fixture.Events.Length * 2); } [Fact] public async Task return_events_in_correct_order_compared_to_written() { - var events = await _fixture.Client - .ReadAllAsync(Direction.Forwards, Position.Start, _fixture.Events.Length * 2) + var events = await Fixture.Streams + .ReadAllAsync(Direction.Forwards, Position.Start, Fixture.Events.Length * 2) .ToArrayAsync(); - Assert.True(EventDataComparer.Equal(_fixture.Events, events.AsResolvedTestEvents().ToArray())); + Assert.True(EventDataComparer.Equal(Fixture.Events, events.AsResolvedTestEvents().ToArray())); } [Fact] public async Task return_single_event() { - var events = await _fixture.Client.ReadAllAsync(Direction.Forwards, Position.Start, 1) + var events = await Fixture.Streams.ReadAllAsync(Direction.Forwards, Position.Start, 1) .ToArrayAsync(); Assert.Single(events); @@ -50,9 +50,9 @@ public async Task return_single_event() { [Fact] public async Task max_count_is_respected() { - var maxCount = _fixture.Events.Length / 2; - var events = await _fixture.Client.ReadAllAsync(Direction.Forwards, Position.Start, maxCount) - .Take(_fixture.Events.Length) + var maxCount = Fixture.Events.Length / 2; + var events = await Fixture.Streams.ReadAllAsync(Direction.Forwards, Position.Start, maxCount) + .Take(Fixture.Events.Length) .ToArrayAsync(); Assert.Equal(maxCount, events.Length); @@ -60,14 +60,16 @@ public async Task max_count_is_respected() { [Fact] public async Task reads_all_events_by_default() { - var count = await _fixture.Client.ReadAllAsync(Direction.Forwards, Position.Start) + var count = await Fixture.Streams.ReadAllAsync(Direction.Forwards, Position.Start) .CountAsync(); - Assert.True(count >= _fixture.Events.Length); + Assert.True(count >= Fixture.Events.Length); } +} - public class Fixture : EventStoreClientFixture { - public Fixture() => +public class ReadAllEventsForward : EventStoreFixture { + public ReadAllEventsForward() { + OnSetup = async () => { Events = Enumerable .Concat( CreateTestEvents(20), @@ -75,19 +77,18 @@ public Fixture() => ) .ToArray(); - public EventData[] Events { get; } + var streamName = GetStreamName(); - protected override async Task Given() { - var result = await Client.SetStreamMetadataAsync( + var result = await Streams.SetStreamMetadataAsync( SystemStreams.AllStream, StreamState.NoStream, new(acl: new(SystemRoles.All)), userCredentials: TestCredentials.Root ); - await Client.AppendToStreamAsync(Stream, StreamState.NoStream, Events); - } - - protected override Task When() => Task.CompletedTask; + await Streams.AppendToStreamAsync(streamName, StreamState.NoStream, Events); + }; } + + public EventData[] Events { get; private set; } = Array.Empty(); } \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/read_all_events_forward_with_linkto_passed_max_count.cs b/test/EventStore.Client.Streams.Tests/read_all_events_forward_with_linkto_passed_max_count.cs index 50ff40b1e..f71840c79 100644 --- a/test/EventStore.Client.Streams.Tests/read_all_events_forward_with_linkto_passed_max_count.cs +++ b/test/EventStore.Client.Streams.Tests/read_all_events_forward_with_linkto_passed_max_count.cs @@ -2,53 +2,49 @@ namespace EventStore.Client.Streams.Tests; -[Trait("Category", "LongRunning")] -public class read_all_events_forward_with_linkto_passed_max_count - : IClassFixture { - readonly Fixture _fixture; - - public read_all_events_forward_with_linkto_passed_max_count(Fixture fixture) => _fixture = fixture; +[LongRunning] +public class read_all_events_forward_with_linkto_passed_max_count : IClassFixture { + public read_all_events_forward_with_linkto_passed_max_count(ITestOutputHelper output, EventStoreFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); + EventStoreFixture Fixture { get; } + [Fact] - public void one_event_is_read() => Assert.Single(_fixture.Events ?? Array.Empty()); - - public class Fixture : EventStoreClientFixture { - const string DeletedStream = nameof(DeletedStream); - const string LinkedStream = nameof(LinkedStream); - public ResolvedEvent[]? Events { get; private set; } - - protected override async Task Given() { - await Client.AppendToStreamAsync(DeletedStream, StreamState.Any, CreateTestEvents()); - await Client.SetStreamMetadataAsync( - DeletedStream, - StreamState.Any, - new(2) - ); - - await Client.AppendToStreamAsync(DeletedStream, StreamState.Any, CreateTestEvents()); - await Client.AppendToStreamAsync(DeletedStream, StreamState.Any, CreateTestEvents()); - await Client.AppendToStreamAsync( - LinkedStream, - StreamState.Any, - new[] { - new EventData( - Uuid.NewUuid(), - SystemEventTypes.LinkTo, - Encoding.UTF8.GetBytes("0@" + DeletedStream), - Array.Empty(), - Constants.Metadata.ContentTypes.ApplicationOctetStream - ) - } - ); - } - - protected override async Task When() => - Events = await Client.ReadStreamAsync( - Direction.Forwards, - LinkedStream, - StreamPosition.Start, - resolveLinkTos: true + public async Task 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, + StreamState.Any, + new(2) + ); + + await Fixture.Streams.AppendToStreamAsync(deletedStream, StreamState.Any, Fixture.CreateTestEvents()); + await Fixture.Streams.AppendToStreamAsync(deletedStream, StreamState.Any, Fixture.CreateTestEvents()); + await Fixture.Streams.AppendToStreamAsync( + linkedStream, + StreamState.Any, + new[] { + new EventData( + Uuid.NewUuid(), + SystemEventTypes.LinkTo, + Encoding.UTF8.GetBytes("0@" + deletedStream), + Array.Empty(), + Constants.Metadata.ContentTypes.ApplicationOctetStream ) - .ToArrayAsync(); + } + ); + + var events = await Fixture.Streams.ReadStreamAsync( + Direction.Forwards, + linkedStream, + StreamPosition.Start, + resolveLinkTos: true + ) + .ToArrayAsync(); + + Assert.Single(events); } } \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/read_all_forward_messages.cs b/test/EventStore.Client.Streams.Tests/read_all_forward_messages.cs index 34ffbffd7..df2fddc14 100644 --- a/test/EventStore.Client.Streams.Tests/read_all_forward_messages.cs +++ b/test/EventStore.Client.Streams.Tests/read_all_forward_messages.cs @@ -1,20 +1,21 @@ -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests; -[Trait("Category", "Network")] -public class read_all_forward_messages : IClassFixture { - readonly Fixture _fixture; +[Network] +public class read_all_forward_messages : IClassFixture { + public read_all_forward_messages(ITestOutputHelper output, EventStoreFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); - public read_all_forward_messages(Fixture fixture) => _fixture = fixture; + EventStoreFixture Fixture { get; } [Fact] public async Task stream_found() { - var events = _fixture.CreateTestEvents(32).ToArray(); + var events = Fixture.CreateTestEvents(32).ToArray(); - var streamName = _fixture.GetStreamName(); + var streamName = Fixture.GetStreamName(); - await _fixture.Client.AppendToStreamAsync(streamName, StreamState.NoStream, events); + await Fixture.Streams.AppendToStreamAsync(streamName, StreamState.NoStream, events); - var result = await _fixture.Client.ReadAllAsync( + var result = await Fixture.Streams.ReadAllAsync( Direction.Forwards, Position.Start, 32, @@ -23,9 +24,4 @@ public async Task stream_found() { Assert.Equal(32, result.OfType().Count()); } - - 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.Streams.Tests/read_all_with_timeout.cs b/test/EventStore.Client.Streams.Tests/read_all_with_timeout.cs index ffbf644c3..b85c65f66 100644 --- a/test/EventStore.Client.Streams.Tests/read_all_with_timeout.cs +++ b/test/EventStore.Client.Streams.Tests/read_all_with_timeout.cs @@ -1,17 +1,18 @@ using Grpc.Core; -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests; -[Trait("Category", "Network")] -public class read_all_with_timeout : IClassFixture { - readonly Fixture _fixture; +[Network] +public class read_all_with_timeout : IClassFixture { + public read_all_with_timeout(ITestOutputHelper output, EventStoreFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); - public read_all_with_timeout(Fixture fixture) => _fixture = fixture; + EventStoreFixture Fixture { get; } [Fact] public async Task fails_when_operation_expired() { var rpcException = await Assert.ThrowsAsync( - () => _fixture.Client + () => Fixture.Streams .ReadAllAsync( Direction.Backwards, Position.Start, @@ -24,9 +25,4 @@ public async Task fails_when_operation_expired() { Assert.Equal(StatusCode.DeadlineExceeded, rpcException.StatusCode); } - - 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.Streams.Tests/read_events_linked_to_deleted_stream.cs b/test/EventStore.Client.Streams.Tests/read_events_linked_to_deleted_stream.cs deleted file mode 100644 index 2fded6228..000000000 --- a/test/EventStore.Client.Streams.Tests/read_events_linked_to_deleted_stream.cs +++ /dev/null @@ -1,80 +0,0 @@ -using System.Text; - -namespace EventStore.Client.Streams.Tests; - -public abstract class read_events_linked_to_deleted_stream { - readonly Fixture _fixture; - - protected read_events_linked_to_deleted_stream(Fixture fixture) => _fixture = fixture; - - [Fact] - public void one_event_is_read() => Assert.Single(_fixture.Events ?? Array.Empty()); - - [Fact] - public void the_linked_event_is_not_resolved() => Assert.Null(_fixture.Events![0].Event); - - [Fact] - public void the_link_event_is_included() => Assert.NotNull(_fixture.Events![0].OriginalEvent); - - [Fact] - public void the_event_is_not_resolved() => Assert.False(_fixture.Events![0].IsResolved); - - public abstract class Fixture : EventStoreClientFixture { - const string DeletedStream = nameof(DeletedStream); - protected const string LinkedStream = nameof(LinkedStream); - public ResolvedEvent[]? Events { get; private set; } - - protected override async Task Given() { - await Client.AppendToStreamAsync(DeletedStream, StreamState.Any, CreateTestEvents()); - await Client.AppendToStreamAsync( - LinkedStream, - StreamState.Any, - new[] { - new EventData( - Uuid.NewUuid(), - SystemEventTypes.LinkTo, - Encoding.UTF8.GetBytes("0@" + DeletedStream), - Array.Empty(), - Constants.Metadata.ContentTypes.ApplicationOctetStream - ) - } - ); - - await Client.DeleteAsync(DeletedStream, StreamState.Any); - } - - protected override async Task When() => Events = await Read(); - - protected abstract ValueTask Read(); - } - - public class @forwards : read_events_linked_to_deleted_stream, IClassFixture { - public forwards(Fixture fixture) : base(fixture) { } - - public new class Fixture : read_events_linked_to_deleted_stream.Fixture { - protected override ValueTask Read() => - Client.ReadStreamAsync( - Direction.Forwards, - LinkedStream, - StreamPosition.Start, - 1, - true - ).ToArrayAsync(); - } - } - - public class @backwards : read_events_linked_to_deleted_stream, IClassFixture { - public backwards(Fixture fixture) : base(fixture) { } - - public new class Fixture : read_events_linked_to_deleted_stream.Fixture { - protected override ValueTask Read() => - Client.ReadStreamAsync( - Direction.Backwards, - LinkedStream, - StreamPosition.Start, - 1, - true - ).ToArrayAsync(); - } - } -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/read_stream_backward_messages.cs b/test/EventStore.Client.Streams.Tests/read_stream_backward_messages.cs deleted file mode 100644 index 581194679..000000000 --- a/test/EventStore.Client.Streams.Tests/read_stream_backward_messages.cs +++ /dev/null @@ -1,51 +0,0 @@ -namespace EventStore.Client.Streams.Tests; - -[Trait("Category", "Network")] -public class read_stream_backward_messages : IClassFixture { - readonly Fixture _fixture; - - public read_stream_backward_messages(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task stream_not_found() { - var result = await _fixture.Client.ReadStreamAsync( - Direction.Backwards, - _fixture.GetStreamName(), - StreamPosition.End - ).Messages.SingleAsync(); - - Assert.Equal(StreamMessage.NotFound.Instance, result); - } - - [Fact] - public async Task stream_found() { - var events = _fixture.CreateTestEvents(_fixture.Count).ToArray(); - - var streamName = _fixture.GetStreamName(); - - await _fixture.Client.AppendToStreamAsync(streamName, StreamState.NoStream, events); - - var result = await _fixture.Client.ReadStreamAsync( - Direction.Backwards, - streamName, - StreamPosition.End - ).Messages.ToArrayAsync(); - - Assert.Equal( - _fixture.Count + (_fixture.HasLastStreamPosition ? 2 : 1), - result.Length - ); - - Assert.Equal(StreamMessage.Ok.Instance, result[0]); - Assert.Equal(_fixture.Count, result.OfType().Count()); - if (_fixture.HasLastStreamPosition) - Assert.Equal(new StreamMessage.LastStreamPosition(new(31)), result[^1]); - } - - public class Fixture : EventStoreClientFixture { - public int Count => 32; - public bool HasLastStreamPosition => (EventStoreTestServer.Version?.Major ?? int.MaxValue) >= 21; - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/read_stream_forward_messages.cs b/test/EventStore.Client.Streams.Tests/read_stream_forward_messages.cs deleted file mode 100644 index 69d0d1538..000000000 --- a/test/EventStore.Client.Streams.Tests/read_stream_forward_messages.cs +++ /dev/null @@ -1,99 +0,0 @@ -namespace EventStore.Client.Streams.Tests; - -[Trait("Category", "Network")] -public class read_stream_forward_messages : IClassFixture { - readonly Fixture _fixture; - - public read_stream_forward_messages(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task stream_not_found() { - var result = await _fixture.Client.ReadStreamAsync( - Direction.Forwards, - _fixture.GetStreamName(), - StreamPosition.Start - ).Messages.SingleAsync(); - - Assert.Equal(StreamMessage.NotFound.Instance, result); - } - - [Fact] - public async Task stream_found() { - var events = _fixture.CreateTestEvents(_fixture.Count).ToArray(); - - var streamName = _fixture.GetStreamName(); - - await _fixture.Client.AppendToStreamAsync(streamName, StreamState.NoStream, events); - - var result = await _fixture.Client.ReadStreamAsync( - Direction.Forwards, - streamName, - StreamPosition.Start - ).Messages.ToArrayAsync(); - - Assert.Equal( - _fixture.Count + (_fixture.HasStreamPositions ? 2 : 1), - result.Length - ); - - Assert.Equal(StreamMessage.Ok.Instance, result[0]); - Assert.Equal(_fixture.Count, result.OfType().Count()); - var first = Assert.IsType(result[1]); - Assert.Equal(new(0), first.ResolvedEvent.OriginalEventNumber); - var last = Assert.IsType(result[_fixture.HasStreamPositions ? ^2 : ^1]); - Assert.Equal(new((ulong)_fixture.Count - 1), last.ResolvedEvent.OriginalEventNumber); - - if (_fixture.HasStreamPositions) - if (_fixture.HasStreamPositions) - Assert.Equal( - new StreamMessage.LastStreamPosition(new((ulong)_fixture.Count - 1)), - result[^1] - ); - } - - [Fact] - public async Task stream_found_truncated() { - var events = _fixture.CreateTestEvents(_fixture.Count).ToArray(); - - var streamName = _fixture.GetStreamName(); - - await _fixture.Client.AppendToStreamAsync(streamName, StreamState.NoStream, events); - - await _fixture.Client.SetStreamMetadataAsync( - streamName, - StreamState.Any, - new(truncateBefore: new StreamPosition(32)) - ); - - var result = await _fixture.Client.ReadStreamAsync( - Direction.Forwards, - streamName, - StreamPosition.Start - ).Messages.ToArrayAsync(); - - Assert.Equal( - _fixture.Count - 32 + (_fixture.HasStreamPositions ? 3 : 1), - result.Length - ); - - Assert.Equal(StreamMessage.Ok.Instance, result[0]); - - if (_fixture.HasStreamPositions) - Assert.Equal(new StreamMessage.FirstStreamPosition(new(32)), result[1]); - - Assert.Equal(32, result.OfType().Count()); - - if (_fixture.HasStreamPositions) - Assert.Equal( - new StreamMessage.LastStreamPosition(new((ulong)_fixture.Count - 1)), - result[^1] - ); - } - - public class Fixture : EventStoreClientFixture { - public int Count => 64; - public bool HasStreamPositions => (EventStoreTestServer.Version?.Major ?? int.MaxValue) >= 21; - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/read_stream_with_timeout.cs b/test/EventStore.Client.Streams.Tests/read_stream_with_timeout.cs index 2f1fbac98..b207304b8 100644 --- a/test/EventStore.Client.Streams.Tests/read_stream_with_timeout.cs +++ b/test/EventStore.Client.Streams.Tests/read_stream_with_timeout.cs @@ -2,20 +2,21 @@ namespace EventStore.Client.Streams.Tests; -[Trait("Category", "Network")] -public class read_stream_with_timeout : IClassFixture { - readonly Fixture _fixture; +[Network] +public class read_stream_with_timeout : IClassFixture { + public read_stream_with_timeout(ITestOutputHelper output, EventStoreFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); - public read_stream_with_timeout(Fixture fixture) => _fixture = fixture; + EventStoreFixture Fixture { get; } [Fact] public async Task fails_when_operation_expired() { - var stream = _fixture.GetStreamName(); + var stream = Fixture.GetStreamName(); - await _fixture.Client.AppendToStreamAsync(stream, StreamRevision.None, _fixture.CreateTestEvents()); + await Fixture.Streams.AppendToStreamAsync(stream, StreamRevision.None, Fixture.CreateTestEvents()); var rpcException = await Assert.ThrowsAsync( - () => _fixture.Client + () => Fixture.Streams .ReadStreamAsync( Direction.Backwards, stream, @@ -30,8 +31,5 @@ public async Task fails_when_operation_expired() { Assert.Equal(StatusCode.DeadlineExceeded, rpcException.StatusCode); } - 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.Streams.Tests/sending_and_receiving_large_messages.cs b/test/EventStore.Client.Streams.Tests/sending_and_receiving_large_messages.cs index 43e760968..6b37e2dc1 100644 --- a/test/EventStore.Client.Streams.Tests/sending_and_receiving_large_messages.cs +++ b/test/EventStore.Client.Streams.Tests/sending_and_receiving_large_messages.cs @@ -1,43 +1,31 @@ using Grpc.Core; -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests; -public class sending_and_receiving_large_messages : IClassFixture { - readonly Fixture _fixture; +public class sending_and_receiving_large_messages : IClassFixture { + public sending_and_receiving_large_messages(ITestOutputHelper output, CustomFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); - public sending_and_receiving_large_messages(Fixture fixture, ITestOutputHelper outputHelper) { - _fixture = fixture; - _fixture.CaptureLogs(outputHelper); - } + CustomFixture Fixture { get; } [Fact] public async Task over_the_hard_limit() { - var streamName = _fixture.GetStreamName(); + 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.Client.AppendToStreamAsync( + () => Fixture.Streams.AppendToStreamAsync( streamName, StreamState.NoStream, - _fixture.LargeEvent + largeEvent ) ); Assert.Equal(StatusCode.ResourceExhausted, ex.StatusCode); } - public class Fixture : EventStoreClientFixture { - const int MaximumSize = 16 * 1024 * 1024 - 10000; // magic number - - public Fixture() : base( - env: new() { - ["EVENTSTORE_MAX_APPEND_SIZE"] = $"{MaximumSize}" - } - ) { } - - public IEnumerable LargeEvent => - CreateTestEvents() - .Select(e => new EventData(e.EventId, "-", new byte[MaximumSize + 1])); - - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; + 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/when_having_max_count_set_for_stream.cs b/test/EventStore.Client.Streams.Tests/when_having_max_count_set_for_stream.cs deleted file mode 100644 index 4a4afc827..000000000 --- a/test/EventStore.Client.Streams.Tests/when_having_max_count_set_for_stream.cs +++ /dev/null @@ -1,129 +0,0 @@ -namespace EventStore.Client.Streams.Tests; - -[Trait("Category", "LongRunning")] -public class when_having_max_count_set_for_stream : IClassFixture { - readonly Fixture _fixture; - - public when_having_max_count_set_for_stream(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task read_stream_forwards_respects_max_count() { - var stream = _fixture.GetStreamName(); - - await _fixture.Client.SetStreamMetadataAsync(stream, StreamState.NoStream, new(3)); - - var expected = _fixture.CreateTestEvents(5).ToArray(); - - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, expected); - - var actual = await _fixture.Client.ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, 100) - .Select(x => x.Event) - .ToArrayAsync(); - - Assert.Equal(3, actual.Length); - Assert.True(EventDataComparer.Equal(expected.Skip(2).ToArray(), actual)); - } - - [Fact] - public async Task read_stream_backwards_respects_max_count() { - var stream = _fixture.GetStreamName(); - - await _fixture.Client.SetStreamMetadataAsync(stream, StreamState.NoStream, new(3)); - - var expected = _fixture.CreateTestEvents(5).ToArray(); - - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, expected); - - var actual = await _fixture.Client.ReadStreamAsync(Direction.Backwards, stream, StreamPosition.End, 100) - .Select(x => x.Event) - .ToArrayAsync(); - - Assert.Equal(3, actual.Length); - Assert.True(EventDataComparer.Equal(expected.Skip(2).Reverse().ToArray(), actual)); - } - - [Fact] - public async Task after_setting_less_strict_max_count_read_stream_forward_reads_more_events() { - var stream = _fixture.GetStreamName(); - - await _fixture.Client.SetStreamMetadataAsync(stream, StreamState.NoStream, new(3)); - - var expected = _fixture.CreateTestEvents(5).ToArray(); - - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, expected); - - await _fixture.Client.SetStreamMetadataAsync(stream, new StreamRevision(0), new(4)); - - var actual = await _fixture.Client.ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, 100) - .Select(x => x.Event) - .ToArrayAsync(); - - Assert.Equal(4, actual.Length); - Assert.True(EventDataComparer.Equal(expected.Skip(1).ToArray(), actual)); - } - - [Fact] - public async Task after_setting_more_strict_max_count_read_stream_forward_reads_less_events() { - var stream = _fixture.GetStreamName(); - - await _fixture.Client.SetStreamMetadataAsync(stream, StreamState.NoStream, new(3)); - - var expected = _fixture.CreateTestEvents(5).ToArray(); - - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, expected); - - await _fixture.Client.SetStreamMetadataAsync(stream, new StreamRevision(0), new(2)); - - var actual = await _fixture.Client.ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, 100) - .Select(x => x.Event) - .ToArrayAsync(); - - Assert.Equal(2, actual.Length); - Assert.True(EventDataComparer.Equal(expected.Skip(3).ToArray(), actual)); - } - - [Fact] - public async Task after_setting_less_strict_max_count_read_stream_backwards_reads_more_events() { - var stream = _fixture.GetStreamName(); - - await _fixture.Client.SetStreamMetadataAsync(stream, StreamState.NoStream, new(3)); - - var expected = _fixture.CreateTestEvents(5).ToArray(); - - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, expected); - - await _fixture.Client.SetStreamMetadataAsync(stream, new StreamRevision(0), new(4)); - - var actual = await _fixture.Client.ReadStreamAsync(Direction.Backwards, stream, StreamPosition.End, 100) - .Select(x => x.Event) - .ToArrayAsync(); - - Assert.Equal(4, actual.Length); - Assert.True(EventDataComparer.Equal(expected.Skip(1).Reverse().ToArray(), actual)); - } - - [Fact] - public async Task after_setting_more_strict_max_count_read_stream_backwards_reads_less_events() { - var stream = _fixture.GetStreamName(); - - await _fixture.Client.SetStreamMetadataAsync(stream, StreamState.NoStream, new(3)); - - var expected = _fixture.CreateTestEvents(5).ToArray(); - - await _fixture.Client.AppendToStreamAsync(stream, StreamState.NoStream, expected); - - await _fixture.Client.SetStreamMetadataAsync(stream, new StreamRevision(0), new(2)); - - var actual = await _fixture.Client.ReadStreamAsync(Direction.Backwards, stream, StreamPosition.End, 100) - .Select(x => x.Event) - .ToArrayAsync(); - - Assert.Equal(2, actual.Length); - Assert.True(EventDataComparer.Equal(expected.Skip(3).Reverse().ToArray(), actual)); - } - - 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.Tests.Common/EventStore.Client.Tests.Common.csproj b/test/EventStore.Client.Tests.Common/EventStore.Client.Tests.Common.csproj index 3608cdb92..ba1a806f8 100644 --- a/test/EventStore.Client.Tests.Common/EventStore.Client.Tests.Common.csproj +++ b/test/EventStore.Client.Tests.Common/EventStore.Client.Tests.Common.csproj @@ -25,6 +25,7 @@ + diff --git a/test/EventStore.Client.Tests.Common/Fixtures/EventStoreFixture.Helpers.cs b/test/EventStore.Client.Tests.Common/Fixtures/EventStoreFixture.Helpers.cs index f698dd55a..56be23915 100644 --- a/test/EventStore.Client.Tests.Common/Fixtures/EventStoreFixture.Helpers.cs +++ b/test/EventStore.Client.Tests.Common/Fixtures/EventStoreFixture.Helpers.cs @@ -45,10 +45,9 @@ await Users.CreateUserAsync( } ).WhenAll(); - public async Task RestartService(TimeSpan delay, Action? restarted = default) { + public async Task RestartService(TimeSpan delay) { await Service.Restart(delay); await Streams.WarmUp(); Log.Information("Service restarted."); - restarted?.Invoke(); } } \ No newline at end of file diff --git a/test/EventStore.Client.Tests.Common/Fixtures/EventStoreFixture.cs b/test/EventStore.Client.Tests.Common/Fixtures/EventStoreFixture.cs index 91767af78..a59125751 100644 --- a/test/EventStore.Client.Tests.Common/Fixtures/EventStoreFixture.cs +++ b/test/EventStore.Client.Tests.Common/Fixtures/EventStoreFixture.cs @@ -1,4 +1,7 @@ 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; @@ -64,6 +67,10 @@ protected EventStoreFixture(ConfigureFixture configure) { public ITestService Service { get; } public EventStoreFixtureOptions 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!; @@ -73,7 +80,7 @@ protected EventStoreFixture(ConfigureFixture configure) { public Func OnSetup { get; init; } = () => Task.CompletedTask; public Func OnTearDown { get; init; } = () => Task.CompletedTask; - + /// /// must test this /// @@ -92,7 +99,8 @@ protected EventStoreFixture(ConfigureFixture configure) { InterlockedBoolean WarmUpCompleted { get; } = new InterlockedBoolean(); SemaphoreSlim WarmUpGatekeeper { get; } = new(1, 1); - + + public void CaptureTestRun(ITestOutputHelper outputHelper) { var testRunId = Logging.CaptureLogs(outputHelper); TestRuns.Add(testRunId); @@ -103,6 +111,9 @@ public void CaptureTestRun(ITestOutputHelper outputHelper) { public async Task InitializeAsync() { await Service.Start(); + EventStoreVersion = GetEventStoreVersion(); + EventStoreHasLastStreamPosition = (EventStoreVersion?.Major ?? int.MaxValue) >= 21; + await WarmUpGatekeeper.WaitAsync(); try { @@ -139,6 +150,27 @@ async Task InitClient(Func action, bool execute = true) where 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(line[(versionPrefix.Length + 1)..].Split(' ')[0], out var version)) + return version; + + throw new InvalidOperationException("Could not determine server version."); + } } public async Task DisposeAsync() { diff --git a/test/EventStore.Client.Tests.Common/XUnit/Categories.cs b/test/EventStore.Client.Tests.Common/XUnit/Categories.cs new file mode 100644 index 000000000..36068cb6b --- /dev/null +++ b/test/EventStore.Client.Tests.Common/XUnit/Categories.cs @@ -0,0 +1,49 @@ +// ReSharper disable CheckNamespace + +using Xunit.Sdk; + +namespace Xunit.Categories; + +class TraitDiscoverer { + internal const string AssemblyName = "Xunit.Categories"; +} + +[PublicAPI] +[TraitDiscoverer(DedicatedDatabaseDiscoverer.DiscovererTypeName, TraitDiscoverer.AssemblyName)] +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)] +public class DedicatedDatabaseAttribute : Attribute, ITraitAttribute { + public class DedicatedDatabaseDiscoverer : ITraitDiscoverer { + internal const string DiscovererTypeName = $"{TraitDiscoverer.AssemblyName}.{nameof(DedicatedDatabaseAttribute)}{nameof(DedicatedDatabaseDiscoverer)}"; + + public IEnumerable> GetTraits(IAttributeInfo traitAttribute) { + yield return new("Category", "DedicatedDatabase"); + } + } +} + +[PublicAPI] +[TraitDiscoverer(LongRunningDiscoverer.DiscovererTypeName, TraitDiscoverer.AssemblyName)] +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)] +public class LongRunningAttribute : Attribute, ITraitAttribute { + public class LongRunningDiscoverer : ITraitDiscoverer { + internal const string DiscovererTypeName = $"{TraitDiscoverer.AssemblyName}.{nameof(LongRunningAttribute)}{nameof(LongRunningDiscoverer)}"; + + public IEnumerable> GetTraits(IAttributeInfo traitAttribute) { + yield return new("Category", "LongRunning"); + } + } +} + +[PublicAPI] +[TraitDiscoverer(NetworkDiscoverer.DiscovererTypeName, TraitDiscoverer.AssemblyName)] +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)] +public class NetworkAttribute : Attribute, ITraitAttribute { + public class NetworkDiscoverer : ITraitDiscoverer { + internal const string DiscovererTypeName = $"{TraitDiscoverer.AssemblyName}.{nameof(NetworkAttribute)}{nameof(NetworkDiscoverer)}"; + + public IEnumerable> GetTraits(IAttributeInfo traitAttribute) { + yield return new("Category", "Network"); + } + } +} + From 3e5776d335c5cd27800c45f835517d1d725153a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Silveira?= Date: Wed, 6 Dec 2023 16:26:39 +0100 Subject: [PATCH 10/22] subscriptions tests full re-write --- .../AppendToStream/append_to_stream.cs | 6 +- ...nd_to_stream_expected_version_no_stream.cs | 2 + .../AppendToStream/append_to_stream_limits.cs | 2 + .../append_to_stream_retry.cs | 6 +- ...to_stream_when_events_enumerator_throws.cs | 2 + .../append_to_stream_with_timeout.cs | 4 +- .../appending_to_implicitly_created_stream.cs | 4 +- .../sending_and_receiving_large_messages.cs | 2 + .../Bugs/Issue_104.cs | 1 + .../Bugs/Issue_2544.cs | 1 + .../delete_stream_with_timeout.cs | 3 +- .../{ => DeleteStream}/deleting_stream.cs | 3 +- .../DeleteStream/soft_deleted_stream.cs | 4 +- ...re.Client.Streams.Tests.csproj.DotSettings | 8 + .../FilterTestCase.cs | 27 - .../read_all_backward_messages.cs | 4 +- .../ReadAll/read_all_events_backward.cs | 4 +- .../{ => ReadAll}/read_all_events_forward.cs | 4 +- ...ts_forward_with_linkto_passed_max_count.cs | 4 +- .../read_all_forward_messages.cs | 4 +- .../{ => ReadAll}/read_all_with_timeout.cs | 5 +- .../ReadAll/read_enumeration_tests.cs | 6 +- .../read_events_linked_to_deleted_stream.cs | 6 +- .../ReadStream/read_stream_backward.cs | 4 +- .../read_stream_backward_messages.cs | 4 +- .../ReadStream/read_stream_forward.cs | 4 +- .../read_stream_forward_messages.cs | 4 +- .../read_stream_with_timeout.cs | 6 +- .../when_having_max_count_set_for_stream.cs | 4 +- .../all_stream_with_no_acl_security.cs | 1 + .../Security/delete_stream_security.cs | 1 + .../Security/multiple_role_security.cs | 1 + .../overriden_system_stream_security.cs | 1 + ...verriden_system_stream_security_for_all.cs | 1 + .../overriden_user_stream_security.cs | 1 + .../Security/read_all_security.cs | 1 + .../Security/read_stream_meta_security.cs | 1 + .../Security/read_stream_security.cs | 1 + .../Security/stream_security_inheritance.cs | 1 + .../Security/subscribe_to_all_security.cs | 1 + .../Security/subscribe_to_stream_security.cs | 1 + .../Security/system_stream_security.cs | 1 + .../Security/write_stream_meta_security.cs | 1 + .../Security/write_stream_security.cs | 1 + .../StreamMetadata/stream_metadata.cs | 3 +- .../stream_metadata_with_timeout.cs | 3 +- .../Subscriptions/FilterTestCase.cs | 39 + .../SubscriptionDroppedResult.cs | 16 + .../Subscriptions/SubscriptionFilter.cs | 24 + .../Subscriptions/SubscriptionsFixture.cs | 16 + .../Subscriptions/reconnection.cs | 4 +- .../subscribe_resolve_link_to.cs | 190 ----- .../Subscriptions/subscribe_to_all.cs | 665 ++++++++++++++---- .../subscribe_to_all_filtered.cs | 195 ----- .../subscribe_to_all_filtered_live.cs | 97 --- ...subscribe_to_all_filtered_with_position.cs | 115 --- .../Subscriptions/subscribe_to_all_live.cs | 167 ----- .../subscribe_to_all_with_position.cs | 245 ------- .../Subscriptions/subscribe_to_stream.cs | 436 +++++++++++- .../Subscriptions/subscribe_to_stream_live.cs | 160 ----- .../subscribe_to_stream_with_revision.cs | 237 ------- .../is_json.cs | 2 +- .../Extensions/TaskExtensions.cs | 16 +- .../Fixtures/EventStoreFixture.Helpers.cs | 2 +- 64 files changed, 1180 insertions(+), 1605 deletions(-) rename test/EventStore.Client.Streams.Tests/{ => AppendToStream}/append_to_stream_expected_version_no_stream.cs (93%) rename test/EventStore.Client.Streams.Tests/{ => AppendToStream}/append_to_stream_retry.cs (90%) rename test/EventStore.Client.Streams.Tests/{ => AppendToStream}/append_to_stream_when_events_enumerator_throws.cs (94%) rename test/EventStore.Client.Streams.Tests/{ => AppendToStream}/append_to_stream_with_timeout.cs (93%) rename test/EventStore.Client.Streams.Tests/{ => AppendToStream}/appending_to_implicitly_created_stream.cs (98%) rename test/EventStore.Client.Streams.Tests/{ => AppendToStream}/sending_and_receiving_large_messages.cs (94%) rename test/EventStore.Client.Streams.Tests/{ => DeleteStream}/deleting_stream.cs (97%) create mode 100644 test/EventStore.Client.Streams.Tests/EventStore.Client.Streams.Tests.csproj.DotSettings delete mode 100644 test/EventStore.Client.Streams.Tests/FilterTestCase.cs rename test/EventStore.Client.Streams.Tests/{ => ReadAll}/read_all_backward_messages.cs (89%) rename test/EventStore.Client.Streams.Tests/{ => ReadAll}/read_all_events_forward.cs (96%) rename test/EventStore.Client.Streams.Tests/{ => ReadAll}/read_all_events_forward_with_linkto_passed_max_count.cs (93%) rename test/EventStore.Client.Streams.Tests/{ => ReadAll}/read_all_forward_messages.cs (89%) rename test/EventStore.Client.Streams.Tests/{ => ReadAll}/read_all_with_timeout.cs (84%) rename test/EventStore.Client.Streams.Tests/{ => ReadStream}/read_stream_with_timeout.cs (90%) create mode 100644 test/EventStore.Client.Streams.Tests/Subscriptions/FilterTestCase.cs create mode 100644 test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionDroppedResult.cs create mode 100644 test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionFilter.cs create mode 100644 test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionsFixture.cs delete mode 100644 test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_resolve_link_to.cs delete mode 100644 test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all_filtered.cs delete mode 100644 test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all_filtered_live.cs delete mode 100644 test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all_filtered_with_position.cs delete mode 100644 test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all_live.cs delete mode 100644 test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all_with_position.cs delete mode 100644 test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream_live.cs delete mode 100644 test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream_with_revision.cs diff --git a/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream.cs b/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream.cs index 2595b67ca..19dc0ff0e 100644 --- a/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream.cs +++ b/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream.cs @@ -1,6 +1,8 @@ -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests; -[Network] +[Trait("Category", "Network")] +[Trait("Category", "Stream")] +[Trait("Category", "Append")] public class append_to_stream : IClassFixture { public append_to_stream(ITestOutputHelper output, EventStoreFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); diff --git a/test/EventStore.Client.Streams.Tests/append_to_stream_expected_version_no_stream.cs b/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_expected_version_no_stream.cs similarity index 93% rename from test/EventStore.Client.Streams.Tests/append_to_stream_expected_version_no_stream.cs rename to test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_expected_version_no_stream.cs index 792bb642a..1c173b445 100644 --- a/test/EventStore.Client.Streams.Tests/append_to_stream_expected_version_no_stream.cs +++ b/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_expected_version_no_stream.cs @@ -1,5 +1,7 @@ namespace EventStore.Client.Streams.Tests; +[Trait("Category", "Stream")] +[Trait("Category", "Append")] public class append_to_stream_expected_version_no_stream : IClassFixture { public append_to_stream_expected_version_no_stream(ITestOutputHelper output, EventStoreFixture fixture) { Fixture = fixture.With(x => x.CaptureTestRun(output)); diff --git a/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_limits.cs b/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_limits.cs index c44f64860..35aa13926 100644 --- a/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_limits.cs +++ b/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_limits.cs @@ -1,5 +1,7 @@ namespace EventStore.Client.Streams.Tests; +[Trait("Category", "Stream")] +[Trait("Category", "Append")] public class append_to_stream_limits : IClassFixture { public append_to_stream_limits(ITestOutputHelper output, StreamLimitsFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); diff --git a/test/EventStore.Client.Streams.Tests/append_to_stream_retry.cs b/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_retry.cs similarity index 90% rename from test/EventStore.Client.Streams.Tests/append_to_stream_retry.cs rename to test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_retry.cs index cf2c3c92e..a8cbd522e 100644 --- a/test/EventStore.Client.Streams.Tests/append_to_stream_retry.cs +++ b/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_retry.cs @@ -2,8 +2,10 @@ namespace EventStore.Client.Streams.Tests; -[Network] -[DedicatedDatabase] +[Trait("Category", "Network")] +[Trait("Category", "DedicatedDatabase")] +[Trait("Category", "Stream")] +[Trait("Category", "Append")] public class append_to_stream_retry : IClassFixture { public append_to_stream_retry(ITestOutputHelper output, EventStoreFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); diff --git a/test/EventStore.Client.Streams.Tests/append_to_stream_when_events_enumerator_throws.cs b/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_when_events_enumerator_throws.cs similarity index 94% rename from test/EventStore.Client.Streams.Tests/append_to_stream_when_events_enumerator_throws.cs rename to test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_when_events_enumerator_throws.cs index 67b8d3991..0ead3a0c0 100644 --- a/test/EventStore.Client.Streams.Tests/append_to_stream_when_events_enumerator_throws.cs +++ b/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_when_events_enumerator_throws.cs @@ -1,5 +1,7 @@ namespace EventStore.Client.Streams.Tests; +[Trait("Category", "Stream")] +[Trait("Category", "Append")] public class append_to_stream_when_events_enumerator_throws : IClassFixture { public append_to_stream_when_events_enumerator_throws(ITestOutputHelper output, EventStoreFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); diff --git a/test/EventStore.Client.Streams.Tests/append_to_stream_with_timeout.cs b/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_with_timeout.cs similarity index 93% rename from test/EventStore.Client.Streams.Tests/append_to_stream_with_timeout.cs rename to test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_with_timeout.cs index 5df05c065..9e305dd04 100644 --- a/test/EventStore.Client.Streams.Tests/append_to_stream_with_timeout.cs +++ b/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_with_timeout.cs @@ -2,7 +2,9 @@ namespace EventStore.Client.Streams.Tests; -[Network] +[Trait("Category", "Network")] +[Trait("Category", "Stream")] +[Trait("Category", "Append")] public class append_to_stream_with_timeout : IClassFixture { public append_to_stream_with_timeout(ITestOutputHelper output, EventStoreFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); diff --git a/test/EventStore.Client.Streams.Tests/appending_to_implicitly_created_stream.cs b/test/EventStore.Client.Streams.Tests/AppendToStream/appending_to_implicitly_created_stream.cs similarity index 98% rename from test/EventStore.Client.Streams.Tests/appending_to_implicitly_created_stream.cs rename to test/EventStore.Client.Streams.Tests/AppendToStream/appending_to_implicitly_created_stream.cs index 4b5846b47..a153e0f1b 100644 --- a/test/EventStore.Client.Streams.Tests/appending_to_implicitly_created_stream.cs +++ b/test/EventStore.Client.Streams.Tests/AppendToStream/appending_to_implicitly_created_stream.cs @@ -1,6 +1,8 @@ namespace EventStore.Client.Streams.Tests; -[LongRunning] +[Trait("Category", "LongRunning")] +[Trait("Category", "Stream")] +[Trait("Category", "Append")] public class appending_to_implicitly_created_stream : IClassFixture { public appending_to_implicitly_created_stream(ITestOutputHelper output, EventStoreFixture fixture) => diff --git a/test/EventStore.Client.Streams.Tests/sending_and_receiving_large_messages.cs b/test/EventStore.Client.Streams.Tests/AppendToStream/sending_and_receiving_large_messages.cs similarity index 94% rename from test/EventStore.Client.Streams.Tests/sending_and_receiving_large_messages.cs rename to test/EventStore.Client.Streams.Tests/AppendToStream/sending_and_receiving_large_messages.cs index 6b37e2dc1..a65b9d317 100644 --- a/test/EventStore.Client.Streams.Tests/sending_and_receiving_large_messages.cs +++ b/test/EventStore.Client.Streams.Tests/AppendToStream/sending_and_receiving_large_messages.cs @@ -2,6 +2,8 @@ namespace EventStore.Client.Streams.Tests; +[Trait("Category", "Stream")] +[Trait("Category", "Append")] public class sending_and_receiving_large_messages : IClassFixture { public sending_and_receiving_large_messages(ITestOutputHelper output, CustomFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); diff --git a/test/EventStore.Client.Streams.Tests/Bugs/Issue_104.cs b/test/EventStore.Client.Streams.Tests/Bugs/Issue_104.cs index 9e64ff0d7..799f5d203 100644 --- a/test/EventStore.Client.Streams.Tests/Bugs/Issue_104.cs +++ b/test/EventStore.Client.Streams.Tests/Bugs/Issue_104.cs @@ -1,5 +1,6 @@ namespace EventStore.Client.Streams.Tests.Bugs; +[Trait("Category", "Bug")] public class Issue_104 : IClassFixture { public Issue_104(ITestOutputHelper output, EventStoreFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); diff --git a/test/EventStore.Client.Streams.Tests/Bugs/Issue_2544.cs b/test/EventStore.Client.Streams.Tests/Bugs/Issue_2544.cs index aabe78bdf..fb2ab3616 100644 --- a/test/EventStore.Client.Streams.Tests/Bugs/Issue_2544.cs +++ b/test/EventStore.Client.Streams.Tests/Bugs/Issue_2544.cs @@ -2,6 +2,7 @@ namespace EventStore.Client.Streams.Tests.Bugs; +[Trait("Category", "Bug")] public class Issue_2544 : IClassFixture { public Issue_2544(ITestOutputHelper output, EventStoreFixture fixture) { Fixture = fixture.With(x => x.CaptureTestRun(output)); diff --git a/test/EventStore.Client.Streams.Tests/DeleteStream/delete_stream_with_timeout.cs b/test/EventStore.Client.Streams.Tests/DeleteStream/delete_stream_with_timeout.cs index 475db2747..aeb4f8f65 100644 --- a/test/EventStore.Client.Streams.Tests/DeleteStream/delete_stream_with_timeout.cs +++ b/test/EventStore.Client.Streams.Tests/DeleteStream/delete_stream_with_timeout.cs @@ -2,7 +2,8 @@ namespace EventStore.Client.Streams.Tests; -[Network] +[Trait("Category", "Network")] +[Trait("Category", "Delete")] public class deleting_stream_with_timeout : IClassFixture { public deleting_stream_with_timeout(ITestOutputHelper output, EventStoreFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); diff --git a/test/EventStore.Client.Streams.Tests/deleting_stream.cs b/test/EventStore.Client.Streams.Tests/DeleteStream/deleting_stream.cs similarity index 97% rename from test/EventStore.Client.Streams.Tests/deleting_stream.cs rename to test/EventStore.Client.Streams.Tests/DeleteStream/deleting_stream.cs index 2f76d1d1b..cfdd42626 100644 --- a/test/EventStore.Client.Streams.Tests/deleting_stream.cs +++ b/test/EventStore.Client.Streams.Tests/DeleteStream/deleting_stream.cs @@ -1,6 +1,7 @@ namespace EventStore.Client.Streams.Tests; -[Network] +[Trait("Category", "Network")] +[Trait("Category", "Delete")] public class deleting_stream : IClassFixture { public deleting_stream(ITestOutputHelper output, EventStoreFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); diff --git a/test/EventStore.Client.Streams.Tests/DeleteStream/soft_deleted_stream.cs b/test/EventStore.Client.Streams.Tests/DeleteStream/soft_deleted_stream.cs index 8b3ec1f35..ee83b84fe 100644 --- a/test/EventStore.Client.Streams.Tests/DeleteStream/soft_deleted_stream.cs +++ b/test/EventStore.Client.Streams.Tests/DeleteStream/soft_deleted_stream.cs @@ -2,8 +2,8 @@ namespace EventStore.Client.Streams.Tests; -[LongRunning] - +[Trait("Category", "LongRunning")] +[Trait("Category", "Delete")] public class deleted_stream : IClassFixture { public deleted_stream(ITestOutputHelper output, EventStoreFixture fixture) { Fixture = fixture.With(x => x.CaptureTestRun(output)); 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 new file mode 100644 index 000000000..7650c6666 --- /dev/null +++ b/test/EventStore.Client.Streams.Tests/EventStore.Client.Streams.Tests.csproj.DotSettings @@ -0,0 +1,8 @@ + + True + True + True + True + True + True + True \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/FilterTestCase.cs b/test/EventStore.Client.Streams.Tests/FilterTestCase.cs deleted file mode 100644 index 948bdf178..000000000 --- a/test/EventStore.Client.Streams.Tests/FilterTestCase.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System.Reflection; - -namespace EventStore.Client.Streams.Tests; - -public static class Filters { - const string StreamNamePrefix = nameof(StreamNamePrefix); - const string StreamNameRegex = nameof(StreamNameRegex); - const string EventTypePrefix = nameof(EventTypePrefix); - const string EventTypeRegex = nameof(EventTypeRegex); - - public static readonly IEnumerable All = typeof(Filters) - .GetFields(BindingFlags.NonPublic | BindingFlags.Static) - .Where(fi => fi.IsLiteral && !fi.IsInitOnly) - .Select(fi => (string)fi.GetRawConstantValue()!); - - static readonly IDictionary, Func)> EventFilters; - - static Filters() => - EventFilters = new Dictionary, Func)> { - [StreamNamePrefix] = (StreamFilter.Prefix, (_, e) => e), - [StreamNameRegex] = (f => StreamFilter.RegularExpression(f), (_, e) => e), - [EventTypePrefix] = (EventTypeFilter.Prefix, (term, e) => new(e.EventId, term, e.Data, e.Metadata, e.ContentType)), - [EventTypeRegex] = (f => EventTypeFilter.RegularExpression(f), (term, e) => new(e.EventId, term, e.Data, e.Metadata, e.ContentType)) - }; - - public static (Func getFilter, Func prepareEvent) GetFilter(string name) => EventFilters[name]; -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/read_all_backward_messages.cs b/test/EventStore.Client.Streams.Tests/ReadAll/read_all_backward_messages.cs similarity index 89% rename from test/EventStore.Client.Streams.Tests/read_all_backward_messages.cs rename to test/EventStore.Client.Streams.Tests/ReadAll/read_all_backward_messages.cs index c4a5d9904..805f82fb5 100644 --- a/test/EventStore.Client.Streams.Tests/read_all_backward_messages.cs +++ b/test/EventStore.Client.Streams.Tests/ReadAll/read_all_backward_messages.cs @@ -1,6 +1,8 @@ namespace EventStore.Client.Streams.Tests; -[Network] +[Trait("Category", "Network")] +[Trait("Category", "AllStream")] +[Trait("Category", "Read")] public class read_all_backward_messages : IClassFixture { public read_all_backward_messages(ITestOutputHelper output, EventStoreFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); diff --git a/test/EventStore.Client.Streams.Tests/ReadAll/read_all_events_backward.cs b/test/EventStore.Client.Streams.Tests/ReadAll/read_all_events_backward.cs index 312c2464d..ef236e706 100644 --- a/test/EventStore.Client.Streams.Tests/ReadAll/read_all_events_backward.cs +++ b/test/EventStore.Client.Streams.Tests/ReadAll/read_all_events_backward.cs @@ -1,6 +1,8 @@ namespace EventStore.Client.Streams.Tests; -[LongRunning] +[Trait("Category", "LongRunning")] +[Trait("Category", "AllStream")] +[Trait("Category", "Read")] public class read_all_events_backward : IClassFixture { public read_all_events_backward(ITestOutputHelper output, ReadAllEventsBackward fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); diff --git a/test/EventStore.Client.Streams.Tests/read_all_events_forward.cs b/test/EventStore.Client.Streams.Tests/ReadAll/read_all_events_forward.cs similarity index 96% rename from test/EventStore.Client.Streams.Tests/read_all_events_forward.cs rename to test/EventStore.Client.Streams.Tests/ReadAll/read_all_events_forward.cs index bc684d3ee..b4c5f054e 100644 --- a/test/EventStore.Client.Streams.Tests/read_all_events_forward.cs +++ b/test/EventStore.Client.Streams.Tests/ReadAll/read_all_events_forward.cs @@ -1,6 +1,8 @@ namespace EventStore.Client.Streams.Tests; -[LongRunning] +[Trait("Category", "LongRunning")] +[Trait("Category", "AllStream")] +[Trait("Category", "Read")] public class read_all_events_forward : IClassFixture { public read_all_events_forward(ITestOutputHelper output, ReadAllEventsForward fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); diff --git a/test/EventStore.Client.Streams.Tests/read_all_events_forward_with_linkto_passed_max_count.cs b/test/EventStore.Client.Streams.Tests/ReadAll/read_all_events_forward_with_linkto_passed_max_count.cs similarity index 93% rename from test/EventStore.Client.Streams.Tests/read_all_events_forward_with_linkto_passed_max_count.cs rename to test/EventStore.Client.Streams.Tests/ReadAll/read_all_events_forward_with_linkto_passed_max_count.cs index f71840c79..f955a33b9 100644 --- a/test/EventStore.Client.Streams.Tests/read_all_events_forward_with_linkto_passed_max_count.cs +++ b/test/EventStore.Client.Streams.Tests/ReadAll/read_all_events_forward_with_linkto_passed_max_count.cs @@ -2,7 +2,9 @@ namespace EventStore.Client.Streams.Tests; -[LongRunning] +[Trait("Category", "LongRunning")] +[Trait("Category", "AllStream")] +[Trait("Category", "Read")] public class read_all_events_forward_with_linkto_passed_max_count : IClassFixture { public read_all_events_forward_with_linkto_passed_max_count(ITestOutputHelper output, EventStoreFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); diff --git a/test/EventStore.Client.Streams.Tests/read_all_forward_messages.cs b/test/EventStore.Client.Streams.Tests/ReadAll/read_all_forward_messages.cs similarity index 89% rename from test/EventStore.Client.Streams.Tests/read_all_forward_messages.cs rename to test/EventStore.Client.Streams.Tests/ReadAll/read_all_forward_messages.cs index df2fddc14..c572cb251 100644 --- a/test/EventStore.Client.Streams.Tests/read_all_forward_messages.cs +++ b/test/EventStore.Client.Streams.Tests/ReadAll/read_all_forward_messages.cs @@ -1,6 +1,8 @@ namespace EventStore.Client.Streams.Tests; -[Network] +[Trait("Category", "Network")] +[Trait("Category", "AllStream")] +[Trait("Category", "Read")] public class read_all_forward_messages : IClassFixture { public read_all_forward_messages(ITestOutputHelper output, EventStoreFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); diff --git a/test/EventStore.Client.Streams.Tests/read_all_with_timeout.cs b/test/EventStore.Client.Streams.Tests/ReadAll/read_all_with_timeout.cs similarity index 84% rename from test/EventStore.Client.Streams.Tests/read_all_with_timeout.cs rename to test/EventStore.Client.Streams.Tests/ReadAll/read_all_with_timeout.cs index b85c65f66..4ec5b16ca 100644 --- a/test/EventStore.Client.Streams.Tests/read_all_with_timeout.cs +++ b/test/EventStore.Client.Streams.Tests/ReadAll/read_all_with_timeout.cs @@ -2,7 +2,10 @@ namespace EventStore.Client.Streams.Tests; -[Network] +[Trait("Category", "Network")] +[Trait("Category", "LongRunning")] +[Trait("Category", "AllStream")] +[Trait("Category", "Read")] public class read_all_with_timeout : IClassFixture { public read_all_with_timeout(ITestOutputHelper output, EventStoreFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); diff --git a/test/EventStore.Client.Streams.Tests/ReadAll/read_enumeration_tests.cs b/test/EventStore.Client.Streams.Tests/ReadAll/read_enumeration_tests.cs index 9ac925afd..a9e11e4d1 100644 --- a/test/EventStore.Client.Streams.Tests/ReadAll/read_enumeration_tests.cs +++ b/test/EventStore.Client.Streams.Tests/ReadAll/read_enumeration_tests.cs @@ -1,6 +1,10 @@ namespace EventStore.Client.Streams.Tests; -[Network] +[Trait("Category", "Network")] +[Trait("Category", "LongRunning")] +[Trait("Category", "AllStream")] +[Trait("Category", "Stream")] +[Trait("Category", "Read")] public class read_enumeration_tests : IClassFixture { public read_enumeration_tests(ITestOutputHelper output, EventStoreFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); diff --git a/test/EventStore.Client.Streams.Tests/ReadStream/read_events_linked_to_deleted_stream.cs b/test/EventStore.Client.Streams.Tests/ReadStream/read_events_linked_to_deleted_stream.cs index 955dd31cc..453bce219 100644 --- a/test/EventStore.Client.Streams.Tests/ReadStream/read_events_linked_to_deleted_stream.cs +++ b/test/EventStore.Client.Streams.Tests/ReadStream/read_events_linked_to_deleted_stream.cs @@ -2,6 +2,8 @@ namespace EventStore.Client.Streams.Tests; +[Trait("Category", "Stream")] +[Trait("Category", "Read")] public abstract class read_events_linked_to_deleted_stream(ReadEventsLinkedToDeletedStreamFixture fixture) { ReadEventsLinkedToDeletedStreamFixture Fixture { get; } = fixture; @@ -17,13 +19,13 @@ public abstract class read_events_linked_to_deleted_stream(ReadEventsLinkedToDel [Fact] public void the_event_is_not_resolved() => Assert.False(Fixture.Events![0].IsResolved); - public class @forwards(ReadEventsLinkedToDeletedStreamFixture fixture) + public class @forwards(forwards.CustomFixture fixture) : read_events_linked_to_deleted_stream(fixture), IClassFixture { public class CustomFixture() : ReadEventsLinkedToDeletedStreamFixture(Direction.Forwards); } - public class @backwards(ReadEventsLinkedToDeletedStreamFixture fixture) + public class @backwards(backwards.CustomFixture fixture) : read_events_linked_to_deleted_stream(fixture), IClassFixture { public class CustomFixture() : ReadEventsLinkedToDeletedStreamFixture(Direction.Backwards); diff --git a/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_backward.cs b/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_backward.cs index 7a3d31eee..675404223 100644 --- a/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_backward.cs +++ b/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_backward.cs @@ -1,6 +1,8 @@ namespace EventStore.Client.Streams.Tests; -[Network] +[Trait("Category", "Network")] +[Trait("Category", "Stream")] +[Trait("Category", "Read")] public class read_stream_backward : IClassFixture { public read_stream_backward(ITestOutputHelper output, EventStoreFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); diff --git a/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_backward_messages.cs b/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_backward_messages.cs index a163874da..6c1c852dc 100644 --- a/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_backward_messages.cs +++ b/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_backward_messages.cs @@ -1,6 +1,8 @@ namespace EventStore.Client.Streams.Tests; -[Network] +[Trait("Category", "Network")] +[Trait("Category", "Stream")] +[Trait("Category", "Read")] public class read_stream_backward_messages : IClassFixture { public read_stream_backward_messages(ITestOutputHelper output, EventStoreFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); diff --git a/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_forward.cs b/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_forward.cs index b91465a23..1dda92385 100644 --- a/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_forward.cs +++ b/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_forward.cs @@ -1,6 +1,8 @@ namespace EventStore.Client.Streams.Tests; -[Network] +[Trait("Category", "Network")] +[Trait("Category", "Stream")] +[Trait("Category", "Read")] public class read_stream_forward : IClassFixture { public read_stream_forward(ITestOutputHelper output, EventStoreFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); diff --git a/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_forward_messages.cs b/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_forward_messages.cs index 3fcac9c87..2ae1e05a3 100644 --- a/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_forward_messages.cs +++ b/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_forward_messages.cs @@ -1,6 +1,8 @@ namespace EventStore.Client.Streams.Tests; -[Network] +[Trait("Category", "Network")] +[Trait("Category", "Stream")] +[Trait("Category", "Read")] public class read_stream_forward_messages : IClassFixture { public read_stream_forward_messages(ITestOutputHelper output, EventStoreFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); diff --git a/test/EventStore.Client.Streams.Tests/read_stream_with_timeout.cs b/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_with_timeout.cs similarity index 90% rename from test/EventStore.Client.Streams.Tests/read_stream_with_timeout.cs rename to test/EventStore.Client.Streams.Tests/ReadStream/read_stream_with_timeout.cs index b207304b8..995dc7503 100644 --- a/test/EventStore.Client.Streams.Tests/read_stream_with_timeout.cs +++ b/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_with_timeout.cs @@ -2,7 +2,9 @@ namespace EventStore.Client.Streams.Tests; -[Network] +[Trait("Category", "Network")] +[Trait("Category", "Stream")] +[Trait("Category", "Read")] public class read_stream_with_timeout : IClassFixture { public read_stream_with_timeout(ITestOutputHelper output, EventStoreFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); @@ -30,6 +32,4 @@ public async Task fails_when_operation_expired() { Assert.Equal(StatusCode.DeadlineExceeded, rpcException.StatusCode); } - - } \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/ReadStream/when_having_max_count_set_for_stream.cs b/test/EventStore.Client.Streams.Tests/ReadStream/when_having_max_count_set_for_stream.cs index 0833f04ea..8ebe4d724 100644 --- a/test/EventStore.Client.Streams.Tests/ReadStream/when_having_max_count_set_for_stream.cs +++ b/test/EventStore.Client.Streams.Tests/ReadStream/when_having_max_count_set_for_stream.cs @@ -1,6 +1,8 @@ namespace EventStore.Client.Streams.Tests; -[LongRunning] +[Trait("Category", "LongRunning")] +[Trait("Category", "Stream")] +[Trait("Category", "Read")] public class when_having_max_count_set_for_stream : IClassFixture { public when_having_max_count_set_for_stream(ITestOutputHelper output, EventStoreFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); diff --git a/test/EventStore.Client.Streams.Tests/Security/all_stream_with_no_acl_security.cs b/test/EventStore.Client.Streams.Tests/Security/all_stream_with_no_acl_security.cs index 2e833a802..1049db01c 100644 --- a/test/EventStore.Client.Streams.Tests/Security/all_stream_with_no_acl_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/all_stream_with_no_acl_security.cs @@ -1,5 +1,6 @@ namespace EventStore.Client.Streams.Tests.Security; +[Trait("Category", "Security")] public class all_stream_with_no_acl_security : IClassFixture { public all_stream_with_no_acl_security(ITestOutputHelper output, CustomFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); diff --git a/test/EventStore.Client.Streams.Tests/Security/delete_stream_security.cs b/test/EventStore.Client.Streams.Tests/Security/delete_stream_security.cs index 0478c7d70..ea2299e85 100644 --- a/test/EventStore.Client.Streams.Tests/Security/delete_stream_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/delete_stream_security.cs @@ -1,5 +1,6 @@ namespace EventStore.Client.Streams.Tests.Security; +[Trait("Category", "Security")] public class delete_stream_security : IClassFixture { public delete_stream_security(ITestOutputHelper output, SecurityFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); diff --git a/test/EventStore.Client.Streams.Tests/Security/multiple_role_security.cs b/test/EventStore.Client.Streams.Tests/Security/multiple_role_security.cs index 22d52fa1b..c331e4db1 100644 --- a/test/EventStore.Client.Streams.Tests/Security/multiple_role_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/multiple_role_security.cs @@ -1,5 +1,6 @@ namespace EventStore.Client.Streams.Tests.Security; +[Trait("Category", "Security")] public class multiple_role_security : IClassFixture { public multiple_role_security(ITestOutputHelper output, CustomFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); diff --git a/test/EventStore.Client.Streams.Tests/Security/overriden_system_stream_security.cs b/test/EventStore.Client.Streams.Tests/Security/overriden_system_stream_security.cs index dbb6cb469..5fbb4deda 100644 --- a/test/EventStore.Client.Streams.Tests/Security/overriden_system_stream_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/overriden_system_stream_security.cs @@ -1,5 +1,6 @@ namespace EventStore.Client.Streams.Tests.Security; +[Trait("Category", "Security")] public class overriden_system_stream_security : IClassFixture { public overriden_system_stream_security(ITestOutputHelper output, CustomFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); diff --git a/test/EventStore.Client.Streams.Tests/Security/overriden_system_stream_security_for_all.cs b/test/EventStore.Client.Streams.Tests/Security/overriden_system_stream_security_for_all.cs index e525c550b..6c3c427f7 100644 --- a/test/EventStore.Client.Streams.Tests/Security/overriden_system_stream_security_for_all.cs +++ b/test/EventStore.Client.Streams.Tests/Security/overriden_system_stream_security_for_all.cs @@ -1,5 +1,6 @@ namespace EventStore.Client.Streams.Tests.Security; +[Trait("Category", "Security")] public class overriden_system_stream_security_for_all : IClassFixture { public overriden_system_stream_security_for_all(ITestOutputHelper output, CustomFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); diff --git a/test/EventStore.Client.Streams.Tests/Security/overriden_user_stream_security.cs b/test/EventStore.Client.Streams.Tests/Security/overriden_user_stream_security.cs index 5951cad5f..1d876089a 100644 --- a/test/EventStore.Client.Streams.Tests/Security/overriden_user_stream_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/overriden_user_stream_security.cs @@ -1,5 +1,6 @@ namespace EventStore.Client.Streams.Tests.Security; +[Trait("Category", "Security")] public class overriden_user_stream_security : IClassFixture { public overriden_user_stream_security(ITestOutputHelper output, CustomFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); diff --git a/test/EventStore.Client.Streams.Tests/Security/read_all_security.cs b/test/EventStore.Client.Streams.Tests/Security/read_all_security.cs index ba05ac78e..9df7fecdd 100644 --- a/test/EventStore.Client.Streams.Tests/Security/read_all_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/read_all_security.cs @@ -1,5 +1,6 @@ namespace EventStore.Client.Streams.Tests.Security; +[Trait("Category", "Security")] public class read_all_security : IClassFixture { public read_all_security(ITestOutputHelper output, SecurityFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); diff --git a/test/EventStore.Client.Streams.Tests/Security/read_stream_meta_security.cs b/test/EventStore.Client.Streams.Tests/Security/read_stream_meta_security.cs index ee7302456..d73c5a880 100644 --- a/test/EventStore.Client.Streams.Tests/Security/read_stream_meta_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/read_stream_meta_security.cs @@ -1,5 +1,6 @@ namespace EventStore.Client.Streams.Tests.Security; +[Trait("Category", "Security")] public class read_stream_meta_security : IClassFixture { public read_stream_meta_security(ITestOutputHelper output, SecurityFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); diff --git a/test/EventStore.Client.Streams.Tests/Security/read_stream_security.cs b/test/EventStore.Client.Streams.Tests/Security/read_stream_security.cs index 59879019f..1ccb05311 100644 --- a/test/EventStore.Client.Streams.Tests/Security/read_stream_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/read_stream_security.cs @@ -1,5 +1,6 @@ namespace EventStore.Client.Streams.Tests.Security; +[Trait("Category", "Security")] public class read_stream_security : IClassFixture { public read_stream_security(ITestOutputHelper output, SecurityFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); diff --git a/test/EventStore.Client.Streams.Tests/Security/stream_security_inheritance.cs b/test/EventStore.Client.Streams.Tests/Security/stream_security_inheritance.cs index 292752f70..1b9806b62 100644 --- a/test/EventStore.Client.Streams.Tests/Security/stream_security_inheritance.cs +++ b/test/EventStore.Client.Streams.Tests/Security/stream_security_inheritance.cs @@ -1,5 +1,6 @@ namespace EventStore.Client.Streams.Tests.Security; +[Trait("Category", "Security")] public class stream_security_inheritance : IClassFixture { public stream_security_inheritance(ITestOutputHelper output, CustomFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); diff --git a/test/EventStore.Client.Streams.Tests/Security/subscribe_to_all_security.cs b/test/EventStore.Client.Streams.Tests/Security/subscribe_to_all_security.cs index d9d3dd981..76729b35b 100644 --- a/test/EventStore.Client.Streams.Tests/Security/subscribe_to_all_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/subscribe_to_all_security.cs @@ -1,5 +1,6 @@ namespace EventStore.Client.Streams.Tests.Security; +[Trait("Category", "Security")] public class subscribe_to_all_security : IClassFixture { public subscribe_to_all_security(ITestOutputHelper output, SecurityFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); diff --git a/test/EventStore.Client.Streams.Tests/Security/subscribe_to_stream_security.cs b/test/EventStore.Client.Streams.Tests/Security/subscribe_to_stream_security.cs index f9ebc0b1a..819027bbd 100644 --- a/test/EventStore.Client.Streams.Tests/Security/subscribe_to_stream_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/subscribe_to_stream_security.cs @@ -1,5 +1,6 @@ namespace EventStore.Client.Streams.Tests.Security; +[Trait("Category", "Security")] public class subscribe_to_stream_security : IClassFixture { public subscribe_to_stream_security(ITestOutputHelper output, SecurityFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); diff --git a/test/EventStore.Client.Streams.Tests/Security/system_stream_security.cs b/test/EventStore.Client.Streams.Tests/Security/system_stream_security.cs index b1d217bf4..3c86d4749 100644 --- a/test/EventStore.Client.Streams.Tests/Security/system_stream_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/system_stream_security.cs @@ -1,5 +1,6 @@ namespace EventStore.Client.Streams.Tests.Security; +[Trait("Category", "Security")] public class system_stream_security : IClassFixture { public system_stream_security(ITestOutputHelper output, SecurityFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); diff --git a/test/EventStore.Client.Streams.Tests/Security/write_stream_meta_security.cs b/test/EventStore.Client.Streams.Tests/Security/write_stream_meta_security.cs index f53678604..4c15dfed0 100644 --- a/test/EventStore.Client.Streams.Tests/Security/write_stream_meta_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/write_stream_meta_security.cs @@ -1,5 +1,6 @@ namespace EventStore.Client.Streams.Tests.Security; +[Trait("Category", "Security")] public class write_stream_meta_security : IClassFixture { public write_stream_meta_security(ITestOutputHelper output, SecurityFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); diff --git a/test/EventStore.Client.Streams.Tests/Security/write_stream_security.cs b/test/EventStore.Client.Streams.Tests/Security/write_stream_security.cs index 36a4085a5..a979f2c2e 100644 --- a/test/EventStore.Client.Streams.Tests/Security/write_stream_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/write_stream_security.cs @@ -1,5 +1,6 @@ namespace EventStore.Client.Streams.Tests.Security; +[Trait("Category", "Security")] public class write_stream_security : IClassFixture { public write_stream_security(ITestOutputHelper output, SecurityFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); diff --git a/test/EventStore.Client.Streams.Tests/StreamMetadata/stream_metadata.cs b/test/EventStore.Client.Streams.Tests/StreamMetadata/stream_metadata.cs index be0179577..7815ac4fe 100644 --- a/test/EventStore.Client.Streams.Tests/StreamMetadata/stream_metadata.cs +++ b/test/EventStore.Client.Streams.Tests/StreamMetadata/stream_metadata.cs @@ -2,7 +2,8 @@ namespace EventStore.Client.Streams.Tests; -[LongRunning] +[Trait("Category", "LongRunning")] +[Trait("Category", "StreamMetadata")] public class stream_metadata : IClassFixture { public stream_metadata(ITestOutputHelper output, EventStoreFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); diff --git a/test/EventStore.Client.Streams.Tests/StreamMetadata/stream_metadata_with_timeout.cs b/test/EventStore.Client.Streams.Tests/StreamMetadata/stream_metadata_with_timeout.cs index 77b1e3c95..faf66d61b 100644 --- a/test/EventStore.Client.Streams.Tests/StreamMetadata/stream_metadata_with_timeout.cs +++ b/test/EventStore.Client.Streams.Tests/StreamMetadata/stream_metadata_with_timeout.cs @@ -2,7 +2,8 @@ namespace EventStore.Client.Streams.Tests; -[Network] +[Trait("Category", "Network")] +[Trait("Category", "StreamMetadata")] public class stream_metadata_with_timeout : IClassFixture { public stream_metadata_with_timeout(ITestOutputHelper output, EventStoreFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/FilterTestCase.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/FilterTestCase.cs new file mode 100644 index 000000000..1e0381587 --- /dev/null +++ b/test/EventStore.Client.Streams.Tests/Subscriptions/FilterTestCase.cs @@ -0,0 +1,39 @@ +using System.Reflection; + +namespace EventStore.Client.Streams.Tests; + +public static class Filters { + const string StreamNamePrefix = nameof(StreamNamePrefix); + const string StreamNameRegex = nameof(StreamNameRegex); + const string EventTypePrefix = nameof(EventTypePrefix); + const string EventTypeRegex = nameof(EventTypeRegex); + + static readonly SubscriptionFilter StreamNamePrefixSubscriptionFilter = new(StreamNamePrefix, StreamFilter.Prefix, (_, evt) => evt); + static readonly SubscriptionFilter StreamNameRegexSubscriptionFilter = new(StreamNameRegex, f => StreamFilter.RegularExpression(f), (_, evt) => evt); + static readonly SubscriptionFilter EventTypePrefixSubscriptionFilter = new(EventTypePrefix, EventTypeFilter.Prefix, (term, evt) => new(evt.EventId, term, evt.Data, evt.Metadata, evt.ContentType)); + static readonly SubscriptionFilter EventTypeRegexSubscriptionFilter = new(EventTypeRegex, f => EventTypeFilter.RegularExpression(f), (term, evt) => new(evt.EventId, term, evt.Data, evt.Metadata, evt.ContentType)); + + static Filters() { + EventFilters = new Dictionary { + [StreamNamePrefix] = new(StreamNamePrefix, StreamFilter.Prefix, (_, evt) => evt), + [StreamNameRegex] = new(StreamNameRegex, f => StreamFilter.RegularExpression(f), (_, evt) => evt), + [EventTypePrefix] = new(EventTypePrefix, EventTypeFilter.Prefix, (term, evt) => new(evt.EventId, term, evt.Data, evt.Metadata, evt.ContentType)), + [EventTypeRegex] = new(EventTypeRegex, f => EventTypeFilter.RegularExpression(f), (term, evt) => new(evt.EventId, term, evt.Data, evt.Metadata, evt.ContentType)) + }; + + TestCases = EventFilters.Select(x => new object[] { x.Value }); + } + + public static IDictionary EventFilters { get; } + public static IEnumerable TestCases { get; } + + public static readonly IEnumerable All = typeof(Filters) + .GetFields(BindingFlags.NonPublic | BindingFlags.Static) + .Where(fi => fi.IsLiteral && !fi.IsInitOnly) + .Select(fi => (string)fi.GetRawConstantValue()!); + + public static (Func GetFilter, Func PrepareEvent) GetFilterDefinition(string name) { + var result = EventFilters[name]; + return (result.Create, result.PrepareEvent); + } +} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionDroppedResult.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionDroppedResult.cs new file mode 100644 index 000000000..6b3887a78 --- /dev/null +++ b/test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionDroppedResult.cs @@ -0,0 +1,16 @@ +namespace EventStore.Client.Streams.Tests; + +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/SubscriptionFilter.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionFilter.cs new file mode 100644 index 000000000..b7d4d76dc --- /dev/null +++ b/test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionFilter.cs @@ -0,0 +1,24 @@ +namespace EventStore.Client.Streams.Tests; + +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)); + static readonly SubscriptionFilter EventTypeRegex = new(nameof(EventTypeRegex), f => EventTypeFilter.RegularExpression(f), (term, evt) => new(evt.EventId, term, evt.Data, evt.Metadata, evt.ContentType)); + + static SubscriptionFilter() { + All = new[] { + StreamNamePrefix, + StreamNameRegex, + 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.Streams.Tests/Subscriptions/SubscriptionsFixture.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionsFixture.cs new file mode 100644 index 000000000..6a5030b5a --- /dev/null +++ b/test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionsFixture.cs @@ -0,0 +1,16 @@ +namespace EventStore.Client.Streams.Tests; + +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 index 9e2bfdcd5..175e85457 100644 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/reconnection.cs +++ b/test/EventStore.Client.Streams.Tests/Subscriptions/reconnection.cs @@ -3,9 +3,9 @@ namespace EventStore.Client.Streams.Tests; +[Trait("Category", "Subscriptions")] public class @reconnection : IClassFixture { - public reconnection(ITestOutputHelper output, ReconnectionFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); + public reconnection(ITestOutputHelper output, ReconnectionFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); ReconnectionFixture Fixture { get; } diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_resolve_link_to.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_resolve_link_to.cs deleted file mode 100644 index 58798a392..000000000 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_resolve_link_to.cs +++ /dev/null @@ -1,190 +0,0 @@ -namespace EventStore.Client.Streams.Tests; - -public class subscribe_resolve_link_to : IClassFixture { - public subscribe_resolve_link_to(ITestOutputHelper output, RunProjectionsTestFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - RunProjectionsTestFixture Fixture { get; } - - [Fact] - public async Task stream_subscription() { - var stream = Fixture.GetStreamName(); - - var events = Fixture.CreateTestEvents(20).ToArray(); - - var appeared = new TaskCompletionSource(); - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - - var beforeEvents = events.Take(10); - var afterEvents = events.Skip(10); - - using var enumerator = events.AsEnumerable().GetEnumerator(); - - enumerator.MoveNext(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, beforeEvents) - .WithTimeout(); - - using var subscription = await Fixture.Streams - .SubscribeToStreamAsync( - $"$et-{EventStoreClientFixtureBase.TestEventType}", - FromStream.Start, - EventAppeared, - true, - SubscriptionDropped, - TestCredentials.Root - ) - .WithTimeout(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, afterEvents) - .WithTimeout(); - - await appeared.Task.WithTimeout(); - - subscription.Dispose(); - - var (reason, ex) = await dropped.Task.WithTimeout(); - - Assert.Equal(SubscriptionDroppedReason.Disposed, reason); - Assert.Null(ex); - - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) { - try { - Assert.Equal(enumerator.Current.EventId, e.Event.EventId); - if (!enumerator.MoveNext()) - appeared.TrySetResult(true); - } - catch (Exception ex) { - appeared.TrySetException(ex); - throw; - } - - return Task.CompletedTask; - } - - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => - dropped.SetResult((reason, ex)); - } - - [Fact] - public async Task all_subscription() { - var stream = Fixture.GetStreamName(); - - var events = Fixture.CreateTestEvents(20).ToArray(); - - var appeared = new TaskCompletionSource(); - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - - var beforeEvents = events.Take(10); - var afterEvents = events.Skip(10); - - using var enumerator = events.AsEnumerable().GetEnumerator(); - - enumerator.MoveNext(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, beforeEvents) - .WithTimeout(); - - using var subscription = await Fixture.Streams.SubscribeToAllAsync( - FromAll.Start, - EventAppeared, - true, - SubscriptionDropped, - userCredentials: TestCredentials.Root - ) - .WithTimeout(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, afterEvents).WithTimeout(); - - await appeared.Task.WithTimeout(); - - subscription.Dispose(); - - var (reason, ex) = await dropped.Task.WithTimeout(); - - Assert.Equal(SubscriptionDroppedReason.Disposed, reason); - Assert.Null(ex); - - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) { - if (e.OriginalEvent.EventStreamId != $"$et-{EventStoreClientFixtureBase.TestEventType}") - return Task.CompletedTask; - - try { - Assert.Equal(enumerator.Current.EventId, e.Event.EventId); - if (!enumerator.MoveNext()) - appeared.TrySetResult(true); - } - catch (Exception ex) { - appeared.TrySetException(ex); - throw; - } - - return Task.CompletedTask; - } - - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => - dropped.SetResult((reason, ex)); - } - - [Fact] - public async Task all_filtered_subscription() { - var stream = Fixture.GetStreamName(); - - var events = Fixture.CreateTestEvents(20).ToArray(); - - var appeared = new TaskCompletionSource(); - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - - var beforeEvents = events.Take(10); - var afterEvents = events.Skip(10); - - using var enumerator = events.AsEnumerable().GetEnumerator(); - - enumerator.MoveNext(); - - var result = await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, beforeEvents) - .WithTimeout(); - - using var subscription = await Fixture.Streams.SubscribeToAllAsync( - FromAll.Start, - EventAppeared, - true, - SubscriptionDropped, - new(StreamFilter.Prefix($"$et-{EventStoreClientFixtureBase.TestEventType}")), - TestCredentials.Root - ) - .WithTimeout(); - - result = await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, afterEvents) - .WithTimeout(); - - await appeared.Task.WithTimeout(); - - subscription.Dispose(); - - var (reason, ex) = await dropped.Task.WithTimeout(); - - Assert.Equal(SubscriptionDroppedReason.Disposed, reason); - Assert.Null(ex); - - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) { - if (e.OriginalEvent.EventStreamId != $"$et-{EventStoreClientFixtureBase.TestEventType}") - return Task.CompletedTask; - - try { - Assert.Equal(enumerator.Current.EventId, e.Event.EventId); - if (!enumerator.MoveNext()) - appeared.TrySetResult(true); - } - catch (Exception ex) { - appeared.TrySetException(ex); - throw; - } - - return Task.CompletedTask; - } - - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => - dropped.SetResult((reason, ex)); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all.cs index 9b7fbc68f..650dcd78d 100644 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all.cs +++ b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all.cs @@ -1,179 +1,596 @@ namespace EventStore.Client.Streams.Tests; -[DedicatedDatabase, LongRunning] -public class subscribe_to_all : IClassFixture { - /// - /// This class because it checks $all, requires a dedicated db node for each test. - /// - public subscribe_to_all(ITestOutputHelper output, CustomFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - CustomFixture Fixture { get; } +[Trait("Category", "Subscriptions")] +[Trait("Category", "AllStream")] +public class subscribe_to_all : IClassFixture { + public subscribe_to_all(ITestOutputHelper output, SubscriptionsFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); + SubscriptionsFixture Fixture { get; } + [Fact] - public async Task calls_subscription_dropped_when_disposed() { - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - - using var subscription = await Fixture.Streams.SubscribeToAllAsync( - FromAll.Start, - EventAppeared, - false, - SubscriptionDropped - ) + 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(); - if (dropped.Task.IsCompleted) - Assert.False(dropped.Task.IsCompleted, dropped.Task.Result.ToString()); + 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; + } - var (reason, ex) = await dropped.Task.WithTimeout(); + 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(); - Assert.Equal(SubscriptionDroppedReason.Disposed, reason); - Assert.Null(ex); + // 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 }); - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) => Task.CompletedTask; + await receivedAllEvents.Task.WithTimeout(); - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => - dropped.SetResult((reason, ex)); - } + // if the subscription dropped before time, raise the reason why + if (subscriptionDropped.Task.IsCompleted) + subscriptionDropped.Task.IsCompleted.ShouldBe(false, subscriptionDropped.Task.Result.ToString()); - [Fact] - public async Task calls_subscription_dropped_when_error_processing_event() { - var stream = Fixture.GetStreamName(); - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - var expectedException = new Exception("Error"); + // 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; + } - using var subscription = await Fixture.Streams.SubscribeToAllAsync( - FromAll.Start, - EventAppeared, - false, - SubscriptionDropped - ) + 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(); - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents()); + foreach (var evt in seedEvents.Skip(pageSize)) + await Fixture.Streams.AppendToStreamAsync($"stream-{evt.EventId.ToGuid():N}", StreamState.NoStream, new[] { evt }); - var (reason, ex) = await dropped.Task.WithTimeout(); + await receivedAllEvents.Task.WithTimeout(); - Assert.Equal(SubscriptionDroppedReason.SubscriberError, reason); - Assert.Same(expectedException, ex); + // if the subscription dropped before time, raise the reason why + if (subscriptionDropped.Task.IsCompleted) + subscriptionDropped.Task.IsCompleted.ShouldBe(false, subscriptionDropped.Task.Result.ToString()); - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) => - Task.FromException(expectedException); + // 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 SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => - dropped.SetResult((reason, ex)); + void OnDropped(StreamSubscription sub, SubscriptionDroppedReason reason, Exception? ex) => + subscriptionDropped.SetResult(new(reason, ex)); } - + [Fact] - public async Task subscribe_to_empty_database() { - var appeared = new TaskCompletionSource(); - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - - using var subscription = await Fixture.Streams.SubscribeToAllAsync( - FromAll.Start, - EventAppeared, - false, - SubscriptionDropped - ) + 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(); - Assert.False(appeared.Task.IsCompleted); - - if (dropped.Task.IsCompleted) - Assert.False(dropped.Task.IsCompleted, dropped.Task.Result.ToString()); + // 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; + } - var (reason, ex) = await dropped.Task.WithTimeout(); + 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(); - Assert.Equal(SubscriptionDroppedReason.Disposed, reason); - Assert.Null(ex); + // 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); + } - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) { - if (!SystemStreams.IsSystemStream(e.OriginalStreamId)) - appeared.TrySetResult(true); + if (availableEvents.Count == 0) { + receivedAllEvents.TrySetResult(true); + Fixture.Log.Information("Received all {TotalEventsCount} expected events.", seedEvents.Length); + } return Task.CompletedTask; } - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => - dropped.SetResult((reason, ex)); - } + void OnDropped(StreamSubscription sub, SubscriptionDroppedReason reason, Exception? ex) { + subscriptionDropped.SetResult(new(reason, ex)); + if (reason != SubscriptionDroppedReason.Disposed) { + receivedAllEvents.TrySetException(ex!); + checkpointReached.TrySetException(ex!); + } + } - [Fact] - public async Task reads_all_existing_events_and_keep_listening_to_new_ones() { - var appeared = new TaskCompletionSource(); - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - var appearedEvents = new List(); - var beforeEvents = Fixture.CreateTestEvents(10).ToArray(); - var afterEvents = Fixture.CreateTestEvents(10).ToArray(); - - foreach (var @event in beforeEvents) - await Fixture.Streams.AppendToStreamAsync( - $"stream-{@event.EventId:n}", - StreamState.NoStream, - new[] { @event } + 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 ); - - using var subscription = await Fixture.Streams.SubscribeToAllAsync( - FromAll.Start, - EventAppeared, - false, - SubscriptionDropped - ) + 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(); - foreach (var @event in afterEvents) - await Fixture.Streams.AppendToStreamAsync( - $"stream-{@event.EventId:n}", - StreamState.NoStream, - new[] { @event } - ); + // 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 + ); - await appeared.Task.WithTimeout(); + 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); + } - Assert.Equal( - beforeEvents.Concat(afterEvents).Select(x => x.EventId), - appearedEvents.Select(x => x.EventId) - ); + if (availableEvents.Count == 0) { + receivedAllEvents.TrySetResult(true); + Fixture.Log.Information("Received all {TotalEventsCount} expected events", pageSize); + } - if (dropped.Task.IsCompleted) - Assert.False(dropped.Task.IsCompleted, dropped.Task.Result.ToString()); + return Task.CompletedTask; + } - subscription.Dispose(); + 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; + } + } - var (reason, ex) = await dropped.Task.WithTimeout(); + [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(); - Assert.Equal(SubscriptionDroppedReason.Disposed, reason); - Assert.Null(ex); + // 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 + ); - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) { - if (!SystemStreams.IsSystemStream(e.OriginalStreamId)) { - appearedEvents.Add(e.Event); + 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 (appearedEvents.Count >= beforeEvents.Length + afterEvents.Length) - appeared.TrySetResult(true); + if (availableEvents.Count == 0) { + receivedAllEvents.TrySetResult(true); + Fixture.Log.Information("Received all {TotalEventsCount} expected events", pageSize); } return Task.CompletedTask; } - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => - dropped.SetResult((reason, ex)); + 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(); - public class CustomFixture : EventStoreFixture { - public CustomFixture() { - OnSetup = async () => { - await Streams.SetStreamMetadataAsync( - SystemStreams.AllStream, - StreamState.NoStream, - new(acl: new(SystemRoles.All)), - userCredentials: TestCredentials.Root - ); - }; + 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); } } \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all_filtered.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all_filtered.cs deleted file mode 100644 index c17adf0d2..000000000 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all_filtered.cs +++ /dev/null @@ -1,195 +0,0 @@ -namespace EventStore.Client.Streams.Tests; - -[DedicatedDatabase] -public class subscribe_to_all_filtered : IClassFixture { - public subscribe_to_all_filtered(ITestOutputHelper output, CustomFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - CustomFixture Fixture { get; } - - public static IEnumerable FilterCases() => Filters.All.Select(filter => new object[] { filter }); - - [Theory] - [MemberData(nameof(FilterCases))] - public async Task reads_all_existing_events(string filterName) { - var streamPrefix = Fixture.GetStreamName(); - var (getFilter, prepareEvent) = Filters.GetFilter(filterName); - - var appeared = new TaskCompletionSource(); - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - var checkpointSeen = new TaskCompletionSource(); - var filter = getFilter(streamPrefix); - - var events = Fixture.CreateTestEvents(20).Select(e => prepareEvent(streamPrefix, e)) - .ToArray(); - - using var enumerator = events.OfType().GetEnumerator(); - enumerator.MoveNext(); - - await Fixture.Streams.AppendToStreamAsync( - Guid.NewGuid().ToString(), - StreamState.NoStream, - Fixture.CreateTestEvents(256) - ); - - foreach (var e in events) - await Fixture.Streams.AppendToStreamAsync( - $"{streamPrefix}_{Guid.NewGuid():n}", - StreamState.NoStream, - new[] { e } - ); - - using var subscription = await Fixture.Streams.SubscribeToAllAsync( - FromAll.Start, - EventAppeared, - false, - SubscriptionDropped, - new(filter, 5, CheckpointReached) - ) - .WithTimeout(); - - await Task.WhenAll(appeared.Task, checkpointSeen.Task).WithTimeout(); - - Assert.False(dropped.Task.IsCompleted); - - subscription.Dispose(); - - var (reason, ex) = await dropped.Task.WithTimeout(); - - Assert.Equal(SubscriptionDroppedReason.Disposed, reason); - Assert.Null(ex); - - Task EventAppeared(StreamSubscription _, ResolvedEvent e, CancellationToken ct) { - try { - Assert.Equal(enumerator.Current.EventId, e.OriginalEvent.EventId); - if (!enumerator.MoveNext()) - appeared.TrySetResult(true); - } - catch (Exception ex) { - appeared.TrySetException(ex); - throw; - } - - return Task.CompletedTask; - } - - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) { - dropped.SetResult((reason, ex)); - if (reason != SubscriptionDroppedReason.Disposed) { - appeared.TrySetException(ex!); - checkpointSeen.TrySetException(ex!); - } - } - - Task CheckpointReached(StreamSubscription _, Position position, CancellationToken ct) { - checkpointSeen.TrySetResult(true); - - return Task.CompletedTask; - } - } - - [Theory] - [MemberData(nameof(FilterCases))] - public async Task reads_all_existing_events_and_keep_listening_to_new_ones(string filterName) { - var streamPrefix = Fixture.GetStreamName(); - var (getFilter, prepareEvent) = Filters.GetFilter(filterName); - - var appeared = new TaskCompletionSource(); - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - var checkpointSeen = new TaskCompletionSource(); - var filter = getFilter(streamPrefix); - var events = Fixture.CreateTestEvents(20).Select(e => prepareEvent(streamPrefix, e)) - .ToArray(); - - var beforeEvents = events.Take(10); - var afterEvents = events.Skip(10); - - using var enumerator = events.OfType().GetEnumerator(); - enumerator.MoveNext(); - - await Fixture.Streams.AppendToStreamAsync( - Guid.NewGuid().ToString(), - StreamState.NoStream, - Fixture.CreateTestEvents(256) - ); - - foreach (var e in beforeEvents) - await Fixture.Streams.AppendToStreamAsync( - $"{streamPrefix}_{Guid.NewGuid():n}", - StreamState.NoStream, - new[] { e } - ); - - using var subscription = await Fixture.Streams.SubscribeToAllAsync( - FromAll.Start, - EventAppeared, - false, - SubscriptionDropped, - new(filter, 5, CheckpointReached) - ) - .WithTimeout(); - - foreach (var e in afterEvents) - await Fixture.Streams.AppendToStreamAsync( - $"{streamPrefix}_{Guid.NewGuid():n}", - StreamState.NoStream, - new[] { e } - ); - - await Task.WhenAll(appeared.Task, checkpointSeen.Task).WithTimeout(); - - Assert.False(dropped.Task.IsCompleted); - - subscription.Dispose(); - - var (reason, ex) = await dropped.Task.WithTimeout(); - - Assert.Equal(SubscriptionDroppedReason.Disposed, reason); - Assert.Null(ex); - - Task EventAppeared(StreamSubscription _, ResolvedEvent e, CancellationToken ct) { - try { - Assert.Equal(enumerator.Current.EventId, e.OriginalEvent.EventId); - if (!enumerator.MoveNext()) - appeared.TrySetResult(true); - } - catch (Exception ex) { - appeared.TrySetException(ex); - throw; - } - - return Task.CompletedTask; - } - - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) { - dropped.SetResult((reason, ex)); - if (reason != SubscriptionDroppedReason.Disposed) { - appeared.TrySetException(ex!); - checkpointSeen.TrySetException(ex!); - } - } - - Task CheckpointReached(StreamSubscription _, Position position, CancellationToken ct) { - checkpointSeen.TrySetResult(true); - - return Task.CompletedTask; - } - } - - public class CustomFixture : EventStoreFixture { - public const string FilteredOutStream = nameof(FilteredOutStream); - - public CustomFixture() { - OnSetup = async () => { - await Streams.SetStreamMetadataAsync( - SystemStreams.AllStream, - StreamState.NoStream, - new(acl: new(SystemRoles.All)), - userCredentials: TestCredentials.Root - ); - - await Streams.AppendToStreamAsync(FilteredOutStream, StreamState.NoStream, CreateTestEvents(10)); - }; - } - } -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all_filtered_live.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all_filtered_live.cs deleted file mode 100644 index af9b6105d..000000000 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all_filtered_live.cs +++ /dev/null @@ -1,97 +0,0 @@ -namespace EventStore.Client.Streams.Tests; - -[DedicatedDatabase] -public class subscribe_to_all_filtered_live : IClassFixture { - public subscribe_to_all_filtered_live(ITestOutputHelper output, EventStoreFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - EventStoreFixture Fixture { get; } - - public static IEnumerable FilterCases() => Filters.All.Select(filter => new object[] { filter }); - - [Theory] - [MemberData(nameof(FilterCases))] - public async Task does_not_read_all_events_but_keep_listening_to_new_ones(string filterName) { - const string filteredOutStream = nameof(filteredOutStream); - - await Fixture.Streams.SetStreamMetadataAsync( - SystemStreams.AllStream, - StreamState.Any, - new(acl: new(SystemRoles.All)), - userCredentials: TestCredentials.Root - ); - - await Fixture.Streams.AppendToStreamAsync( - filteredOutStream, - StreamState.NoStream, - Fixture.CreateTestEvents(10) - ); - - var streamPrefix = Fixture.GetStreamName(); - var (getFilter, prepareEvent) = Filters.GetFilter(filterName); - - var appeared = new TaskCompletionSource(); - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - - var filter = getFilter(streamPrefix); - var events = Fixture.CreateTestEvents(20).Select(e => prepareEvent(streamPrefix, e)) - .ToArray(); - - var beforeEvents = events.Take(10); - var afterEvents = events.Skip(10); - - using var enumerator = afterEvents.OfType().GetEnumerator(); - enumerator.MoveNext(); - - foreach (var e in beforeEvents) - await Fixture.Streams.AppendToStreamAsync( - $"{streamPrefix}_{Guid.NewGuid():n}", - StreamState.NoStream, - new[] { e } - ); - - using var subscription = await Fixture.Streams.SubscribeToAllAsync( - FromAll.End, - EventAppeared, - false, - SubscriptionDropped, - new(filter) - ) - .WithTimeout(); - - foreach (var e in afterEvents) - await Fixture.Streams.AppendToStreamAsync( - $"{streamPrefix}_{Guid.NewGuid():n}", - StreamState.NoStream, - new[] { e } - ); - - await appeared.Task.WithTimeout(); - - Assert.False(dropped.Task.IsCompleted); - - subscription.Dispose(); - - var (reason, ex) = await dropped.Task.WithTimeout(); - - Assert.Equal(SubscriptionDroppedReason.Disposed, reason); - Assert.Null(ex); - - Task EventAppeared(StreamSubscription _, ResolvedEvent e, CancellationToken ct) { - try { - Assert.Equal(enumerator.Current.EventId, e.OriginalEvent.EventId); - if (!enumerator.MoveNext()) - appeared.TrySetResult(true); - } - catch (Exception ex) { - appeared.TrySetException(ex); - throw; - } - - return Task.CompletedTask; - } - - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => - dropped.SetResult((reason, ex)); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all_filtered_with_position.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all_filtered_with_position.cs deleted file mode 100644 index 3c7cbe79f..000000000 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all_filtered_with_position.cs +++ /dev/null @@ -1,115 +0,0 @@ -namespace EventStore.Client.Streams.Tests; - -[DedicatedDatabase] -public class subscribe_to_all_filtered_with_position : IClassFixture { - public subscribe_to_all_filtered_with_position(ITestOutputHelper output, EventStoreFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - EventStoreFixture Fixture { get; } - - public static IEnumerable FilterCases() => Filters.All.Select(filter => new object[] { filter }); - - [Theory] - [MemberData(nameof(FilterCases))] - public async Task reads_all_existing_events_and_keep_listening_to_new_ones(string filterName) { - const string filteredOutStream = nameof(filteredOutStream); - - await Fixture.Streams.SetStreamMetadataAsync( - SystemStreams.AllStream, - StreamState.Any, - new(acl: new(SystemRoles.All)), - userCredentials: TestCredentials.Root - ); - - await Fixture.Streams.AppendToStreamAsync( - filteredOutStream, - StreamState.NoStream, - Fixture.CreateTestEvents(10) - ); - - var streamPrefix = Fixture.GetStreamName(); - var (getFilter, prepareEvent) = Filters.GetFilter(filterName); - - var appeared = new TaskCompletionSource(); - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - var checkpointSeen = new TaskCompletionSource(); - var filter = getFilter(streamPrefix); - var events = Fixture.CreateTestEvents(20).Select(e => prepareEvent(streamPrefix, e)) - .ToArray(); - - var beforeEvents = events.Take(10); - var afterEvents = events.Skip(10); - - using var enumerator = afterEvents.OfType().GetEnumerator(); - enumerator.MoveNext(); - - foreach (var e in beforeEvents) - await Fixture.Streams.AppendToStreamAsync( - $"{streamPrefix}_{Guid.NewGuid():n}", - StreamState.NoStream, - new[] { e } - ); - - var writeResult = await Fixture.Streams.AppendToStreamAsync( - "checkpoint", - StreamState.NoStream, - Fixture.CreateTestEvents() - ); - - await Fixture.Streams.AppendToStreamAsync( - Guid.NewGuid().ToString(), - StreamState.NoStream, - Fixture.CreateTestEvents(256) - ); - - using var subscription = await Fixture.Streams.SubscribeToAllAsync( - FromAll.After(writeResult.LogPosition), - EventAppeared, - false, - SubscriptionDropped, - new(filter, 4, CheckpointReached) - ) - .WithTimeout(); - - foreach (var e in afterEvents) - await Fixture.Streams.AppendToStreamAsync( - $"{streamPrefix}_{Guid.NewGuid():n}", - StreamState.NoStream, - new[] { e } - ); - - await Task.WhenAll(appeared.Task, checkpointSeen.Task).WithTimeout(); - - Assert.False(dropped.Task.IsCompleted); - - subscription.Dispose(); - - var (reason, ex) = await dropped.Task.WithTimeout(); - - Assert.Equal(SubscriptionDroppedReason.Disposed, reason); - Assert.Null(ex); - - Task EventAppeared(StreamSubscription _, ResolvedEvent e, CancellationToken ct) { - try { - Assert.Equal(enumerator.Current.EventId, e.OriginalEvent.EventId); - if (!enumerator.MoveNext()) - appeared.TrySetResult(true); - } - catch (Exception ex) { - appeared.TrySetException(ex); - throw; - } - - return Task.CompletedTask; - } - - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => - dropped.SetResult((reason, ex)); - - Task CheckpointReached(StreamSubscription _, Position position, CancellationToken ct) { - checkpointSeen.TrySetResult(true); - - return Task.CompletedTask; - } - } -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all_live.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all_live.cs deleted file mode 100644 index 185b893b7..000000000 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all_live.cs +++ /dev/null @@ -1,167 +0,0 @@ -namespace EventStore.Client.Streams.Tests; - -[DedicatedDatabase, LongRunning] -public class subscribe_to_all_live : IClassFixture { - /// - /// This class does not implement IClassFixture because it checks $all, and we want a fresh Node for each test. - /// - public subscribe_to_all_live(ITestOutputHelper output, EventStoreFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - EventStoreFixture Fixture { get; } - - [Fact] - public async Task calls_subscription_dropped_when_disposed() { - await Fixture.Streams.SetStreamMetadataAsync( - SystemStreams.AllStream, - StreamState.NoStream, - new(acl: new(SystemRoles.All)), - userCredentials: TestCredentials.Root - ); - - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - - using var subscription = await Fixture.Streams - .SubscribeToAllAsync(FromAll.End, EventAppeared, false, SubscriptionDropped) - .WithTimeout(); - - if (dropped.Task.IsCompleted) - Assert.False(dropped.Task.IsCompleted, dropped.Task.Result.ToString()); - - subscription.Dispose(); - - var (reason, ex) = await dropped.Task.WithTimeout(); - - Assert.Equal(SubscriptionDroppedReason.Disposed, reason); - Assert.Null(ex); - - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) => Task.CompletedTask; - - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => - dropped.SetResult((reason, ex)); - } - - [Fact] - public async Task calls_subscription_dropped_when_error_processing_event() { - await Fixture.Streams.SetStreamMetadataAsync( - SystemStreams.AllStream, - StreamState.NoStream, - new(acl: new(SystemRoles.All)), - userCredentials: TestCredentials.Root - ); - - var stream = Fixture.GetStreamName(); - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - var expectedException = new Exception("Error"); - - using var subscription = await Fixture.Streams - .SubscribeToAllAsync(FromAll.End, EventAppeared, false, SubscriptionDropped) - .WithTimeout(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents()); - - var (reason, ex) = await dropped.Task.WithTimeout(); - - Assert.Equal(SubscriptionDroppedReason.SubscriberError, reason); - Assert.Same(expectedException, ex); - - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) => - Task.FromException(expectedException); - - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => - dropped.SetResult((reason, ex)); - } - - [Fact] - public async Task subscribe_to_empty_database() { - await Fixture.Streams.SetStreamMetadataAsync( - SystemStreams.AllStream, - StreamState.NoStream, - new(acl: new(SystemRoles.All)), - userCredentials: TestCredentials.Root - ); - - var appeared = new TaskCompletionSource(); - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - - using var subscription = await Fixture.Streams - .SubscribeToAllAsync(FromAll.End, EventAppeared, false, SubscriptionDropped) - .WithTimeout(); - - Assert.False(appeared.Task.IsCompleted); - - if (dropped.Task.IsCompleted) - Assert.False(dropped.Task.IsCompleted, dropped.Task.Result.ToString()); - - subscription.Dispose(); - - var (reason, ex) = await dropped.Task.WithTimeout(); - - Assert.Equal(SubscriptionDroppedReason.Disposed, reason); - Assert.Null(ex); - - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) { - if (!SystemStreams.IsSystemStream(e.OriginalStreamId)) - appeared.TrySetResult(true); - - return Task.CompletedTask; - } - - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => - dropped.SetResult((reason, ex)); - } - - [Fact] - public async Task does_not_read_existing_events_but_keep_listening_to_new_ones() { - await Fixture.Streams.SetStreamMetadataAsync( - SystemStreams.AllStream, - StreamState.NoStream, - new(acl: new(SystemRoles.All)), - userCredentials: TestCredentials.Root - ); - - var appeared = new TaskCompletionSource(); - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - var appearedEvents = new List(); - var afterEvents = Fixture.CreateTestEvents(10).ToArray(); - - using var subscription = await Fixture.Streams - .SubscribeToAllAsync(FromAll.End, EventAppeared, false, SubscriptionDropped) - .WithTimeout(); - - foreach (var @event in afterEvents) - await Fixture.Streams.AppendToStreamAsync( - $"stream-{@event.EventId:n}", - StreamState.NoStream, - new[] { @event } - ); - - await appeared.Task.WithTimeout(); - - Assert.Equal(afterEvents.Select(x => x.EventId), appearedEvents.Select(x => x.EventId)); - - if (dropped.Task.IsCompleted) - Assert.False(dropped.Task.IsCompleted, dropped.Task.Result.ToString()); - - subscription.Dispose(); - - var (reason, ex) = await dropped.Task.WithTimeout(); - - Assert.Equal(SubscriptionDroppedReason.Disposed, reason); - Assert.Null(ex); - - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) { - if (!SystemStreams.IsSystemStream(e.OriginalStreamId)) { - appearedEvents.Add(e.Event); - - if (appearedEvents.Count >= afterEvents.Length) - appeared.TrySetResult(true); - } - - return Task.CompletedTask; - } - - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => - dropped.SetResult((reason, ex)); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all_with_position.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all_with_position.cs deleted file mode 100644 index d5fa9594e..000000000 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all_with_position.cs +++ /dev/null @@ -1,245 +0,0 @@ -namespace EventStore.Client.Streams.Tests; - -[DedicatedDatabase, LongRunning] -public class subscribe_to_all_with_position : IClassFixture { - public subscribe_to_all_with_position(ITestOutputHelper output, EventStoreFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - EventStoreFixture Fixture { get; } - - [Fact] - public async Task reads_all_existing_events_after_position_and_keep_listening_to_new_ones() { - await Fixture.Streams.SetStreamMetadataAsync( - SystemStreams.AllStream, - StreamState.NoStream, - new(acl: new(SystemRoles.All)), - userCredentials: TestCredentials.Root - ); - - var events = Fixture.CreateTestEvents(20).ToArray(); - - var appeared = new TaskCompletionSource(); - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - - var beforeEvents = events.Take(10); - var afterEvents = events.Skip(10); - - using var enumerator = events.AsEnumerable().GetEnumerator(); - - enumerator.MoveNext(); - - var position = await Fixture.Streams.ReadAllAsync(Direction.Forwards, Position.Start, 1) - .Select(x => x.OriginalEvent.Position) - .FirstAsync(); - - foreach (var @event in beforeEvents) - await Fixture.Streams.AppendToStreamAsync( - $"stream-{@event.EventId:n}", - StreamState.NoStream, - new[] { @event } - ); - - using var subscription = await Fixture.Streams.SubscribeToAllAsync( - FromAll.After(position), - EventAppeared, - false, - SubscriptionDropped - ) - .WithTimeout(); - - foreach (var @event in afterEvents) - await Fixture.Streams.AppendToStreamAsync( - $"stream-{@event.EventId:n}", - StreamState.NoStream, - new[] { @event } - ); - - await appeared.Task.WithTimeout(); - - Assert.False(dropped.Task.IsCompleted); - - subscription.Dispose(); - - var (reason, ex) = await dropped.Task.WithTimeout(); - - Assert.Equal(SubscriptionDroppedReason.Disposed, reason); - Assert.Null(ex); - - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) { - if (position >= e.OriginalEvent.Position) - appeared.TrySetException(new Exception()); - - if (!SystemStreams.IsSystemStream(e.OriginalStreamId)) - try { - Assert.Equal(enumerator.Current.EventId, e.OriginalEvent.EventId); - if (!enumerator.MoveNext()) - appeared.TrySetResult(true); - } - catch (Exception ex) { - appeared.TrySetException(ex); - throw; - } - - return Task.CompletedTask; - } - - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => - dropped.SetResult((reason, ex)); - } -} - -[DedicatedDatabase, LongRunning] -public class subscribe_to_all_with_position_to_empty_database : IClassFixture { - - public subscribe_to_all_with_position_to_empty_database(ITestOutputHelper output, EventStoreFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - EventStoreFixture Fixture { get; } - - [Fact] - public async Task verified() { - await Fixture.Streams.SetStreamMetadataAsync( - SystemStreams.AllStream, - StreamState.NoStream, - new(acl: new(SystemRoles.All)), - userCredentials: TestCredentials.Root - ); - - var appeared = new TaskCompletionSource(); - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - - var firstEvent = await Fixture.Streams.ReadAllAsync(Direction.Forwards, Position.Start, 1) - .FirstOrDefaultAsync(); - - using var subscription = await Fixture.Streams - .SubscribeToAllAsync( - FromAll.After(firstEvent.OriginalEvent.Position), - EventAppeared, - false, - SubscriptionDropped - ) - .WithTimeout(); - - Assert.False(appeared.Task.IsCompleted); - - if (dropped.Task.IsCompleted) - Assert.False(dropped.Task.IsCompleted, dropped.Task.Result.ToString()); - - subscription.Dispose(); - - var (reason, ex) = await dropped.Task.WithTimeout(); - - Assert.Equal(SubscriptionDroppedReason.Disposed, reason); - Assert.Null(ex); - - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) { - if (e.OriginalEvent.Position == firstEvent.OriginalEvent.Position) { - appeared.TrySetException(new Exception()); - return Task.CompletedTask; - } - - if (!SystemStreams.IsSystemStream(e.OriginalStreamId)) - appeared.TrySetResult(true); - - return Task.CompletedTask; - } - - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => - dropped.SetResult((reason, ex)); - } -} - -[DedicatedDatabase, LongRunning] -public class subscribe_to_all_with_position_calls_subscription_dropped_when_disposed : IClassFixture { - public subscribe_to_all_with_position_calls_subscription_dropped_when_disposed(ITestOutputHelper output, EventStoreFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - EventStoreFixture Fixture { get; } - - [Fact] - public async Task verified() { - await Fixture.Streams.SetStreamMetadataAsync( - SystemStreams.AllStream, - StreamState.NoStream, - new(acl: new(SystemRoles.All)), - userCredentials: TestCredentials.Root - ); - - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - - var firstEvent = await Fixture.Streams.ReadAllAsync(Direction.Forwards, Position.Start, 1) - .FirstOrDefaultAsync(); - - using var subscription = await Fixture.Streams - .SubscribeToAllAsync( - FromAll.After(firstEvent.OriginalEvent.Position), - EventAppeared, - false, - SubscriptionDropped - ) - .WithTimeout(); - - if (dropped.Task.IsCompleted) - Assert.False(dropped.Task.IsCompleted, dropped.Task.Result.ToString()); - - subscription.Dispose(); - - var (reason, ex) = await dropped.Task.WithTimeout(); - - Assert.Equal(SubscriptionDroppedReason.Disposed, reason); - Assert.Null(ex); - - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) => Task.CompletedTask; - - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => - dropped.SetResult((reason, ex)); - } -} - -[DedicatedDatabase, LongRunning] -public class subscribe_to_all_with_position_calls_subscription_dropped_when_error_processing_event : IClassFixture { - public subscribe_to_all_with_position_calls_subscription_dropped_when_error_processing_event(ITestOutputHelper output, EventStoreFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - EventStoreFixture Fixture { get; } - - [Fact] - public async Task verified() { - await Fixture.Streams.SetStreamMetadataAsync( - SystemStreams.AllStream, - StreamState.NoStream, - new(acl: new(SystemRoles.All)), - userCredentials: TestCredentials.Root - ); - - var stream = Fixture.GetStreamName(); - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - - var expectedException = new Exception("Error"); - - var firstEvent = await Fixture.Streams.ReadAllAsync(Direction.Forwards, Position.Start, 1) - .FirstOrDefaultAsync(); - - using var subscription = await Fixture.Streams - .SubscribeToAllAsync( - FromAll.After(firstEvent.OriginalEvent.Position), - EventAppeared, - false, - SubscriptionDropped - ) - .WithTimeout(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents(2)); - - var (reason, ex) = await dropped.Task.WithTimeout(); - - Assert.Equal(SubscriptionDroppedReason.SubscriberError, reason); - Assert.Same(expectedException, ex); - - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) => - Task.FromException(expectedException); - - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => - dropped.SetResult((reason, ex)); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream.cs index a0a8a6226..799b23bbf 100644 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream.cs +++ b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream.cs @@ -1,11 +1,12 @@ namespace EventStore.Client.Streams.Tests; -[LongRunning] -public class subscribe_to_stream : IClassFixture { - public subscribe_to_stream(ITestOutputHelper output, EventStoreFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); +[Trait("Category", "LongRunning")] +[Trait("Category", "Subscriptions")] +[Trait("Category", "Stream")] +public class subscribe_to_stream : IClassFixture { + public subscribe_to_stream(ITestOutputHelper output, SubscriptionsFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); - EventStoreFixture Fixture { get; } + SubscriptionsFixture Fixture { get; } [Fact] public async Task subscribe_to_non_existing_stream() { @@ -257,4 +258,429 @@ public async Task catches_deletions() { void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); } + + [Fact] + public async Task with_revision_subscribe_to_non_existing_stream() { + var stream = Fixture.GetStreamName(); + var appeared = new TaskCompletionSource(); + var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); + + using var subscription = await Fixture.Streams + .SubscribeToStreamAsync( + stream, + FromStream.Start, + EventAppeared, + false, + SubscriptionDropped + ) + .WithTimeout(); + + Assert.False(appeared.Task.IsCompleted); + + if (dropped.Task.IsCompleted) + Assert.False(dropped.Task.IsCompleted, dropped.Task.Result.ToString()); + + subscription.Dispose(); + + var (reason, ex) = await dropped.Task.WithTimeout(); + Assert.Equal(SubscriptionDroppedReason.Disposed, reason); + Assert.Null(ex); + + Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) { + appeared.TrySetResult(true); + return Task.CompletedTask; + } + + void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); + } + + [Fact] + public async Task with_revision_subscribe_to_non_existing_stream_then_get_event() { + var stream = Fixture.GetStreamName(); + var appeared = new TaskCompletionSource(); + var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); + + using var subscription = await Fixture.Streams + .SubscribeToStreamAsync( + stream, + FromStream.After(StreamPosition.Start), + EventAppeared, + false, + SubscriptionDropped + ) + .WithTimeout(); + + await Fixture.Streams.AppendToStreamAsync( + stream, + StreamState.NoStream, + Fixture.CreateTestEvents(2) + ); + + Assert.True(await appeared.Task.WithTimeout()); + + if (dropped.Task.IsCompleted) + Assert.False(dropped.Task.IsCompleted, dropped.Task.Result.ToString()); + + subscription.Dispose(); + + var (reason, ex) = await dropped.Task.WithTimeout(); + Assert.Equal(SubscriptionDroppedReason.Disposed, reason); + Assert.Null(ex); + + Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) { + if (e.OriginalEvent.EventNumber == StreamPosition.Start) + appeared.TrySetException(new Exception()); + else + appeared.TrySetResult(true); + + return Task.CompletedTask; + } + + void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); + } + + [Fact] + public async Task with_revision_allow_multiple_subscriptions_to_same_stream() { + var stream = Fixture.GetStreamName(); + + var appeared = new TaskCompletionSource(); + + var appearedCount = 0; + + using var s1 = await Fixture.Streams + .SubscribeToStreamAsync(stream, FromStream.After(StreamPosition.Start), EventAppeared) + .WithTimeout(); + + using var s2 = await Fixture.Streams + .SubscribeToStreamAsync(stream, FromStream.After(StreamPosition.Start), EventAppeared) + .WithTimeout(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents(2)); + + Assert.True(await appeared.Task.WithTimeout()); + + Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) { + if (e.OriginalEvent.EventNumber == StreamPosition.Start) { + appeared.TrySetException(new Exception()); + return Task.CompletedTask; + } + + if (++appearedCount == 2) + appeared.TrySetResult(true); + + return Task.CompletedTask; + } + } + + [Fact] + public async Task with_revision_calls_subscription_dropped_when_disposed() { + var stream = Fixture.GetStreamName(); + var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); + + using var subscription = await Fixture.Streams + .SubscribeToStreamAsync( + stream, + FromStream.Start, + EventAppeared, + false, + SubscriptionDropped + ) + .WithTimeout(); + + if (dropped.Task.IsCompleted) + Assert.False(dropped.Task.IsCompleted, dropped.Task.Result.ToString()); + + subscription.Dispose(); + + var (reason, ex) = await dropped.Task.WithTimeout(); + + Assert.Equal(SubscriptionDroppedReason.Disposed, reason); + Assert.Null(ex); + + Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) => Task.CompletedTask; + + void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); + } + + [Fact] + public async Task with_revision_calls_subscription_dropped_when_error_processing_event() { + var stream = Fixture.GetStreamName(); + var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); + var expectedException = new Exception("Error"); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents(2)); + + using var subscription = await Fixture.Streams.SubscribeToStreamAsync( + stream, + FromStream.Start, + EventAppeared, + false, + SubscriptionDropped + ) + .WithTimeout(); + + var (reason, ex) = await dropped.Task.WithTimeout(); + + Assert.Equal(SubscriptionDroppedReason.SubscriberError, reason); + Assert.Same(expectedException, ex); + + Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) => Task.FromException(expectedException); + + void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); + } + + [Fact] + public async Task with_revision_reads_all_existing_events_and_keep_listening_to_new_ones() { + var stream = Fixture.GetStreamName(); + + var events = Fixture.CreateTestEvents(20).ToArray(); + + var appeared = new TaskCompletionSource(); + var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); + + var beforeEvents = events.Take(10); + var afterEvents = events.Skip(10); + + using var enumerator = events.AsEnumerable().GetEnumerator(); + + enumerator.MoveNext(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents()); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, beforeEvents); + + using var subscription = await Fixture.Streams + .SubscribeToStreamAsync( + stream, + FromStream.After(StreamPosition.Start), + EventAppeared, + false, + SubscriptionDropped + ) + .WithTimeout(); + + var writeResult = await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, afterEvents); + + await appeared.Task.WithTimeout(); + + subscription.Dispose(); + + var (reason, ex) = await dropped.Task.WithTimeout(); + + Assert.Equal(SubscriptionDroppedReason.Disposed, reason); + Assert.Null(ex); + + Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) { + try { + Assert.Equal(enumerator.Current.EventId, e.OriginalEvent.EventId); + if (!enumerator.MoveNext()) + appeared.TrySetResult(true); + } + catch (Exception ex) { + appeared.TrySetException(ex); + throw; + } + + return Task.CompletedTask; + } + + void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((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 + .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)); + } + + [Fact] + public async Task live_does_not_read_existing_events_but_keep_listening_to_new_ones() { + var stream = Fixture.GetStreamName(); + var appeared = new TaskCompletionSource(); + var dropped = new TaskCompletionSource(); + + await Fixture.Streams.AppendToStreamAsync( + stream, + StreamState.NoStream, + Fixture.CreateTestEvents() + ); + + using var _ = await Fixture.Streams + .SubscribeToStreamAsync( + stream, + FromStream.End, + (_, e, _) => { + appeared.TrySetResult(e.OriginalEventNumber); + return Task.CompletedTask; + }, + false, + (s, reason, ex) => dropped.TrySetResult(true) + ) + .WithTimeout(); + + await Fixture.Streams.AppendToStreamAsync( + stream, + new StreamRevision(0), + Fixture.CreateTestEvents() + ); + + Assert.Equal(new(1), await appeared.Task.WithTimeout()); + } + + [Fact] + public async Task live_subscribe_to_non_existing_stream_and_then_catch_new_event() { + var stream = Fixture.GetStreamName(); + var appeared = new TaskCompletionSource(); + var dropped = new TaskCompletionSource(); + + using var _ = await Fixture.Streams + .SubscribeToStreamAsync( + stream, + FromStream.End, + (_, _, _) => { + appeared.TrySetResult(true); + return Task.CompletedTask; + }, + false, + (s, reason, ex) => dropped.TrySetResult(true) + ) + .WithTimeout(); + + await Fixture.Streams.AppendToStreamAsync( + stream, + StreamState.NoStream, + Fixture.CreateTestEvents() + ); + + Assert.True(await appeared.Task.WithTimeout()); + } + + [Fact] + public async Task live_allow_multiple_subscriptions_to_same_stream() { + var stream = Fixture.GetStreamName(); + + var appeared = new TaskCompletionSource(); + + var appearedCount = 0; + + using var s1 = await Fixture.Streams + .SubscribeToStreamAsync(stream, FromStream.End, EventAppeared) + .WithTimeout(); + + using var s2 = await Fixture.Streams + .SubscribeToStreamAsync(stream, FromStream.End, EventAppeared) + .WithTimeout(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents()); + + Assert.True(await appeared.Task.WithTimeout()); + + Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) { + if (++appearedCount == 2) + appeared.TrySetResult(true); + + return Task.CompletedTask; + } + } + + [Fact] + public async Task live_calls_subscription_dropped_when_disposed() { + var stream = Fixture.GetStreamName(); + + var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); + + using var _ = await Fixture.Streams + .SubscribeToStreamAsync( + stream, + FromStream.End, + EventAppeared, + false, + SubscriptionDropped + ) + .WithTimeout(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents()); + + Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) { + s.Dispose(); + return Task.CompletedTask; + } + + void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); + + var (reason, ex) = await dropped.Task.WithTimeout(); + + Assert.Null(ex); + Assert.Equal(SubscriptionDroppedReason.Disposed, reason); + } + + [Fact] + public async Task live_catches_deletions() { + var stream = Fixture.GetStreamName(); + + var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); + + using var _ = await Fixture.Streams + .SubscribeToStreamAsync( + stream, + FromStream.End, + EventAppeared, + false, + SubscriptionDropped + ) + .WithTimeout(); + + await Fixture.Streams.TombstoneAsync(stream, StreamState.NoStream); + var (reason, ex) = await dropped.Task.WithTimeout(); + + Assert.Equal(SubscriptionDroppedReason.ServerError, reason); + var sdex = Assert.IsType(ex); + Assert.Equal(stream, sdex.Stream); + + Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) => Task.CompletedTask; + + void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); + } } \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream_live.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream_live.cs deleted file mode 100644 index 1c7cca16c..000000000 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream_live.cs +++ /dev/null @@ -1,160 +0,0 @@ -namespace EventStore.Client.Streams.Tests; - -[LongRunning] -public class subscribe_to_stream_live : IClassFixture { - public subscribe_to_stream_live(ITestOutputHelper output, EventStoreFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - EventStoreFixture Fixture { get; } - - [Fact] - public async Task does_not_read_existing_events_but_keep_listening_to_new_ones() { - var stream = Fixture.GetStreamName(); - var appeared = new TaskCompletionSource(); - var dropped = new TaskCompletionSource(); - - await Fixture.Streams.AppendToStreamAsync( - stream, - StreamState.NoStream, - Fixture.CreateTestEvents() - ); - - using var _ = await Fixture.Streams - .SubscribeToStreamAsync( - stream, - FromStream.End, - (_, e, _) => { - appeared.TrySetResult(e.OriginalEventNumber); - return Task.CompletedTask; - }, - false, - (s, reason, ex) => dropped.TrySetResult(true) - ) - .WithTimeout(); - - await Fixture.Streams.AppendToStreamAsync( - stream, - new StreamRevision(0), - Fixture.CreateTestEvents() - ); - - Assert.Equal(new(1), await appeared.Task.WithTimeout()); - } - - [Fact] - public async Task subscribe_to_non_existing_stream_and_then_catch_new_event() { - var stream = Fixture.GetStreamName(); - var appeared = new TaskCompletionSource(); - var dropped = new TaskCompletionSource(); - - using var _ = await Fixture.Streams - .SubscribeToStreamAsync( - stream, - FromStream.End, - (_, _, _) => { - appeared.TrySetResult(true); - return Task.CompletedTask; - }, - false, - (s, reason, ex) => dropped.TrySetResult(true) - ) - .WithTimeout(); - - await Fixture.Streams.AppendToStreamAsync( - stream, - StreamState.NoStream, - Fixture.CreateTestEvents() - ); - - Assert.True(await appeared.Task.WithTimeout()); - } - - [Fact] - public async Task allow_multiple_subscriptions_to_same_stream() { - var stream = Fixture.GetStreamName(); - - var appeared = new TaskCompletionSource(); - - var appearedCount = 0; - - using var s1 = await Fixture.Streams - .SubscribeToStreamAsync(stream, FromStream.End, EventAppeared) - .WithTimeout(); - - using var s2 = await Fixture.Streams - .SubscribeToStreamAsync(stream, FromStream.End, EventAppeared) - .WithTimeout(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents()); - - Assert.True(await appeared.Task.WithTimeout()); - - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) { - if (++appearedCount == 2) - appeared.TrySetResult(true); - - return Task.CompletedTask; - } - } - - [Fact] - public async Task calls_subscription_dropped_when_disposed() { - var stream = Fixture.GetStreamName(); - - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - - using var _ = await Fixture.Streams - .SubscribeToStreamAsync( - stream, - FromStream.End, - EventAppeared, - false, - SubscriptionDropped - ) - .WithTimeout(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents()); - - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) { - s.Dispose(); - return Task.CompletedTask; - } - - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); - - var (reason, ex) = await dropped.Task.WithTimeout(); - - Assert.Null(ex); - Assert.Equal(SubscriptionDroppedReason.Disposed, reason); - } - - [Fact] - public async Task catches_deletions() { - var stream = Fixture.GetStreamName(); - - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - - using var _ = await Fixture.Streams - .SubscribeToStreamAsync( - stream, - FromStream.End, - EventAppeared, - false, - SubscriptionDropped - ) - .WithTimeout(); - - await Fixture.Streams.TombstoneAsync(stream, StreamState.NoStream); - var (reason, ex) = await dropped.Task.WithTimeout(); - - Assert.Equal(SubscriptionDroppedReason.ServerError, reason); - var sdex = Assert.IsType(ex); - Assert.Equal(stream, sdex.Stream); - - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) => Task.CompletedTask; - - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); - } - - -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream_with_revision.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream_with_revision.cs deleted file mode 100644 index 4b5f3b4b2..000000000 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream_with_revision.cs +++ /dev/null @@ -1,237 +0,0 @@ -namespace EventStore.Client.Streams.Tests; - -[DedicatedDatabase, LongRunning] -public class subscribe_to_stream_with_revision : IClassFixture { - public subscribe_to_stream_with_revision(ITestOutputHelper output, EventStoreFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - EventStoreFixture Fixture { get; } - - [Fact] - public async Task subscribe_to_non_existing_stream() { - var stream = Fixture.GetStreamName(); - var appeared = new TaskCompletionSource(); - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - - using var subscription = await Fixture.Streams - .SubscribeToStreamAsync( - stream, - FromStream.Start, - EventAppeared, - false, - SubscriptionDropped - ) - .WithTimeout(); - - Assert.False(appeared.Task.IsCompleted); - - if (dropped.Task.IsCompleted) - Assert.False(dropped.Task.IsCompleted, dropped.Task.Result.ToString()); - - subscription.Dispose(); - - var (reason, ex) = await dropped.Task.WithTimeout(); - Assert.Equal(SubscriptionDroppedReason.Disposed, reason); - Assert.Null(ex); - - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) { - appeared.TrySetResult(true); - return Task.CompletedTask; - } - - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); - } - - [Fact] - public async Task subscribe_to_non_existing_stream_then_get_event() { - var stream = Fixture.GetStreamName(); - var appeared = new TaskCompletionSource(); - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - - using var subscription = await Fixture.Streams - .SubscribeToStreamAsync( - stream, - FromStream.After(StreamPosition.Start), - EventAppeared, - false, - SubscriptionDropped - ) - .WithTimeout(); - - await Fixture.Streams.AppendToStreamAsync( - stream, - StreamState.NoStream, - Fixture.CreateTestEvents(2) - ); - - Assert.True(await appeared.Task.WithTimeout()); - - if (dropped.Task.IsCompleted) - Assert.False(dropped.Task.IsCompleted, dropped.Task.Result.ToString()); - - subscription.Dispose(); - - var (reason, ex) = await dropped.Task.WithTimeout(); - Assert.Equal(SubscriptionDroppedReason.Disposed, reason); - Assert.Null(ex); - - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) { - if (e.OriginalEvent.EventNumber == StreamPosition.Start) - appeared.TrySetException(new Exception()); - else - appeared.TrySetResult(true); - - return Task.CompletedTask; - } - - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); - } - - [Fact] - public async Task allow_multiple_subscriptions_to_same_stream() { - var stream = Fixture.GetStreamName(); - - var appeared = new TaskCompletionSource(); - - var appearedCount = 0; - - using var s1 = await Fixture.Streams - .SubscribeToStreamAsync(stream, FromStream.After(StreamPosition.Start), EventAppeared) - .WithTimeout(); - - using var s2 = await Fixture.Streams - .SubscribeToStreamAsync(stream, FromStream.After(StreamPosition.Start), EventAppeared) - .WithTimeout(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents(2)); - - Assert.True(await appeared.Task.WithTimeout()); - - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) { - if (e.OriginalEvent.EventNumber == StreamPosition.Start) { - appeared.TrySetException(new Exception()); - return Task.CompletedTask; - } - - if (++appearedCount == 2) - appeared.TrySetResult(true); - - return Task.CompletedTask; - } - } - - [Fact] - public async Task calls_subscription_dropped_when_disposed() { - var stream = Fixture.GetStreamName(); - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - - using var subscription = await Fixture.Streams - .SubscribeToStreamAsync( - stream, - FromStream.Start, - EventAppeared, - false, - SubscriptionDropped - ) - .WithTimeout(); - - if (dropped.Task.IsCompleted) - Assert.False(dropped.Task.IsCompleted, dropped.Task.Result.ToString()); - - subscription.Dispose(); - - var (reason, ex) = await dropped.Task.WithTimeout(); - - Assert.Equal(SubscriptionDroppedReason.Disposed, reason); - Assert.Null(ex); - - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) => Task.CompletedTask; - - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); - } - - [Fact] - public async Task calls_subscription_dropped_when_error_processing_event() { - var stream = Fixture.GetStreamName(); - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - var expectedException = new Exception("Error"); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents(2)); - - using var subscription = await Fixture.Streams.SubscribeToStreamAsync( - stream, - FromStream.Start, - EventAppeared, - false, - SubscriptionDropped - ) - .WithTimeout(); - - var (reason, ex) = await dropped.Task.WithTimeout(); - - Assert.Equal(SubscriptionDroppedReason.SubscriberError, reason); - Assert.Same(expectedException, ex); - - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) => Task.FromException(expectedException); - - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); - } - - [Fact] - public async Task reads_all_existing_events_and_keep_listening_to_new_ones() { - var stream = Fixture.GetStreamName(); - - var events = Fixture.CreateTestEvents(20).ToArray(); - - var appeared = new TaskCompletionSource(); - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - - var beforeEvents = events.Take(10); - var afterEvents = events.Skip(10); - - using var enumerator = events.AsEnumerable().GetEnumerator(); - - enumerator.MoveNext(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents()); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, beforeEvents); - - using var subscription = await Fixture.Streams - .SubscribeToStreamAsync( - stream, - FromStream.After(StreamPosition.Start), - EventAppeared, - false, - SubscriptionDropped - ) - .WithTimeout(); - - var writeResult = await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, afterEvents); - - await appeared.Task.WithTimeout(); - - subscription.Dispose(); - - var (reason, ex) = await dropped.Task.WithTimeout(); - - Assert.Equal(SubscriptionDroppedReason.Disposed, reason); - Assert.Null(ex); - - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) { - try { - Assert.Equal(enumerator.Current.EventId, e.OriginalEvent.EventId); - if (!enumerator.MoveNext()) - appeared.TrySetResult(true); - } - catch (Exception ex) { - appeared.TrySetException(ex); - throw; - } - - return Task.CompletedTask; - } - - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/is_json.cs b/test/EventStore.Client.Streams.Tests/is_json.cs index 8b7943811..53eb73762 100644 --- a/test/EventStore.Client.Streams.Tests/is_json.cs +++ b/test/EventStore.Client.Streams.Tests/is_json.cs @@ -3,7 +3,7 @@ namespace EventStore.Client.Streams.Tests; -[Network] +[Trait("Category", "Network")] [LongRunning] public class is_json : IClassFixture { public is_json(ITestOutputHelper output, EventStoreFixture fixture) => diff --git a/test/EventStore.Client.Tests.Common/Extensions/TaskExtensions.cs b/test/EventStore.Client.Tests.Common/Extensions/TaskExtensions.cs index 7558c3547..5404ad684 100644 --- a/test/EventStore.Client.Tests.Common/Extensions/TaskExtensions.cs +++ b/test/EventStore.Client.Tests.Common/Extensions/TaskExtensions.cs @@ -6,13 +6,11 @@ public static class TaskExtensions { public static Task WithTimeout(this Task task, TimeSpan timeout) => task.WithTimeout(Convert.ToInt32(timeout.TotalMilliseconds)); - public static async Task WithTimeout(this Task task, int timeoutMs = 10000) { - if (Debugger.IsAttached) { - timeoutMs = -1; - } + public static async Task WithTimeout(this Task task, int timeoutMs = 10000, string? message = null) { + if (Debugger.IsAttached) timeoutMs = -1; if (await Task.WhenAny(task, Task.Delay(timeoutMs)) != task) - throw new TimeoutException("Timed out waiting for task"); + throw new TimeoutException(message ?? "Timed out waiting for task"); await task; } @@ -20,14 +18,12 @@ public static async Task WithTimeout(this Task task, int timeoutMs = 10000) { public static Task WithTimeout(this Task task, TimeSpan timeout) => task.WithTimeout(Convert.ToInt32(timeout.TotalMilliseconds)); - public static async Task WithTimeout(this Task task, int timeoutMs = 10000) { - if (Debugger.IsAttached) { - timeoutMs = -1; - } + public static async Task WithTimeout(this Task task, int timeoutMs = 10000, string? message = null) { + if (Debugger.IsAttached) timeoutMs = -1; if (await Task.WhenAny(task, Task.Delay(timeoutMs)) == task) return await task; - throw new TimeoutException("Timed out waiting for task"); + throw new TimeoutException(message ?? "Timed out waiting for task"); } } \ No newline at end of file diff --git a/test/EventStore.Client.Tests.Common/Fixtures/EventStoreFixture.Helpers.cs b/test/EventStore.Client.Tests.Common/Fixtures/EventStoreFixture.Helpers.cs index 56be23915..e9f06b512 100644 --- a/test/EventStore.Client.Tests.Common/Fixtures/EventStoreFixture.Helpers.cs +++ b/test/EventStore.Client.Tests.Common/Fixtures/EventStoreFixture.Helpers.cs @@ -4,7 +4,7 @@ namespace EventStore.Client.Tests; public partial class EventStoreFixture { - const string TestEventType = "-"; + public const string TestEventType = "tst"; public T NewClient(Action configure) where T : EventStoreClientBase, new() => (T)Activator.CreateInstance(typeof(T), new object?[] { ClientSettings.With(configure) })!; From 5586432a498ecdac5b3af09d1f4cbe27f5196f3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Silveira?= Date: Thu, 7 Dec 2023 16:01:35 +0100 Subject: [PATCH 11/22] more tests refactored and a lot of files deleted --- src/Directory.Build.props | 8 +- .../EventStoreClient.cs | 34 +- .../Interceptors/TypedExceptionInterceptor.cs | 9 - .../AppendToStream/append_to_stream.cs | 195 +++-- ...nd_to_stream_expected_version_no_stream.cs | 33 - .../AppendToStream/append_to_stream_limits.cs | 9 +- .../AppendToStream/append_to_stream_retry.cs | 31 +- ...to_stream_when_events_enumerator_throws.cs | 39 - .../append_to_stream_with_timeout.cs | 48 -- .../appending_to_implicitly_created_stream.cs | 8 +- .../sending_and_receiving_large_messages.cs | 8 +- .../Bugs/Issue_104.cs | 9 +- .../Bugs/Issue_2544.cs | 13 - .../delete_stream_with_timeout.cs | 58 -- .../DeleteStream/deleting_stream.cs | 52 +- .../DeleteStream/soft_deleted_stream.cs | 31 +- .../EventDataComparer.cs | 17 +- .../EventDataTests.cs | 3 +- .../EventStore.Client.Streams.Tests.csproj | 3 + ...re.Client.Streams.Tests.csproj.DotSettings | 1 + .../ReadAll/EventBinaryData.cs | 33 + .../ReadAll/ReadAllEventsFixture.cs | 41 + .../ReadAll/read_all_backward_messages.cs | 29 - .../ReadAll/read_all_events_backward.cs | 119 ++- .../ReadAll/read_all_events_forward.cs | 170 +++-- ...ts_forward_with_linkto_passed_max_count.cs | 52 -- .../ReadAll/read_all_forward_messages.cs | 29 - .../ReadAll/read_all_with_timeout.cs | 31 - .../ReadAll/read_enumeration_tests.cs | 75 -- .../ReadStream/read_stream_backward.cs | 102 ++- .../read_stream_backward_messages.cs | 50 -- .../ReadStream/read_stream_forward.cs | 94 ++- .../read_stream_forward_messages.cs | 96 --- .../ReadStream/read_stream_with_timeout.cs | 35 - .../when_having_max_count_set_for_stream.cs | 7 +- .../Security/SecurityFixture.cs | 4 +- .../all_stream_with_no_acl_security.cs | 22 +- .../Security/delete_stream_security.cs | 7 +- .../Security/multiple_role_security.cs | 7 +- .../overriden_system_stream_security.cs | 7 +- ...verriden_system_stream_security_for_all.cs | 7 +- .../overriden_user_stream_security.cs | 6 +- .../Security/read_all_security.cs | 7 +- .../Security/read_stream_meta_security.cs | 6 +- .../Security/read_stream_security.cs | 6 +- .../Security/stream_security_inheritance.cs | 6 +- .../Security/subscribe_to_all_security.cs | 6 +- .../Security/subscribe_to_stream_security.cs | 6 +- .../Security/system_stream_security.cs | 6 +- .../Security/write_stream_meta_security.cs | 6 +- .../Security/write_stream_security.cs | 3 +- .../StreamMetadata/stream_metadata.cs | 49 +- .../stream_metadata_with_timeout.cs | 54 -- .../Subscriptions/FilterTestCase.cs | 39 - .../Subscriptions/SubscriptionsFixture.cs | 2 + .../Subscriptions/reconnection.cs | 10 +- .../Subscriptions/subscribe_to_all.cs | 8 +- .../Subscriptions/subscribe_to_stream.cs | 699 ++++-------------- .../TestEventExtensions.cs | 4 +- .../is_json.cs | 9 +- .../Extensions/TaskExtensions.cs | 4 +- .../Fixtures/EventStoreFixture.cs | 19 +- .../Shouldly/ShouldThrowAsyncExtensions.cs | 13 + .../XUnit/Categories.cs | 49 -- 64 files changed, 922 insertions(+), 1721 deletions(-) delete mode 100644 test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_expected_version_no_stream.cs delete mode 100644 test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_when_events_enumerator_throws.cs delete mode 100644 test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_with_timeout.cs delete mode 100644 test/EventStore.Client.Streams.Tests/DeleteStream/delete_stream_with_timeout.cs create mode 100644 test/EventStore.Client.Streams.Tests/ReadAll/EventBinaryData.cs create mode 100644 test/EventStore.Client.Streams.Tests/ReadAll/ReadAllEventsFixture.cs delete mode 100644 test/EventStore.Client.Streams.Tests/ReadAll/read_all_backward_messages.cs delete mode 100644 test/EventStore.Client.Streams.Tests/ReadAll/read_all_events_forward_with_linkto_passed_max_count.cs delete mode 100644 test/EventStore.Client.Streams.Tests/ReadAll/read_all_forward_messages.cs delete mode 100644 test/EventStore.Client.Streams.Tests/ReadAll/read_all_with_timeout.cs delete mode 100644 test/EventStore.Client.Streams.Tests/ReadAll/read_enumeration_tests.cs delete mode 100644 test/EventStore.Client.Streams.Tests/ReadStream/read_stream_backward_messages.cs delete mode 100644 test/EventStore.Client.Streams.Tests/ReadStream/read_stream_forward_messages.cs delete mode 100644 test/EventStore.Client.Streams.Tests/ReadStream/read_stream_with_timeout.cs delete mode 100644 test/EventStore.Client.Streams.Tests/StreamMetadata/stream_metadata_with_timeout.cs delete mode 100644 test/EventStore.Client.Streams.Tests/Subscriptions/FilterTestCase.cs create mode 100644 test/EventStore.Client.Tests.Common/Shouldly/ShouldThrowAsyncExtensions.cs delete mode 100644 test/EventStore.Client.Tests.Common/XUnit/Categories.cs diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 1921131a9..85db7ad50 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -35,10 +35,10 @@ - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - + + + + all runtime; build; native; contentfiles; analyzers diff --git a/src/EventStore.Client.Streams/EventStoreClient.cs b/src/EventStore.Client.Streams/EventStoreClient.cs index cace19051..33041d303 100644 --- a/src/EventStore.Client.Streams/EventStoreClient.cs +++ b/src/EventStore.Client.Streams/EventStoreClient.cs @@ -30,35 +30,19 @@ public sealed partial class EventStoreClient : EventStoreClientBase { private static readonly Dictionary> ExceptionMap = new() { - [Constants.Exceptions.InvalidTransaction] = - ex => new InvalidTransactionException(ex.Message, ex), - [Constants.Exceptions.StreamDeleted] = ex => new StreamDeletedException( - ex.Trailers.FirstOrDefault(x => x.Key == Constants.Exceptions.StreamName)?.Value ?? - "", - ex), - [Constants.Exceptions.WrongExpectedVersion] = ex => new WrongExpectedVersionException( - ex.Trailers.FirstOrDefault(x => x.Key == Constants.Exceptions.StreamName)?.Value!, - ex.Trailers.GetStreamRevision(Constants.Exceptions.ExpectedVersion), - ex.Trailers.GetStreamRevision(Constants.Exceptions.ActualVersion), - ex, ex.Message), - [Constants.Exceptions.MaximumAppendSizeExceeded] = ex => - new MaximumAppendSizeExceededException( - ex.Trailers.GetIntValueOrDefault(Constants.Exceptions.MaximumAppendSize), ex), - [Constants.Exceptions.StreamNotFound] = ex => new StreamNotFoundException( - ex.Trailers.FirstOrDefault(x => x.Key == Constants.Exceptions.StreamName)?.Value!, ex), - [Constants.Exceptions.MissingRequiredMetadataProperty] = ex => new - RequiredMetadataPropertyMissingException( - ex.Trailers.FirstOrDefault(x => - x.Key == Constants.Exceptions.MissingRequiredMetadataProperty) - ?.Value!, ex), + [Constants.Exceptions.InvalidTransaction] = ex => new InvalidTransactionException(ex.Message, ex), + [Constants.Exceptions.StreamDeleted] = ex => new StreamDeletedException(ex.Trailers.FirstOrDefault(x => x.Key == Constants.Exceptions.StreamName)?.Value ?? "", ex), + [Constants.Exceptions.WrongExpectedVersion] = ex => new WrongExpectedVersionException(ex.Trailers.FirstOrDefault(x => x.Key == Constants.Exceptions.StreamName)?.Value!, ex.Trailers.GetStreamRevision(Constants.Exceptions.ExpectedVersion), ex.Trailers.GetStreamRevision(Constants.Exceptions.ActualVersion), ex, ex.Message), + [Constants.Exceptions.MaximumAppendSizeExceeded] = ex => new MaximumAppendSizeExceededException(ex.Trailers.GetIntValueOrDefault(Constants.Exceptions.MaximumAppendSize), ex), + [Constants.Exceptions.StreamNotFound] = ex => new StreamNotFoundException(ex.Trailers.FirstOrDefault(x => x.Key == Constants.Exceptions.StreamName)?.Value!, ex), + [Constants.Exceptions.MissingRequiredMetadataProperty] = ex => new RequiredMetadataPropertyMissingException(ex.Trailers.FirstOrDefault(x => x.Key == Constants.Exceptions.MissingRequiredMetadataProperty)?.Value!, ex), }; /// /// Constructs a new . This is not intended to be called directly from your code. /// /// - public EventStoreClient(IOptions options) : this(options.Value) { - } + public EventStoreClient(IOptions options) : this(options.Value) { } /// /// Constructs a new . @@ -71,9 +55,7 @@ public EventStoreClient(EventStoreClientSettings? settings = null) : base(settin } private void SwapStreamAppender(Exception ex) => - Interlocked.Exchange(ref _streamAppenderLazy, - new Lazy(CreateStreamAppender)) - .Value.Dispose(); + Interlocked.Exchange(ref _streamAppenderLazy, new Lazy(CreateStreamAppender)).Value.Dispose(); // todo: might be nice to have two different kinds of appenders and we decide which to instantiate according to the server caps. private StreamAppender CreateStreamAppender() { diff --git a/src/EventStore.Client/Interceptors/TypedExceptionInterceptor.cs b/src/EventStore.Client/Interceptors/TypedExceptionInterceptor.cs index 7a6965284..bc640f795 100644 --- a/src/EventStore.Client/Interceptors/TypedExceptionInterceptor.cs +++ b/src/EventStore.Client/Interceptors/TypedExceptionInterceptor.cs @@ -6,14 +6,6 @@ namespace EventStore.Client.Interceptors; -static class EnumerableExtensions { - public static Dictionary ToDictionary(this IEnumerable> source) where TKey : notnull => - ToDictionary(source, null); - - public static Dictionary ToDictionary(this IEnumerable> source, IEqualityComparer? comparer) where TKey : notnull => - new(source, comparer); -} - class TypedExceptionInterceptor : Interceptor { static readonly Dictionary> DefaultExceptionMap = new() { [Exceptions.AccessDenied] = ex => ex.ToAccessDeniedException(), @@ -21,7 +13,6 @@ class TypedExceptionInterceptor : Interceptor { }; public TypedExceptionInterceptor(Dictionary> customExceptionMap) { - //var map = DefaultExceptionMap.Concat(customExceptionMap).ToDictionary(); // net 8... var map = new Dictionary>(DefaultExceptionMap.Concat(customExceptionMap)); ConvertRpcException = rpcEx => { diff --git a/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream.cs b/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream.cs index 19dc0ff0e..e0eeef8b9 100644 --- a/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream.cs +++ b/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream.cs @@ -1,13 +1,26 @@ +using Grpc.Core; + namespace EventStore.Client.Streams.Tests; +public static class ShouldThrowAsyncExtensions { + + public static Task ShouldThrowAsync(this EventStoreClient.ReadStreamResult source) where TException : Exception => + source + .ToArrayAsync() + .AsTask() + .ShouldThrowAsync(); + + public static async Task ShouldThrowAsync(this EventStoreClient.ReadStreamResult source, Action handler) where TException : Exception { + var ex = await source.ShouldThrowAsync(); + handler(ex); + } +} + + [Trait("Category", "Network")] [Trait("Category", "Stream")] [Trait("Category", "Append")] -public class append_to_stream : IClassFixture { - public append_to_stream(ITestOutputHelper output, EventStoreFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - EventStoreFixture Fixture { get; } +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 }; @@ -21,17 +34,12 @@ public async Task appending_zero_events(StreamState expectedStreamState) { const int iterations = 2; for (var i = 0; i < iterations; i++) { var writeResult = await Fixture.Streams.AppendToStreamAsync(stream, expectedStreamState, Enumerable.Empty()); - Assert.Equal(StreamRevision.None, writeResult.NextExpectedStreamRevision); + writeResult.NextExpectedStreamRevision.ShouldBe(StreamRevision.None); } - var ex = await Assert.ThrowsAsync( - () => - Fixture.Streams - .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, iterations) - .ToArrayAsync().AsTask() - ); - - Assert.Equal(stream, ex.Stream); + await Fixture.Streams + .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, iterations) + .ShouldThrowAsync(ex => ex.Stream.ShouldBe(stream)); } [Theory] @@ -45,14 +53,9 @@ public async Task appending_zero_events_again(StreamState expectedStreamState) { Assert.Equal(StreamRevision.None, writeResult.NextExpectedStreamRevision); } - var ex = await Assert.ThrowsAsync( - () => - Fixture.Streams - .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, iterations) - .ToArrayAsync().AsTask() - ); - - Assert.Equal(stream, ex.Stream); + await Fixture.Streams + .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, iterations) + .ShouldThrowAsync(ex => ex.Stream.ShouldBe(stream)); } [Theory] @@ -137,13 +140,9 @@ public async Task writing_with_correct_expected_version_to_deleted_stream_throws await Fixture.Streams.TombstoneAsync(stream, StreamState.NoStream); - await Assert.ThrowsAsync( - () => Fixture.Streams.AppendToStreamAsync( - stream, - StreamState.NoStream, - Fixture.CreateTestEvents(1) - ) - ); + await Fixture.Streams + .AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents(1)) + .ShouldThrowAsync(); } [Fact] @@ -165,7 +164,9 @@ public async Task writing_with_any_expected_version_to_deleted_stream_throws_str var stream = Fixture.GetStreamName(); await Fixture.Streams.TombstoneAsync(stream, StreamState.NoStream); - await Assert.ThrowsAsync(() => Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, Fixture.CreateTestEvents(1))); + await Fixture.Streams + .AppendToStreamAsync(stream, StreamState.Any, Fixture.CreateTestEvents(1)) + .ShouldThrowAsync(); } [Fact] @@ -174,7 +175,9 @@ public async Task writing_with_invalid_expected_version_to_deleted_stream_throws await Fixture.Streams.TombstoneAsync(stream, StreamState.NoStream); - await Assert.ThrowsAsync(() => Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(5), Fixture.CreateTestEvents())); + await Fixture.Streams + .AppendToStreamAsync(stream, new StreamRevision(5), Fixture.CreateTestEvents()) + .ShouldThrowAsync(); } [Fact] @@ -223,12 +226,12 @@ public async Task appending_with_wrong_expected_version_to_existing_stream_throw await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents()); - var ex = await Assert.ThrowsAsync( - () => Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(999), Fixture.CreateTestEvents()) - ); + var ex = await Fixture.Streams + .AppendToStreamAsync(stream, new StreamRevision(999), Fixture.CreateTestEvents()) + .ShouldThrowAsync(); - Assert.Equal(new(0), ex.ActualStreamRevision); - Assert.Equal(new(999), ex.ExpectedStreamRevision); + ex.ActualStreamRevision.ShouldBe(new(0)); + ex.ExpectedStreamRevision.ShouldBe(new(999)); } [Fact] @@ -295,15 +298,11 @@ await Fixture.Streams.AppendToStreamAsync( public async Task appending_with_stream_exists_expected_version_and_stream_does_not_exist_throws_wrong_expected_version() { var stream = Fixture.GetStreamName(); - var ex = await Assert.ThrowsAsync( - () => Fixture.Streams.AppendToStreamAsync( - stream, - StreamState.StreamExists, - Fixture.CreateTestEvents() - ) - ); - - Assert.Equal(StreamRevision.None, ex.ActualStreamRevision); + var ex = await Fixture.Streams + .AppendToStreamAsync(stream, StreamState.StreamExists, Fixture.CreateTestEvents()) + .ShouldThrowAsync(); + + ex.ActualStreamRevision.ShouldBe(StreamRevision.None); } [Fact] @@ -328,13 +327,9 @@ public async Task appending_with_stream_exists_expected_version_to_hard_deleted_ await Fixture.Streams.TombstoneAsync(stream, StreamState.NoStream); - await Assert.ThrowsAsync( - () => Fixture.Streams.AppendToStreamAsync( - stream, - StreamState.StreamExists, - Fixture.CreateTestEvents() - ) - ); + await Fixture.Streams + .AppendToStreamAsync(stream, StreamState.StreamExists, Fixture.CreateTestEvents()) + .ShouldThrowAsync(); } [Fact] @@ -345,13 +340,9 @@ public async Task appending_with_stream_exists_expected_version_to_deleted_strea await Fixture.Streams.DeleteAsync(stream, StreamState.Any); - await Assert.ThrowsAsync( - () => Fixture.Streams.AppendToStreamAsync( - stream, - StreamState.StreamExists, - Fixture.CreateTestEvents() - ) - ); + await Fixture.Streams + .AppendToStreamAsync(stream, StreamState.StreamExists, Fixture.CreateTestEvents()) + .ShouldThrowAsync(); } [Fact] @@ -411,4 +402,90 @@ public async Task returns_failure_status_when_conditionally_appending_to_a_delet Assert.Equal(ConditionalWriteResult.StreamDeleted, result); } + + [Fact] + public async Task expected_version_no_stream() { + var result = await Fixture.Streams.AppendToStreamAsync( + Fixture.GetStreamName(), + StreamState.NoStream, + Fixture.CreateTestEvents() + ); + + Assert.Equal(new(0), result!.NextExpectedStreamRevision); + } + + [Fact] + public async Task expected_version_no_stream_returns_position() { + var result = await Fixture.Streams.AppendToStreamAsync( + Fixture.GetStreamName(), + StreamState.NoStream, + Fixture.CreateTestEvents() + ); + + Assert.True(result.LogPosition > Position.Start); + } + + [Fact] + public async Task with_timeout_any_stream_revision_fails_when_operation_expired() { + var stream = Fixture.GetStreamName(); + + var ex = await Fixture.Streams.AppendToStreamAsync( + stream, + StreamState.Any, + Fixture.CreateTestEvents(100), + deadline: TimeSpan.FromTicks(1) + ).ShouldThrowAsync(); + + ex.StatusCode.ShouldBe(StatusCode.DeadlineExceeded); + } + + [Fact] + public async Task with_timeout_stream_revision_fails_when_operation_expired() { + var stream = Fixture.GetStreamName(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, Fixture.CreateTestEvents()); + + var ex = await Fixture.Streams.AppendToStreamAsync( + stream, + new StreamRevision(0), + Fixture.CreateTestEvents(10), + deadline: TimeSpan.Zero + ).ShouldThrowAsync(); + + ex.StatusCode.ShouldBe(StatusCode.DeadlineExceeded); + } + + [Fact] + public async Task when_events_enumerator_throws_the_write_does_not_succeed() { + var streamName = Fixture.GetStreamName(); + + await Fixture.Streams + .AppendToStreamAsync(streamName, StreamRevision.None, GetEvents()) + .ShouldThrowAsync(); + + var result = Fixture.Streams.ReadStreamAsync(Direction.Forwards, streamName, StreamPosition.Start); + + var state = await result.ReadState; + + state.ShouldBe(ReadState.StreamNotFound); + + return; + + IEnumerable GetEvents() { + var i = 0; + foreach (var evt in Fixture.CreateTestEvents(5)) { + if (i++ % 3 == 0) + throw new EnumerationFailedException(); + + yield return evt; + } + } + } + + class EnumerationFailedException : Exception { } + + public static IEnumerable ArgumentOutOfRangeTestCases() { + yield return new object?[] { StreamState.Any }; + yield return new object?[] { ulong.MaxValue - 1UL }; + } } \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_expected_version_no_stream.cs b/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_expected_version_no_stream.cs deleted file mode 100644 index 1c173b445..000000000 --- a/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_expected_version_no_stream.cs +++ /dev/null @@ -1,33 +0,0 @@ -namespace EventStore.Client.Streams.Tests; - -[Trait("Category", "Stream")] -[Trait("Category", "Append")] -public class append_to_stream_expected_version_no_stream : IClassFixture { - public append_to_stream_expected_version_no_stream(ITestOutputHelper output, EventStoreFixture fixture) { - Fixture = fixture.With(x => x.CaptureTestRun(output)); - } - - EventStoreFixture Fixture { get; } - - [Fact] - public async Task succeeds() { - var result = await Fixture.Streams.AppendToStreamAsync( - Fixture.GetStreamName(), - StreamState.NoStream, - Fixture.CreateTestEvents() - ); - - Assert.Equal(new(0), result!.NextExpectedStreamRevision); - } - - [Fact] - public async Task returns_position() { - var result = await Fixture.Streams.AppendToStreamAsync( - Fixture.GetStreamName(), - StreamState.NoStream, - Fixture.CreateTestEvents() - ); - - Assert.True(result.LogPosition > Position.Start); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_limits.cs b/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_limits.cs index 35aa13926..b3d0099e3 100644 --- a/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_limits.cs +++ b/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_limits.cs @@ -2,12 +2,7 @@ namespace EventStore.Client.Streams.Tests; [Trait("Category", "Stream")] [Trait("Category", "Append")] -public class append_to_stream_limits : IClassFixture { - public append_to_stream_limits(ITestOutputHelper output, StreamLimitsFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - StreamLimitsFixture Fixture { get; } - +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(); @@ -56,4 +51,4 @@ public class StreamLimitsFixture() : EventStoreFixture(x => x.WithMaxAppendSize( return (events, (uint)size); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_retry.cs b/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_retry.cs index a8cbd522e..a12367774 100644 --- a/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_retry.cs +++ b/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_retry.cs @@ -1,4 +1,5 @@ using Polly; +using Polly.Contrib.WaitAndRetry; namespace EventStore.Client.Streams.Tests; @@ -6,22 +7,13 @@ namespace EventStore.Client.Streams.Tests; [Trait("Category", "DedicatedDatabase")] [Trait("Category", "Stream")] [Trait("Category", "Append")] -public class append_to_stream_retry : IClassFixture { - public append_to_stream_retry(ITestOutputHelper output, EventStoreFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - EventStoreFixture Fixture { get; } - +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, - StreamRevision.None, - Fixture.CreateTestEvents() - ); + var result = await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents()); result.NextExpectedStreamRevision.ShouldBe(new(0)); @@ -30,15 +22,14 @@ public async Task can_retry() { // write can be retried var writeResult = await Policy .Handle() - .WaitAndRetryAsync(2, _ => TimeSpan.FromSeconds(1)) - .ExecuteAsync( - async () => await Fixture.Streams.AppendToStreamAsync( - stream, - result.NextExpectedStreamRevision, - Fixture.CreateTestEvents() - ) - ); - + .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)); } } diff --git a/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_when_events_enumerator_throws.cs b/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_when_events_enumerator_throws.cs deleted file mode 100644 index 0ead3a0c0..000000000 --- a/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_when_events_enumerator_throws.cs +++ /dev/null @@ -1,39 +0,0 @@ -namespace EventStore.Client.Streams.Tests; - -[Trait("Category", "Stream")] -[Trait("Category", "Append")] -public class append_to_stream_when_events_enumerator_throws : IClassFixture { - public append_to_stream_when_events_enumerator_throws(ITestOutputHelper output, EventStoreFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - EventStoreFixture Fixture { get; } - - [Fact] - public async Task the_write_does_not_succeed() { - var streamName = Fixture.GetStreamName(); - - await Fixture.Streams - .AppendToStreamAsync(streamName, StreamRevision.None, GetEvents()) - .ShouldThrowAsync(); - - var result = Fixture.Streams.ReadStreamAsync(Direction.Forwards, streamName, StreamPosition.Start); - - var state = await result.ReadState; - - state.ShouldBe(ReadState.StreamNotFound); - - return; - - IEnumerable GetEvents() { - var i = 0; - foreach (var evt in Fixture.CreateTestEvents(5)) { - if (i++ % 3 == 0) - throw new EnumerationFailedException(); - - yield return evt; - } - } - } - - class EnumerationFailedException : Exception { } -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_with_timeout.cs b/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_with_timeout.cs deleted file mode 100644 index 9e305dd04..000000000 --- a/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_with_timeout.cs +++ /dev/null @@ -1,48 +0,0 @@ -using Grpc.Core; - -namespace EventStore.Client.Streams.Tests; - -[Trait("Category", "Network")] -[Trait("Category", "Stream")] -[Trait("Category", "Append")] -public class append_to_stream_with_timeout : IClassFixture { - public append_to_stream_with_timeout(ITestOutputHelper output, EventStoreFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - EventStoreFixture Fixture { get; } - - public static IEnumerable ArgumentOutOfRangeTestCases() { - yield return new object?[] { StreamState.Any }; - yield return new object?[] { ulong.MaxValue - 1UL }; - } - - [Fact] - public async Task any_stream_revision_fails_when_operation_expired() { - var stream = Fixture.GetStreamName(); - - var ex = await Fixture.Streams.AppendToStreamAsync( - stream, - StreamState.Any, - Fixture.CreateTestEvents(100), - deadline: TimeSpan.FromTicks(1) - ).ShouldThrowAsync(); - - ex.StatusCode.ShouldBe(StatusCode.DeadlineExceeded); - } - - [Fact] - public async Task stream_revision_fails_when_operation_expired() { - var stream = Fixture.GetStreamName(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, Fixture.CreateTestEvents()); - - var ex = await Fixture.Streams.AppendToStreamAsync( - stream, - new StreamRevision(0), - Fixture.CreateTestEvents(10), - deadline: TimeSpan.Zero - ).ShouldThrowAsync(); - - ex.StatusCode.ShouldBe(StatusCode.DeadlineExceeded); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/AppendToStream/appending_to_implicitly_created_stream.cs b/test/EventStore.Client.Streams.Tests/AppendToStream/appending_to_implicitly_created_stream.cs index a153e0f1b..5a15a4d64 100644 --- a/test/EventStore.Client.Streams.Tests/AppendToStream/appending_to_implicitly_created_stream.cs +++ b/test/EventStore.Client.Streams.Tests/AppendToStream/appending_to_implicitly_created_stream.cs @@ -3,13 +3,7 @@ namespace EventStore.Client.Streams.Tests; [Trait("Category", "LongRunning")] [Trait("Category", "Stream")] [Trait("Category", "Append")] -public class appending_to_implicitly_created_stream - : IClassFixture { - public appending_to_implicitly_created_stream(ITestOutputHelper output, EventStoreFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - EventStoreFixture Fixture { get; } - +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(); diff --git a/test/EventStore.Client.Streams.Tests/AppendToStream/sending_and_receiving_large_messages.cs b/test/EventStore.Client.Streams.Tests/AppendToStream/sending_and_receiving_large_messages.cs index a65b9d317..51c4200ce 100644 --- a/test/EventStore.Client.Streams.Tests/AppendToStream/sending_and_receiving_large_messages.cs +++ b/test/EventStore.Client.Streams.Tests/AppendToStream/sending_and_receiving_large_messages.cs @@ -4,12 +4,8 @@ namespace EventStore.Client.Streams.Tests; [Trait("Category", "Stream")] [Trait("Category", "Append")] -public class sending_and_receiving_large_messages : IClassFixture { - public sending_and_receiving_large_messages(ITestOutputHelper output, CustomFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - CustomFixture Fixture { get; } - +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(); diff --git a/test/EventStore.Client.Streams.Tests/Bugs/Issue_104.cs b/test/EventStore.Client.Streams.Tests/Bugs/Issue_104.cs index 799f5d203..67815004d 100644 --- a/test/EventStore.Client.Streams.Tests/Bugs/Issue_104.cs +++ b/test/EventStore.Client.Streams.Tests/Bugs/Issue_104.cs @@ -1,12 +1,7 @@ namespace EventStore.Client.Streams.Tests.Bugs; [Trait("Category", "Bug")] -public class Issue_104 : IClassFixture { - public Issue_104(ITestOutputHelper output, EventStoreFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - EventStoreFixture Fixture { get; } - +public class Issue_104(ITestOutputHelper output, EventStoreFixture fixture) : EventStoreTests(output, fixture) { [Fact] public async Task subscription_does_not_send_checkpoint_reached_after_disposal() { var streamName = Fixture.GetStreamName(); @@ -52,6 +47,6 @@ await Fixture.Streams.AppendToStreamAsync( var delay = Task.Delay(300); var result = await Task.WhenAny(delay, checkpointReachAfterDisposed.Task); - Assert.Equal(delay, result); // iow 300ms have passed without seeing checkpointReachAfterDisposed + result.ShouldBe(delay); // iow 300ms have passed without seeing checkpointReachAfterDisposed } } \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/Bugs/Issue_2544.cs b/test/EventStore.Client.Streams.Tests/Bugs/Issue_2544.cs index fb2ab3616..26f9dbd83 100644 --- a/test/EventStore.Client.Streams.Tests/Bugs/Issue_2544.cs +++ b/test/EventStore.Client.Streams.Tests/Bugs/Issue_2544.cs @@ -168,17 +168,4 @@ Task EventAppeared(ResolvedEvent e, string streamName) { return Task.CompletedTask; } -} - -public class IssueFixture : EventStoreFixture { - public IssueFixture() { - OnSetup = async () => { - await Streams.SetStreamMetadataAsync( - SystemStreams.AllStream, - StreamState.Any, - new(acl: new(SystemRoles.All)), - userCredentials: TestCredentials.Root - ); - }; - } } \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/DeleteStream/delete_stream_with_timeout.cs b/test/EventStore.Client.Streams.Tests/DeleteStream/delete_stream_with_timeout.cs deleted file mode 100644 index aeb4f8f65..000000000 --- a/test/EventStore.Client.Streams.Tests/DeleteStream/delete_stream_with_timeout.cs +++ /dev/null @@ -1,58 +0,0 @@ -using Grpc.Core; - -namespace EventStore.Client.Streams.Tests; - -[Trait("Category", "Network")] -[Trait("Category", "Delete")] -public class deleting_stream_with_timeout : IClassFixture { - public deleting_stream_with_timeout(ITestOutputHelper output, EventStoreFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - EventStoreFixture Fixture { get; } - - [Fact] - public async Task 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) - ); - - Assert.Equal(StatusCode.DeadlineExceeded, rpcException.StatusCode); - } - - [Fact] - public async Task 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) - ); - - Assert.Equal(StatusCode.DeadlineExceeded, rpcException.StatusCode); - } - - [Fact] - public async Task 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) - ); - - Assert.Equal(StatusCode.DeadlineExceeded, rpcException.StatusCode); - } - - [Fact] - public async Task 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) - ); - - Assert.Equal(StatusCode.DeadlineExceeded, rpcException.StatusCode); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/DeleteStream/deleting_stream.cs b/test/EventStore.Client.Streams.Tests/DeleteStream/deleting_stream.cs index cfdd42626..c036861ea 100644 --- a/test/EventStore.Client.Streams.Tests/DeleteStream/deleting_stream.cs +++ b/test/EventStore.Client.Streams.Tests/DeleteStream/deleting_stream.cs @@ -1,13 +1,10 @@ +using Grpc.Core; + namespace EventStore.Client.Streams.Tests; [Trait("Category", "Network")] [Trait("Category", "Delete")] -public class deleting_stream : IClassFixture { - public deleting_stream(ITestOutputHelper output, EventStoreFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - EventStoreFixture Fixture { get; } - +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) }; @@ -82,4 +79,47 @@ 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) + ); + + Assert.Equal(StatusCode.DeadlineExceeded, rpcException.StatusCode); + } + + [Fact] + 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) + ); + + 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) + ); + + Assert.Equal(StatusCode.DeadlineExceeded, rpcException.StatusCode); + } + + [Fact] + 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) + ); + + Assert.Equal(StatusCode.DeadlineExceeded, rpcException.StatusCode); + } } \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/DeleteStream/soft_deleted_stream.cs b/test/EventStore.Client.Streams.Tests/DeleteStream/soft_deleted_stream.cs index ee83b84fe..c27ece1cd 100644 --- a/test/EventStore.Client.Streams.Tests/DeleteStream/soft_deleted_stream.cs +++ b/test/EventStore.Client.Streams.Tests/DeleteStream/soft_deleted_stream.cs @@ -4,10 +4,10 @@ namespace EventStore.Client.Streams.Tests; [Trait("Category", "LongRunning")] [Trait("Category", "Delete")] -public class deleted_stream : IClassFixture { - public deleted_stream(ITestOutputHelper output, EventStoreFixture fixture) { - Fixture = fixture.With(x => x.CaptureTestRun(output)); +public class deleted_stream(ITestOutputHelper output, EventStoreFixture fixture) : EventStoreTests(output, fixture) { + static JsonDocument CustomMetadata { get; } + static deleted_stream() { var customMetadata = new Dictionary { ["key1"] = true, ["key2"] = 17, @@ -16,10 +16,7 @@ public deleted_stream(ITestOutputHelper output, EventStoreFixture fixture) { CustomMetadata = JsonDocument.Parse(JsonSerializer.Serialize(customMetadata)); } - - EventStoreFixture Fixture { get; } - JsonDocument CustomMetadata { get; } - + [Fact] public async Task reading_throws() { var stream = Fixture.GetStreamName(); @@ -129,7 +126,8 @@ public async Task recreated_with_expected_version() { [Fact] public async Task recreated_preserves_metadata_except_truncate_before() { const int count = 2; - var stream = Fixture.GetStreamName(); + + var stream = Fixture.GetStreamName(); var writeResult = await Fixture.Streams.AppendToStreamAsync( stream, @@ -225,12 +223,11 @@ await Assert.ThrowsAsync( public async Task allows_recreating_for_first_write_only_throws_wrong_expected_version() { var stream = Fixture.GetStreamName(); - var writeResult = - await Fixture.Streams.AppendToStreamAsync( - stream, - StreamState.NoStream, - Fixture.CreateTestEvents(2) - ); + var writeResult = await Fixture.Streams.AppendToStreamAsync( + stream, + StreamState.NoStream, + Fixture.CreateTestEvents(2) + ); Assert.Equal(new(1), writeResult.NextExpectedStreamRevision); @@ -257,8 +254,7 @@ await Assert.ThrowsAsync( public async Task allows_recreating_for_first_write_only_returns_wrong_expected_version() { var stream = Fixture.GetStreamName(); - var writeResult = - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents(2)); + var writeResult = await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents(2)); Assert.Equal(new(1), writeResult.NextExpectedStreamRevision); @@ -372,7 +368,8 @@ await Assert.ThrowsAsync( [Fact] public async Task recreated_on_non_empty_when_metadata_set() { const int count = 2; - var stream = Fixture.GetStreamName(); + + var stream = Fixture.GetStreamName(); var streamMetadata = new StreamMetadata( acl: new(deleteRole: "some-role"), diff --git a/test/EventStore.Client.Streams.Tests/EventDataComparer.cs b/test/EventStore.Client.Streams.Tests/EventDataComparer.cs index 780268a76..48a5e8977 100644 --- a/test/EventStore.Client.Streams.Tests/EventDataComparer.cs +++ b/test/EventStore.Client.Streams.Tests/EventDataComparer.cs @@ -1,5 +1,3 @@ -using System.Text; - namespace EventStore.Client.Streams.Tests; static class EventDataComparer { @@ -10,23 +8,14 @@ public static bool Equal(EventData expected, EventRecord actual) { if (expected.Type != actual.EventType) return false; - var expectedDataString = Encoding.UTF8.GetString(expected.Data.ToArray()); - var expectedMetadataString = Encoding.UTF8.GetString(expected.Metadata.ToArray()); - - var actualDataString = Encoding.UTF8.GetString(actual.Data.ToArray()); - var actualMetadataDataString = Encoding.UTF8.GetString(actual.Metadata.ToArray()); - - return expectedDataString == actualDataString && expectedMetadataString == actualMetadataDataString; + return expected.Data.ToArray().SequenceEqual(actual.Data.ToArray()) + && expected.Metadata.ToArray().SequenceEqual(actual.Metadata.ToArray()); } public static bool Equal(EventData[] expected, EventRecord[] actual) { if (expected.Length != actual.Length) return false; - for (var i = 0; i < expected.Length; i++) - if (!Equal(expected[i], actual[i])) - return false; - - return true; + return !expected.Where((t, i) => !Equal(t, actual[i])).Any(); } } \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/EventDataTests.cs b/test/EventStore.Client.Streams.Tests/EventDataTests.cs index b5cf352da..6c661ae59 100644 --- a/test/EventStore.Client.Streams.Tests/EventDataTests.cs +++ b/test/EventStore.Client.Streams.Tests/EventDataTests.cs @@ -4,8 +4,7 @@ public class EventDataTests { [Fact] public void EmptyEventIdThrows() { var ex = Assert.Throws( - () => - new EventData(Uuid.Empty, "-", Array.Empty()) + () => new EventData(Uuid.Empty, "-", Array.Empty()) ); Assert.Equal("eventId", ex.ParamName); diff --git a/test/EventStore.Client.Streams.Tests/EventStore.Client.Streams.Tests.csproj b/test/EventStore.Client.Streams.Tests/EventStore.Client.Streams.Tests.csproj index dac52c701..d32b56a43 100644 --- a/test/EventStore.Client.Streams.Tests/EventStore.Client.Streams.Tests.csproj +++ b/test/EventStore.Client.Streams.Tests/EventStore.Client.Streams.Tests.csproj @@ -3,4 +3,7 @@ + + + \ 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 index 7650c6666..b40879498 100644 --- a/test/EventStore.Client.Streams.Tests/EventStore.Client.Streams.Tests.csproj.DotSettings +++ b/test/EventStore.Client.Streams.Tests/EventStore.Client.Streams.Tests.csproj.DotSettings @@ -3,6 +3,7 @@ True True True + True True True True \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/ReadAll/EventBinaryData.cs b/test/EventStore.Client.Streams.Tests/ReadAll/EventBinaryData.cs new file mode 100644 index 000000000..1f7d3bf3b --- /dev/null +++ b/test/EventStore.Client.Streams.Tests/ReadAll/EventBinaryData.cs @@ -0,0 +1,33 @@ +namespace EventStore.Client.Streams.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) + && 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) => + new(source.EventId, source.Data.ToArray(), source.Metadata.ToArray()); + + public static EventBinaryData ToBinaryData(this EventRecord source) => + new(source.EventId, source.Data.ToArray(), source.Metadata.ToArray()); + + public static EventBinaryData ToBinaryData(this ResolvedEvent source) => + source.Event.ToBinaryData(); + + public static EventBinaryData[] ToBinaryData(this IEnumerable source) => + source.Select(x => x.ToBinaryData()).ToArray(); + + public static EventBinaryData[] ToBinaryData(this IEnumerable source) => + source.Select(x => x.ToBinaryData()).ToArray(); + + 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/ReadAll/ReadAllEventsFixture.cs b/test/EventStore.Client.Streams.Tests/ReadAll/ReadAllEventsFixture.cs new file mode 100644 index 000000000..2579e4260 --- /dev/null +++ b/test/EventStore.Client.Streams.Tests/ReadAll/ReadAllEventsFixture.cs @@ -0,0 +1,41 @@ +namespace EventStore.Client.Streams.Tests; + +public class ReadAllEventsFixture : EventStoreFixture { + public ReadAllEventsFixture() { + OnSetup = async () => { + _ = await Streams.SetStreamMetadataAsync( + SystemStreams.AllStream, + StreamState.NoStream, + new(acl: new(SystemRoles.All)), + userCredentials: TestCredentials.Root + ); + + Events = Enumerable + .Concat( + CreateTestEvents(20), + CreateTestEvents(2, metadataSize: 1_000_000) + ) + .ToArray(); + + ExpectedStreamName = GetStreamName(); + + await Streams.AppendToStreamAsync(ExpectedStreamName, StreamState.NoStream, Events); + + ExpectedEvents = Events.ToBinaryData(); + ExpectedEventsReversed = ExpectedEvents.Reverse().ToArray(); + + ExpectedFirstEvent = ExpectedEvents.First(); + ExpectedLastEvent = ExpectedEvents.Last(); + }; + } + + public string ExpectedStreamName { get; private set; } = null!; + + public EventData[] Events { get; private set; } = Array.Empty(); + + public EventBinaryData[] ExpectedEvents { get; private set; } = Array.Empty(); + public EventBinaryData[] ExpectedEventsReversed { get; private set; } = Array.Empty(); + + 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/ReadAll/read_all_backward_messages.cs b/test/EventStore.Client.Streams.Tests/ReadAll/read_all_backward_messages.cs deleted file mode 100644 index 805f82fb5..000000000 --- a/test/EventStore.Client.Streams.Tests/ReadAll/read_all_backward_messages.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace EventStore.Client.Streams.Tests; - -[Trait("Category", "Network")] -[Trait("Category", "AllStream")] -[Trait("Category", "Read")] -public class read_all_backward_messages : IClassFixture { - public read_all_backward_messages(ITestOutputHelper output, EventStoreFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - EventStoreFixture Fixture { get; } - - [Fact] - public async Task stream_found() { - var events = Fixture.CreateTestEvents(32).ToArray(); - - var streamName = Fixture.GetStreamName(); - - await Fixture.Streams.AppendToStreamAsync(streamName, StreamState.NoStream, events); - - var result = await Fixture.Streams.ReadAllAsync( - Direction.Backwards, - Position.End, - 32, - userCredentials: TestCredentials.Root - ).Messages.ToArrayAsync(); - - Assert.Equal(32, result.OfType().Count()); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/ReadAll/read_all_events_backward.cs b/test/EventStore.Client.Streams.Tests/ReadAll/read_all_events_backward.cs index ef236e706..daf2024d1 100644 --- a/test/EventStore.Client.Streams.Tests/ReadAll/read_all_events_backward.cs +++ b/test/EventStore.Client.Streams.Tests/ReadAll/read_all_events_backward.cs @@ -1,55 +1,78 @@ +using Grpc.Core; + namespace EventStore.Client.Streams.Tests; [Trait("Category", "LongRunning")] [Trait("Category", "AllStream")] [Trait("Category", "Read")] -public class read_all_events_backward : IClassFixture { - public read_all_events_backward(ITestOutputHelper output, ReadAllEventsBackward fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - ReadAllEventsBackward Fixture { get; } - +[Trait("Category", "ReadBackwards")] +[Trait("Category", "DedicatedDatabase")] +public class read_all_events_backward(ITestOutputHelper output, ReadAllEventsFixture fixture) : EventStoreTests(output, fixture) { [Fact] public async Task return_empty_if_reading_from_start() { - var count = await Fixture.Streams.ReadAllAsync(Direction.Backwards, Position.Start, 1).CountAsync(); - Assert.Equal(0, count); + var result = await Fixture.Streams.ReadAllAsync(Direction.Backwards, Position.Start, 1).CountAsync(); + result.ShouldBe(0); } [Fact] public async Task return_partial_slice_if_not_enough_events() { - var events = await Fixture.Streams.ReadAllAsync(Direction.Backwards, Position.End, Fixture.Events.Length * 2) - .ToArrayAsync(); - - Assert.True(events.Length < Fixture.Events.Length * 2); + var count = await Fixture.Streams.ReadAllAsync(Direction.Forwards, Position.Start).CountAsync(); + var sliceSize = count * 2; + var result = await Fixture.Streams.ReadAllAsync(Direction.Backwards, Position.End, sliceSize).ToArrayAsync(); + result.Length.ShouldBeLessThan(sliceSize); } [Fact] public async Task return_events_in_reversed_order_compared_to_written() { - var events = await Fixture.Streams.ReadAllAsync(Direction.Backwards, Position.End, Fixture.Events.Length) - .ToArrayAsync(); - - Assert.True( - EventDataComparer.Equal( - Fixture.Events.Reverse().ToArray(), - events.AsResolvedTestEvents().ToArray() - ) - ); + // TODO SS: this test must be fixed to deterministically read the expected events regardless of how many already exist. reading all for now... + var result = await Fixture.Streams + .ReadAllAsync(Direction.Backwards, Position.End) + .Where(x => x.OriginalStreamId == Fixture.ExpectedStreamName) + .ToBinaryData(); + + result.ShouldBe(Fixture.ExpectedEventsReversed); } [Fact] public async Task return_single_event() { - var events = await Fixture.Streams.ReadAllAsync(Direction.Backwards, Position.End, 1) + var result = await Fixture.Streams + .ReadAllAsync(Direction.Backwards, Position.End, 1) .ToArrayAsync(); - - var actualEvent = Assert.Single(events.AsResolvedTestEvents()); - Assert.True( - EventDataComparer.Equal( - Fixture.Events.Last(), - actualEvent - ) - ); + + result.ShouldHaveSingleItem(); } + [Fact] + public async Task max_count_is_respected() { + var maxCount = Fixture.ExpectedEvents.Length / 2; + var result = await Fixture.Streams + .ReadAllAsync(Direction.Backwards, Position.End, maxCount) + .Take(Fixture.ExpectedEvents.Length) + .ToArrayAsync(); + + 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(Skip = "Not Implemented")] public Task be_able_to_read_all_one_by_one_until_end_of_stream() => throw new NotImplementedException(); @@ -58,40 +81,4 @@ public async Task return_single_event() { [Fact(Skip = "Not Implemented")] public Task when_got_int_max_value_as_maxcount_should_throw() => throw new NotImplementedException(); - - [Fact] - public async Task max_count_is_respected() { - var maxCount = Fixture.Events.Length / 2; - var events = await Fixture.Streams.ReadAllAsync(Direction.Backwards, Position.End, maxCount) - .Take(Fixture.Events.Length) - .ToArrayAsync(); - - Assert.Equal(maxCount, events.Length); - } -} - -public class ReadAllEventsBackward : EventStoreFixture { - public ReadAllEventsBackward() { - OnSetup = async () => { - Events = Enumerable - .Concat( - CreateTestEvents(20), - CreateTestEvents(2, metadataSize: 1_000_000) - ) - .ToArray(); - - var streamName = GetStreamName(); - - var result = await Streams.SetStreamMetadataAsync( - SystemStreams.AllStream, - StreamState.NoStream, - new(acl: new(SystemRoles.All)), - userCredentials: TestCredentials.Root - ); - - await Streams.AppendToStreamAsync(streamName, StreamState.NoStream, Events); - }; - } - - public EventData[] Events { get; private set; } = Array.Empty(); } \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/ReadAll/read_all_events_forward.cs b/test/EventStore.Client.Streams.Tests/ReadAll/read_all_events_forward.cs index b4c5f054e..025fbff87 100644 --- a/test/EventStore.Client.Streams.Tests/ReadAll/read_all_events_forward.cs +++ b/test/EventStore.Client.Streams.Tests/ReadAll/read_all_events_forward.cs @@ -1,96 +1,150 @@ +using System.Text; + namespace EventStore.Client.Streams.Tests; [Trait("Category", "LongRunning")] [Trait("Category", "AllStream")] [Trait("Category", "Read")] -public class read_all_events_forward : IClassFixture { - public read_all_events_forward(ITestOutputHelper output, ReadAllEventsForward fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - ReadAllEventsForward Fixture { get; } - +[Trait("Category", "ReadForwards")] +public class read_all_events_forward(ITestOutputHelper output, ReadAllEventsFixture fixture) : EventStoreTests(output, fixture) { [Fact] public async Task return_empty_if_reading_from_end() { - var count = await Fixture.Streams.ReadAllAsync(Direction.Forwards, Position.End, 1).CountAsync(); - Assert.Equal(0, count); + var result = await Fixture.Streams.ReadAllAsync(Direction.Forwards, Position.End, 1).CountAsync(); + result.ShouldBe(0); } [Fact] public async Task return_partial_slice_if_not_enough_events() { - var events = await Fixture.Streams - .ReadAllAsync(Direction.Forwards, Position.Start, Fixture.Events.Length * 2) - .ToArrayAsync(); - - Assert.True(events.Length < Fixture.Events.Length * 2); + var sliceSize = Fixture.ExpectedEvents.Length * 2; + var result = await Fixture.Streams.ReadAllAsync(Direction.Forwards, Position.Start, sliceSize).ToArrayAsync(); + result.Length.ShouldBeLessThan(sliceSize); } [Fact] public async Task return_events_in_correct_order_compared_to_written() { - var events = await Fixture.Streams - .ReadAllAsync(Direction.Forwards, Position.Start, Fixture.Events.Length * 2) - .ToArrayAsync(); - - Assert.True(EventDataComparer.Equal(Fixture.Events, events.AsResolvedTestEvents().ToArray())); + // TODO SS: this test must be fixed to deterministically read the expected events regardless of how many already exist. reading all for now... + var result = await Fixture.Streams + .ReadAllAsync(Direction.Forwards, Position.Start) + .Where(x => x.OriginalStreamId == Fixture.ExpectedStreamName) + .ToBinaryData(); + + result.ShouldBe(Fixture.ExpectedEvents); } [Fact] public async Task return_single_event() { - var events = await Fixture.Streams.ReadAllAsync(Direction.Forwards, Position.Start, 1) + var result = await Fixture.Streams + .ReadAllAsync(Direction.Forwards, Position.Start, 1) .ToArrayAsync(); - - Assert.Single(events); + + result.ShouldHaveSingleItem(); } - [Fact(Skip = "Not Implemented")] - public Task be_able_to_read_all_one_by_one_until_end_of_stream() => throw new NotImplementedException(); - - [Fact(Skip = "Not Implemented")] - public Task be_able_to_read_events_slice_at_time() => throw new NotImplementedException(); - - [Fact(Skip = "Not Implemented")] - public Task when_got_int_max_value_as_maxcount_should_throw() => throw new NotImplementedException(); - [Fact] public async Task max_count_is_respected() { - var maxCount = Fixture.Events.Length / 2; - var events = await Fixture.Streams.ReadAllAsync(Direction.Forwards, Position.Start, maxCount) - .Take(Fixture.Events.Length) + var maxCount = Fixture.ExpectedEvents.Length / 2; + var result = await Fixture.Streams + .ReadAllAsync(Direction.Forwards, Position.Start, maxCount) + .Take(Fixture.ExpectedEvents.Length) .ToArrayAsync(); - Assert.Equal(maxCount, events.Length); + result.Length.ShouldBe(maxCount); } [Fact] public async Task reads_all_events_by_default() { - var count = await Fixture.Streams.ReadAllAsync(Direction.Forwards, Position.Start) + var count = await Fixture.Streams + .ReadAllAsync(Direction.Forwards, Position.Start) .CountAsync(); - Assert.True(count >= Fixture.Events.Length); + Assert.True(count >= Fixture.ExpectedEvents.Length); } -} - -public class ReadAllEventsForward : EventStoreFixture { - public ReadAllEventsForward() { - OnSetup = async () => { - Events = Enumerable - .Concat( - CreateTestEvents(20), - CreateTestEvents(2, metadataSize: 1_000_000) + + [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, + StreamState.Any, + new(2) + ); + + await Fixture.Streams.AppendToStreamAsync(deletedStream, StreamState.Any, Fixture.CreateTestEvents()); + await Fixture.Streams.AppendToStreamAsync(deletedStream, StreamState.Any, Fixture.CreateTestEvents()); + await Fixture.Streams.AppendToStreamAsync( + linkedStream, + StreamState.Any, + new[] { + new EventData( + Uuid.NewUuid(), + SystemEventTypes.LinkTo, + Encoding.UTF8.GetBytes($"0@{deletedStream}"), + Array.Empty(), + Constants.Metadata.ContentTypes.ApplicationOctetStream ) - .ToArray(); - - var streamName = GetStreamName(); - - var result = await Streams.SetStreamMetadataAsync( - SystemStreams.AllStream, - StreamState.NoStream, - new(acl: new(SystemRoles.All)), - userCredentials: TestCredentials.Root - ); + } + ); + + var events = await Fixture.Streams.ReadStreamAsync( + Direction.Forwards, + linkedStream, + StreamPosition.Start, + resolveLinkTos: true + ) + .ToArrayAsync(); + + Assert.Single(events); + } + + [Fact] + public async Task enumeration_all_referencing_messages_twice_does_not_throw() { + var result = Fixture.Streams.ReadAllAsync( + Direction.Forwards, + Position.Start, + 32, + userCredentials: TestCredentials.Root + ); + + _ = result.Messages; + await result.Messages.ToArrayAsync(); + } - await Streams.AppendToStreamAsync(streamName, StreamState.NoStream, Events); - }; + [Fact] + public async Task enumeration_all_enumerating_messages_twice_throws() { + var result = Fixture.Streams.ReadAllAsync( + Direction.Forwards, + Position.Start, + 32, + userCredentials: TestCredentials.Root + ); + + await result.Messages.ToArrayAsync(); + + await Assert.ThrowsAsync( + async () => + await result.Messages.ToArrayAsync() + ); } + + [Fact(Skip = "Not Implemented")] + public Task be_able_to_read_all_one_by_one_until_end_of_stream() => throw new NotImplementedException(); - public EventData[] Events { get; private set; } = Array.Empty(); + [Fact(Skip = "Not Implemented")] + public Task be_able_to_read_events_slice_at_time() => throw new NotImplementedException(); + + [Fact(Skip = "Not Implemented")] + public Task when_got_int_max_value_as_maxcount_should_throw() => throw new NotImplementedException(); } \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/ReadAll/read_all_events_forward_with_linkto_passed_max_count.cs b/test/EventStore.Client.Streams.Tests/ReadAll/read_all_events_forward_with_linkto_passed_max_count.cs deleted file mode 100644 index f955a33b9..000000000 --- a/test/EventStore.Client.Streams.Tests/ReadAll/read_all_events_forward_with_linkto_passed_max_count.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System.Text; - -namespace EventStore.Client.Streams.Tests; - -[Trait("Category", "LongRunning")] -[Trait("Category", "AllStream")] -[Trait("Category", "Read")] -public class read_all_events_forward_with_linkto_passed_max_count : IClassFixture { - public read_all_events_forward_with_linkto_passed_max_count(ITestOutputHelper output, EventStoreFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - EventStoreFixture Fixture { get; } - - [Fact] - public async Task 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, - StreamState.Any, - new(2) - ); - - await Fixture.Streams.AppendToStreamAsync(deletedStream, StreamState.Any, Fixture.CreateTestEvents()); - await Fixture.Streams.AppendToStreamAsync(deletedStream, StreamState.Any, Fixture.CreateTestEvents()); - await Fixture.Streams.AppendToStreamAsync( - linkedStream, - StreamState.Any, - new[] { - new EventData( - Uuid.NewUuid(), - SystemEventTypes.LinkTo, - Encoding.UTF8.GetBytes("0@" + deletedStream), - Array.Empty(), - Constants.Metadata.ContentTypes.ApplicationOctetStream - ) - } - ); - - var events = await Fixture.Streams.ReadStreamAsync( - Direction.Forwards, - linkedStream, - StreamPosition.Start, - resolveLinkTos: true - ) - .ToArrayAsync(); - - Assert.Single(events); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/ReadAll/read_all_forward_messages.cs b/test/EventStore.Client.Streams.Tests/ReadAll/read_all_forward_messages.cs deleted file mode 100644 index c572cb251..000000000 --- a/test/EventStore.Client.Streams.Tests/ReadAll/read_all_forward_messages.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace EventStore.Client.Streams.Tests; - -[Trait("Category", "Network")] -[Trait("Category", "AllStream")] -[Trait("Category", "Read")] -public class read_all_forward_messages : IClassFixture { - public read_all_forward_messages(ITestOutputHelper output, EventStoreFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - EventStoreFixture Fixture { get; } - - [Fact] - public async Task stream_found() { - var events = Fixture.CreateTestEvents(32).ToArray(); - - var streamName = Fixture.GetStreamName(); - - await Fixture.Streams.AppendToStreamAsync(streamName, StreamState.NoStream, events); - - var result = await Fixture.Streams.ReadAllAsync( - Direction.Forwards, - Position.Start, - 32, - userCredentials: TestCredentials.Root - ).Messages.ToArrayAsync(); - - Assert.Equal(32, result.OfType().Count()); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/ReadAll/read_all_with_timeout.cs b/test/EventStore.Client.Streams.Tests/ReadAll/read_all_with_timeout.cs deleted file mode 100644 index 4ec5b16ca..000000000 --- a/test/EventStore.Client.Streams.Tests/ReadAll/read_all_with_timeout.cs +++ /dev/null @@ -1,31 +0,0 @@ -using Grpc.Core; - -namespace EventStore.Client.Streams.Tests; - -[Trait("Category", "Network")] -[Trait("Category", "LongRunning")] -[Trait("Category", "AllStream")] -[Trait("Category", "Read")] -public class read_all_with_timeout : IClassFixture { - public read_all_with_timeout(ITestOutputHelper output, EventStoreFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - EventStoreFixture Fixture { get; } - - [Fact] - public async Task fails_when_operation_expired() { - var rpcException = await Assert.ThrowsAsync( - () => Fixture.Streams - .ReadAllAsync( - Direction.Backwards, - Position.Start, - 1, - false, - TimeSpan.Zero - ) - .ToArrayAsync().AsTask() - ); - - Assert.Equal(StatusCode.DeadlineExceeded, rpcException.StatusCode); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/ReadAll/read_enumeration_tests.cs b/test/EventStore.Client.Streams.Tests/ReadAll/read_enumeration_tests.cs deleted file mode 100644 index a9e11e4d1..000000000 --- a/test/EventStore.Client.Streams.Tests/ReadAll/read_enumeration_tests.cs +++ /dev/null @@ -1,75 +0,0 @@ -namespace EventStore.Client.Streams.Tests; - -[Trait("Category", "Network")] -[Trait("Category", "LongRunning")] -[Trait("Category", "AllStream")] -[Trait("Category", "Stream")] -[Trait("Category", "Read")] -public class read_enumeration_tests : IClassFixture { - public read_enumeration_tests(ITestOutputHelper output, EventStoreFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - EventStoreFixture Fixture { get; } - - [Fact] - public async Task all_referencing_messages_twice_does_not_throw() { - var result = Fixture.Streams.ReadAllAsync( - Direction.Forwards, - Position.Start, - 32, - userCredentials: TestCredentials.Root - ); - - _ = result.Messages; - await result.Messages.ToArrayAsync(); - } - - [Fact] - public async Task all_enumerating_messages_twice_throws() { - var result = Fixture.Streams.ReadAllAsync( - Direction.Forwards, - Position.Start, - 32, - userCredentials: TestCredentials.Root - ); - - await result.Messages.ToArrayAsync(); - - await Assert.ThrowsAsync( - async () => - await result.Messages.ToArrayAsync() - ); - } - - [Fact] - public async Task referencing_messages_twice_does_not_throw() { - var result = Fixture.Streams.ReadStreamAsync( - Direction.Forwards, - "$users", - StreamPosition.Start, - 32, - userCredentials: TestCredentials.Root - ); - - _ = result.Messages; - await result.Messages.ToArrayAsync(); - } - - [Fact] - public async Task enumerating_messages_twice_throws() { - var result = Fixture.Streams.ReadStreamAsync( - Direction.Forwards, - "$users", - StreamPosition.Start, - 32, - userCredentials: TestCredentials.Root - ); - - await result.Messages.ToArrayAsync(); - - await Assert.ThrowsAsync( - async () => - await result.Messages.ToArrayAsync() - ); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_backward.cs b/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_backward.cs index 675404223..228931560 100644 --- a/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_backward.cs +++ b/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_backward.cs @@ -1,14 +1,11 @@ +using Grpc.Core; + namespace EventStore.Client.Streams.Tests; [Trait("Category", "Network")] [Trait("Category", "Stream")] [Trait("Category", "Read")] -public class read_stream_backward : IClassFixture { - public read_stream_backward(ITestOutputHelper output, EventStoreFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - EventStoreFixture Fixture { get; } - +public class read_stream_backward(ITestOutputHelper output, EventStoreFixture fixture) : EventStoreTests(output, fixture) { [Theory] [InlineData(0)] public async Task count_le_equal_zero_throws(long maxCount) { @@ -184,4 +181,97 @@ 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(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamRevision.None, Fixture.CreateTestEvents()); + + var rpcException = await Assert.ThrowsAsync( + () => Fixture.Streams + .ReadStreamAsync( + Direction.Backwards, + stream, + StreamPosition.End, + 1, + false, + TimeSpan.Zero + ) + .ToArrayAsync().AsTask() + ); + + Assert.Equal(StatusCode.DeadlineExceeded, rpcException.StatusCode); + } + + [Fact] + public async Task enumeration_referencing_messages_twice_does_not_throw() { + var result = Fixture.Streams.ReadStreamAsync( + Direction.Forwards, + "$users", + StreamPosition.Start, + 32, + userCredentials: TestCredentials.Root + ); + + _ = result.Messages; + await result.Messages.ToArrayAsync(); + } + + [Fact] + public async Task enumeration_enumerating_messages_twice_throws() { + var result = Fixture.Streams.ReadStreamAsync( + Direction.Forwards, + "$users", + StreamPosition.Start, + 32, + userCredentials: TestCredentials.Root + ); + + await result.Messages.ToArrayAsync(); + + await Assert.ThrowsAsync( + async () => + await result.Messages.ToArrayAsync() + ); + } + + [Fact] + public async Task stream_not_found() { + var result = await Fixture.Streams.ReadStreamAsync( + Direction.Backwards, + Fixture.GetStreamName(), + StreamPosition.End + ).Messages.SingleAsync(); + + Assert.Equal(StreamMessage.NotFound.Instance, result); + } + + [Fact] + public async Task stream_found() { + const int eventCount = 32; + + var events = Fixture.CreateTestEvents(eventCount).ToArray(); + + var streamName = Fixture.GetStreamName(); + + await Fixture.Streams.AppendToStreamAsync(streamName, StreamState.NoStream, events); + + var result = await Fixture.Streams.ReadStreamAsync( + Direction.Backwards, + streamName, + StreamPosition.End + ).Messages.ToArrayAsync(); + + Assert.Equal( + eventCount + (Fixture.EventStoreHasLastStreamPosition ? 2 : 1), + result.Length + ); + + Assert.Equal(StreamMessage.Ok.Instance, result[0]); + Assert.Equal(eventCount, result.OfType().Count()); + + 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/ReadStream/read_stream_backward_messages.cs b/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_backward_messages.cs deleted file mode 100644 index 6c1c852dc..000000000 --- a/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_backward_messages.cs +++ /dev/null @@ -1,50 +0,0 @@ -namespace EventStore.Client.Streams.Tests; - -[Trait("Category", "Network")] -[Trait("Category", "Stream")] -[Trait("Category", "Read")] -public class read_stream_backward_messages : IClassFixture { - public read_stream_backward_messages(ITestOutputHelper output, EventStoreFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - EventStoreFixture Fixture { get; } - - int EventCount { get; } = 32; - - [Fact] - public async Task stream_not_found() { - var result = await Fixture.Streams.ReadStreamAsync( - Direction.Backwards, - Fixture.GetStreamName(), - StreamPosition.End - ).Messages.SingleAsync(); - - Assert.Equal(StreamMessage.NotFound.Instance, result); - } - - [Fact] - public async Task stream_found() { - var events = Fixture.CreateTestEvents(EventCount).ToArray(); - - var streamName = Fixture.GetStreamName(); - - await Fixture.Streams.AppendToStreamAsync(streamName, StreamState.NoStream, events); - - var result = await Fixture.Streams.ReadStreamAsync( - Direction.Backwards, - streamName, - StreamPosition.End - ).Messages.ToArrayAsync(); - - Assert.Equal( - EventCount + (Fixture.EventStoreHasLastStreamPosition ? 2 : 1), - result.Length - ); - - Assert.Equal(StreamMessage.Ok.Instance, result[0]); - Assert.Equal(EventCount, result.OfType().Count()); - - 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/ReadStream/read_stream_forward.cs b/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_forward.cs index 1dda92385..68820922e 100644 --- a/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_forward.cs +++ b/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_forward.cs @@ -3,12 +3,7 @@ namespace EventStore.Client.Streams.Tests; [Trait("Category", "Network")] [Trait("Category", "Stream")] [Trait("Category", "Read")] -public class read_stream_forward : IClassFixture { - public read_stream_forward(ITestOutputHelper output, EventStoreFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - EventStoreFixture Fixture { get; } - +public class read_stream_forward(ITestOutputHelper output, EventStoreFixture fixture) : EventStoreTests(output, fixture) { [Theory] [InlineData(0)] public async Task count_le_equal_zero_throws(long maxCount) { @@ -181,4 +176,91 @@ 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 stream_not_found() { + var result = await Fixture.Streams.ReadStreamAsync( + Direction.Forwards, + Fixture.GetStreamName(), + StreamPosition.Start + ).Messages.SingleAsync(); + + Assert.Equal(StreamMessage.NotFound.Instance, result); + } + + [Fact] + public async Task stream_found() { + const int eventCount = 64; + + var events = Fixture.CreateTestEvents(eventCount).ToArray(); + + var streamName = Fixture.GetStreamName(); + + await Fixture.Streams.AppendToStreamAsync(streamName, StreamState.NoStream, events); + + var result = await Fixture.Streams.ReadStreamAsync( + Direction.Forwards, + streamName, + StreamPosition.Start + ).Messages.ToArrayAsync(); + + Assert.Equal( + eventCount + (Fixture.EventStoreHasLastStreamPosition ? 2 : 1), + result.Length + ); + + Assert.Equal(StreamMessage.Ok.Instance, result[0]); + Assert.Equal(eventCount, result.OfType().Count()); + var first = Assert.IsType(result[1]); + Assert.Equal(new(0), first.ResolvedEvent.OriginalEventNumber); + var last = Assert.IsType(result[Fixture.EventStoreHasLastStreamPosition ? ^2 : ^1]); + Assert.Equal(new((ulong)eventCount - 1), last.ResolvedEvent.OriginalEventNumber); + + if (Fixture.EventStoreHasLastStreamPosition) + Assert.Equal( + new StreamMessage.LastStreamPosition(new((ulong)eventCount - 1)), + result[^1] + ); + } + + [Fact] + public async Task stream_found_truncated() { + const int eventCount = 64; + + var events = Fixture.CreateTestEvents(eventCount).ToArray(); + + var streamName = Fixture.GetStreamName(); + + await Fixture.Streams.AppendToStreamAsync(streamName, StreamState.NoStream, events); + + await Fixture.Streams.SetStreamMetadataAsync( + streamName, + StreamState.Any, + new(truncateBefore: new StreamPosition(32)) + ); + + var result = await Fixture.Streams.ReadStreamAsync( + Direction.Forwards, + streamName, + StreamPosition.Start + ).Messages.ToArrayAsync(); + + Assert.Equal( + eventCount - 32 + (Fixture.EventStoreHasLastStreamPosition ? 3 : 1), + result.Length + ); + + Assert.Equal(StreamMessage.Ok.Instance, result[0]); + + if (Fixture.EventStoreHasLastStreamPosition) + Assert.Equal(new StreamMessage.FirstStreamPosition(new(32)), result[1]); + + Assert.Equal(32, result.OfType().Count()); + + if (Fixture.EventStoreHasLastStreamPosition) + Assert.Equal( + new StreamMessage.LastStreamPosition(new((ulong)eventCount - 1)), + result[^1] + ); + } } \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_forward_messages.cs b/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_forward_messages.cs deleted file mode 100644 index 2ae1e05a3..000000000 --- a/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_forward_messages.cs +++ /dev/null @@ -1,96 +0,0 @@ -namespace EventStore.Client.Streams.Tests; - -[Trait("Category", "Network")] -[Trait("Category", "Stream")] -[Trait("Category", "Read")] -public class read_stream_forward_messages : IClassFixture { - public read_stream_forward_messages(ITestOutputHelper output, EventStoreFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - EventStoreFixture Fixture { get; } - - int EventCount { get; } = 64; - - [Fact] - public async Task stream_not_found() { - var result = await Fixture.Streams.ReadStreamAsync( - Direction.Forwards, - Fixture.GetStreamName(), - StreamPosition.Start - ).Messages.SingleAsync(); - - Assert.Equal(StreamMessage.NotFound.Instance, result); - } - - [Fact] - public async Task stream_found() { - var events = Fixture.CreateTestEvents(EventCount).ToArray(); - - var streamName = Fixture.GetStreamName(); - - await Fixture.Streams.AppendToStreamAsync(streamName, StreamState.NoStream, events); - - var result = await Fixture.Streams.ReadStreamAsync( - Direction.Forwards, - streamName, - StreamPosition.Start - ).Messages.ToArrayAsync(); - - Assert.Equal( - EventCount + (Fixture.EventStoreHasLastStreamPosition ? 2 : 1), - result.Length - ); - - Assert.Equal(StreamMessage.Ok.Instance, result[0]); - Assert.Equal(EventCount, result.OfType().Count()); - var first = Assert.IsType(result[1]); - Assert.Equal(new(0), first.ResolvedEvent.OriginalEventNumber); - var last = Assert.IsType(result[Fixture.EventStoreHasLastStreamPosition ? ^2 : ^1]); - Assert.Equal(new((ulong)EventCount - 1), last.ResolvedEvent.OriginalEventNumber); - - if (Fixture.EventStoreHasLastStreamPosition) - Assert.Equal( - new StreamMessage.LastStreamPosition(new((ulong)EventCount - 1)), - result[^1] - ); - } - - [Fact] - public async Task stream_found_truncated() { - var events = Fixture.CreateTestEvents(EventCount).ToArray(); - - var streamName = Fixture.GetStreamName(); - - await Fixture.Streams.AppendToStreamAsync(streamName, StreamState.NoStream, events); - - await Fixture.Streams.SetStreamMetadataAsync( - streamName, - StreamState.Any, - new(truncateBefore: new StreamPosition(32)) - ); - - var result = await Fixture.Streams.ReadStreamAsync( - Direction.Forwards, - streamName, - StreamPosition.Start - ).Messages.ToArrayAsync(); - - Assert.Equal( - EventCount - 32 + (Fixture.EventStoreHasLastStreamPosition ? 3 : 1), - result.Length - ); - - Assert.Equal(StreamMessage.Ok.Instance, result[0]); - - if (Fixture.EventStoreHasLastStreamPosition) - Assert.Equal(new StreamMessage.FirstStreamPosition(new(32)), result[1]); - - Assert.Equal(32, result.OfType().Count()); - - if (Fixture.EventStoreHasLastStreamPosition) - Assert.Equal( - new StreamMessage.LastStreamPosition(new((ulong)EventCount - 1)), - result[^1] - ); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_with_timeout.cs b/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_with_timeout.cs deleted file mode 100644 index 995dc7503..000000000 --- a/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_with_timeout.cs +++ /dev/null @@ -1,35 +0,0 @@ -using Grpc.Core; - -namespace EventStore.Client.Streams.Tests; - -[Trait("Category", "Network")] -[Trait("Category", "Stream")] -[Trait("Category", "Read")] -public class read_stream_with_timeout : IClassFixture { - public read_stream_with_timeout(ITestOutputHelper output, EventStoreFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - EventStoreFixture Fixture { get; } - - [Fact] - public async Task fails_when_operation_expired() { - var stream = Fixture.GetStreamName(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamRevision.None, Fixture.CreateTestEvents()); - - var rpcException = await Assert.ThrowsAsync( - () => Fixture.Streams - .ReadStreamAsync( - Direction.Backwards, - stream, - StreamPosition.End, - 1, - false, - TimeSpan.Zero - ) - .ToArrayAsync().AsTask() - ); - - Assert.Equal(StatusCode.DeadlineExceeded, rpcException.StatusCode); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/ReadStream/when_having_max_count_set_for_stream.cs b/test/EventStore.Client.Streams.Tests/ReadStream/when_having_max_count_set_for_stream.cs index 8ebe4d724..041b4a27b 100644 --- a/test/EventStore.Client.Streams.Tests/ReadStream/when_having_max_count_set_for_stream.cs +++ b/test/EventStore.Client.Streams.Tests/ReadStream/when_having_max_count_set_for_stream.cs @@ -3,12 +3,7 @@ namespace EventStore.Client.Streams.Tests; [Trait("Category", "LongRunning")] [Trait("Category", "Stream")] [Trait("Category", "Read")] -public class when_having_max_count_set_for_stream : IClassFixture { - public when_having_max_count_set_for_stream(ITestOutputHelper output, EventStoreFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - EventStoreFixture Fixture { get; } - +public class when_having_max_count_set_for_stream (ITestOutputHelper output, EventStoreFixture fixture) : EventStoreTests(output, fixture) { [Fact] public async Task read_stream_forwards_respects_max_count() { var stream = Fixture.GetStreamName(); diff --git a/test/EventStore.Client.Streams.Tests/Security/SecurityFixture.cs b/test/EventStore.Client.Streams.Tests/Security/SecurityFixture.cs index 1b30d45c9..bcc6e8b15 100644 --- a/test/EventStore.Client.Streams.Tests/Security/SecurityFixture.cs +++ b/test/EventStore.Client.Streams.Tests/Security/SecurityFixture.cs @@ -2,7 +2,7 @@ namespace EventStore.Client.Streams.Tests.Security; -public abstract class SecurityFixture : InsecureClientTestFixture { +public class SecurityFixture : EventStoreFixture { public const string NoAclStream = nameof(NoAclStream); public const string ReadStream = nameof(ReadStream); public const string WriteStream = nameof(WriteStream); @@ -16,7 +16,7 @@ public abstract class SecurityFixture : InsecureClientTestFixture { const int TimeoutMs = 1000; - public SecurityFixture() { + public SecurityFixture() : base(x => x.WithoutDefaultCredentials()) { OnSetup = async () => { await Users.CreateUserWithRetry( TestCredentials.TestUser1.Username!, diff --git a/test/EventStore.Client.Streams.Tests/Security/all_stream_with_no_acl_security.cs b/test/EventStore.Client.Streams.Tests/Security/all_stream_with_no_acl_security.cs index 1049db01c..c87f2e1df 100644 --- a/test/EventStore.Client.Streams.Tests/Security/all_stream_with_no_acl_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/all_stream_with_no_acl_security.cs @@ -1,14 +1,7 @@ -namespace EventStore.Client.Streams.Tests.Security; +namespace EventStore.Client.Streams.Tests.Security; [Trait("Category", "Security")] -public class all_stream_with_no_acl_security : IClassFixture { - public all_stream_with_no_acl_security(ITestOutputHelper output, CustomFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - CustomFixture Fixture { get; } - - public all_stream_with_no_acl_security(CustomFixture fixture) => Fixture = fixture; - +public class all_stream_with_no_acl_security(ITestOutputHelper output, all_stream_with_no_acl_security.CustomFixture fixture) : EventStoreTests(output, fixture) { [Fact] public async Task write_to_all_is_never_allowed() { await Assert.ThrowsAsync(() => Fixture.AppendStream(SecurityFixture.AllStream)); @@ -56,19 +49,14 @@ public async Task meta_write_is_not_allowed_for_usual_user() => await Assert.ThrowsAsync(() => Fixture.WriteMeta(SecurityFixture.AllStream, TestCredentials.TestUser1)); [Fact] - public Task meta_write_is_allowed_for_admin_user() => + public Task meta_write_is_allowed_for_admin_user() => Fixture.WriteMeta(SecurityFixture.AllStream, TestCredentials.TestAdmin); public class CustomFixture : SecurityFixture { protected override async Task Given() { await base.Given(); - - await Streams.SetStreamMetadataAsync( - AllStream, - StreamState.Any, - new(), - userCredentials: TestCredentials.Root - ); + + 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.Streams.Tests/Security/delete_stream_security.cs index ea2299e85..85bec14c8 100644 --- a/test/EventStore.Client.Streams.Tests/Security/delete_stream_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/delete_stream_security.cs @@ -1,12 +1,7 @@ namespace EventStore.Client.Streams.Tests.Security; [Trait("Category", "Security")] -public class delete_stream_security : IClassFixture { - public delete_stream_security(ITestOutputHelper output, SecurityFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - SecurityFixture Fixture { get; } - +public class delete_stream_security(ITestOutputHelper output, SecurityFixture fixture) : EventStoreTests(output, fixture) { [Fact] public async Task delete_of_all_is_never_allowed() { await Assert.ThrowsAsync(() => Fixture.DeleteStream(SecurityFixture.AllStream)); diff --git a/test/EventStore.Client.Streams.Tests/Security/multiple_role_security.cs b/test/EventStore.Client.Streams.Tests/Security/multiple_role_security.cs index c331e4db1..9ac1d775a 100644 --- a/test/EventStore.Client.Streams.Tests/Security/multiple_role_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/multiple_role_security.cs @@ -1,12 +1,7 @@ namespace EventStore.Client.Streams.Tests.Security; [Trait("Category", "Security")] -public class multiple_role_security : IClassFixture { - public multiple_role_security(ITestOutputHelper output, CustomFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - CustomFixture Fixture { get; } - +public class multiple_role_security(ITestOutputHelper output, multiple_role_security.CustomFixture fixture) : EventStoreTests(output, fixture) { [Fact] public async Task multiple_roles_are_handled_correctly() { await Assert.ThrowsAsync(() => Fixture.ReadEvent("usr-stream")); diff --git a/test/EventStore.Client.Streams.Tests/Security/overriden_system_stream_security.cs b/test/EventStore.Client.Streams.Tests/Security/overriden_system_stream_security.cs index 5fbb4deda..795c2bc46 100644 --- a/test/EventStore.Client.Streams.Tests/Security/overriden_system_stream_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/overriden_system_stream_security.cs @@ -1,12 +1,7 @@ namespace EventStore.Client.Streams.Tests.Security; [Trait("Category", "Security")] -public class overriden_system_stream_security : IClassFixture { - public overriden_system_stream_security(ITestOutputHelper output, CustomFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - CustomFixture Fixture { get; } - +public class overriden_system_stream_security(ITestOutputHelper output, overriden_system_stream_security.CustomFixture fixture) : EventStoreTests(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_system_stream_security_for_all.cs b/test/EventStore.Client.Streams.Tests/Security/overriden_system_stream_security_for_all.cs index 6c3c427f7..fcc33c1f0 100644 --- a/test/EventStore.Client.Streams.Tests/Security/overriden_system_stream_security_for_all.cs +++ b/test/EventStore.Client.Streams.Tests/Security/overriden_system_stream_security_for_all.cs @@ -1,12 +1,7 @@ namespace EventStore.Client.Streams.Tests.Security; [Trait("Category", "Security")] -public class overriden_system_stream_security_for_all : IClassFixture { - public overriden_system_stream_security_for_all(ITestOutputHelper output, CustomFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - CustomFixture Fixture { get; } - +public class overriden_system_stream_security_for_all(ITestOutputHelper output, overriden_system_stream_security_for_all.CustomFixture fixture) : EventStoreTests(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_user_stream_security.cs b/test/EventStore.Client.Streams.Tests/Security/overriden_user_stream_security.cs index 1d876089a..708b5a8aa 100644 --- a/test/EventStore.Client.Streams.Tests/Security/overriden_user_stream_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/overriden_user_stream_security.cs @@ -1,11 +1,7 @@ namespace EventStore.Client.Streams.Tests.Security; [Trait("Category", "Security")] -public class overriden_user_stream_security : IClassFixture { - public overriden_user_stream_security(ITestOutputHelper output, CustomFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); - - CustomFixture Fixture { get; } - +public class overriden_user_stream_security(ITestOutputHelper output, overriden_user_stream_security.CustomFixture fixture) : EventStoreTests(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.Streams.Tests/Security/read_all_security.cs index 9df7fecdd..ab510761e 100644 --- a/test/EventStore.Client.Streams.Tests/Security/read_all_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/read_all_security.cs @@ -1,12 +1,7 @@ namespace EventStore.Client.Streams.Tests.Security; [Trait("Category", "Security")] -public class read_all_security : IClassFixture { - public read_all_security(ITestOutputHelper output, SecurityFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - SecurityFixture Fixture { get; } - +public class read_all_security(ITestOutputHelper output, SecurityFixture fixture) : EventStoreTests(output, fixture) { [Fact] public async Task reading_all_with_not_existing_credentials_is_not_authenticated() { await Assert.ThrowsAsync(() => Fixture.ReadAllForward(TestCredentials.TestBadUser)); diff --git a/test/EventStore.Client.Streams.Tests/Security/read_stream_meta_security.cs b/test/EventStore.Client.Streams.Tests/Security/read_stream_meta_security.cs index d73c5a880..0e396080a 100644 --- a/test/EventStore.Client.Streams.Tests/Security/read_stream_meta_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/read_stream_meta_security.cs @@ -1,11 +1,7 @@ namespace EventStore.Client.Streams.Tests.Security; [Trait("Category", "Security")] -public class read_stream_meta_security : IClassFixture { - public read_stream_meta_security(ITestOutputHelper output, SecurityFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); - - SecurityFixture Fixture { get; } - +public class read_stream_meta_security(ITestOutputHelper output, SecurityFixture fixture) : EventStoreTests(output, fixture) { [Fact] public async Task reading_stream_meta_with_not_existing_credentials_is_not_authenticated() => await Assert.ThrowsAsync( diff --git a/test/EventStore.Client.Streams.Tests/Security/read_stream_security.cs b/test/EventStore.Client.Streams.Tests/Security/read_stream_security.cs index 1ccb05311..20b512dc6 100644 --- a/test/EventStore.Client.Streams.Tests/Security/read_stream_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/read_stream_security.cs @@ -1,11 +1,7 @@ namespace EventStore.Client.Streams.Tests.Security; [Trait("Category", "Security")] -public class read_stream_security : IClassFixture { - public read_stream_security(ITestOutputHelper output, SecurityFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); - - SecurityFixture Fixture { get; } - +public class read_stream_security(ITestOutputHelper output, SecurityFixture fixture) : EventStoreTests(output, fixture) { [Fact] public async Task reading_stream_with_not_existing_credentials_is_not_authenticated() { await Assert.ThrowsAsync(() => Fixture.ReadEvent(SecurityFixture.ReadStream, TestCredentials.TestBadUser)); diff --git a/test/EventStore.Client.Streams.Tests/Security/stream_security_inheritance.cs b/test/EventStore.Client.Streams.Tests/Security/stream_security_inheritance.cs index 1b9806b62..729e6b463 100644 --- a/test/EventStore.Client.Streams.Tests/Security/stream_security_inheritance.cs +++ b/test/EventStore.Client.Streams.Tests/Security/stream_security_inheritance.cs @@ -1,11 +1,7 @@ namespace EventStore.Client.Streams.Tests.Security; [Trait("Category", "Security")] -public class stream_security_inheritance : IClassFixture { - public stream_security_inheritance(ITestOutputHelper output, CustomFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); - - CustomFixture Fixture { get; } - +public class stream_security_inheritance(ITestOutputHelper output, stream_security_inheritance.CustomFixture fixture) : EventStoreTests(output, fixture) { [Fact] public async Task acl_inheritance_is_working_properly_on_user_streams() { await Assert.ThrowsAsync(() => Fixture.AppendStream("user-no-acl")); diff --git a/test/EventStore.Client.Streams.Tests/Security/subscribe_to_all_security.cs b/test/EventStore.Client.Streams.Tests/Security/subscribe_to_all_security.cs index 76729b35b..0de1f764a 100644 --- a/test/EventStore.Client.Streams.Tests/Security/subscribe_to_all_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/subscribe_to_all_security.cs @@ -1,11 +1,7 @@ namespace EventStore.Client.Streams.Tests.Security; [Trait("Category", "Security")] -public class subscribe_to_all_security : IClassFixture { - public subscribe_to_all_security(ITestOutputHelper output, SecurityFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); - - SecurityFixture Fixture { get; } - +public class subscribe_to_all_security(ITestOutputHelper output, SecurityFixture fixture) : EventStoreTests(output, fixture) { [Fact] public async Task subscribing_to_all_with_not_existing_credentials_is_not_authenticated() => await Assert.ThrowsAsync(() => Fixture.SubscribeToAll(TestCredentials.TestBadUser)); diff --git a/test/EventStore.Client.Streams.Tests/Security/subscribe_to_stream_security.cs b/test/EventStore.Client.Streams.Tests/Security/subscribe_to_stream_security.cs index 819027bbd..cc08d400d 100644 --- a/test/EventStore.Client.Streams.Tests/Security/subscribe_to_stream_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/subscribe_to_stream_security.cs @@ -1,11 +1,7 @@ namespace EventStore.Client.Streams.Tests.Security; [Trait("Category", "Security")] -public class subscribe_to_stream_security : IClassFixture { - public subscribe_to_stream_security(ITestOutputHelper output, SecurityFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); - - SecurityFixture Fixture { get; } - +public class subscribe_to_stream_security(ITestOutputHelper output, SecurityFixture fixture) : EventStoreTests(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)); diff --git a/test/EventStore.Client.Streams.Tests/Security/system_stream_security.cs b/test/EventStore.Client.Streams.Tests/Security/system_stream_security.cs index 3c86d4749..303711d40 100644 --- a/test/EventStore.Client.Streams.Tests/Security/system_stream_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/system_stream_security.cs @@ -1,11 +1,7 @@ namespace EventStore.Client.Streams.Tests.Security; [Trait("Category", "Security")] -public class system_stream_security : IClassFixture { - public system_stream_security(ITestOutputHelper output, SecurityFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); - - SecurityFixture Fixture { get; } - +public class system_stream_security(ITestOutputHelper output, SecurityFixture 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)); diff --git a/test/EventStore.Client.Streams.Tests/Security/write_stream_meta_security.cs b/test/EventStore.Client.Streams.Tests/Security/write_stream_meta_security.cs index 4c15dfed0..591b5d61e 100644 --- a/test/EventStore.Client.Streams.Tests/Security/write_stream_meta_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/write_stream_meta_security.cs @@ -1,11 +1,7 @@ namespace EventStore.Client.Streams.Tests.Security; [Trait("Category", "Security")] -public class write_stream_meta_security : IClassFixture { - public write_stream_meta_security(ITestOutputHelper output, SecurityFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); - - SecurityFixture Fixture { get; } - +public class write_stream_meta_security(ITestOutputHelper output, SecurityFixture fixture) : EventStoreTests(output, fixture) { [Fact] public async Task writing_meta_with_not_existing_credentials_is_not_authenticated() => await Assert.ThrowsAsync( diff --git a/test/EventStore.Client.Streams.Tests/Security/write_stream_security.cs b/test/EventStore.Client.Streams.Tests/Security/write_stream_security.cs index a979f2c2e..3061b96e7 100644 --- a/test/EventStore.Client.Streams.Tests/Security/write_stream_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/write_stream_security.cs @@ -55,8 +55,7 @@ public async Task writing_to_all_access_normal_stream_succeeds_when_no_credentia await Fixture.AppendStream(SecurityFixture.NormalAllStream); [Fact] - public async Task - writing_to_all_access_normal_stream_is_not_authenticated_when_not_existing_credentials_are_passed() => + public async Task writing_to_all_access_normal_stream_is_not_authenticated_when_not_existing_credentials_are_passed() => await Assert.ThrowsAsync(() => Fixture.AppendStream(SecurityFixture.NormalAllStream, TestCredentials.TestBadUser)); [Fact] diff --git a/test/EventStore.Client.Streams.Tests/StreamMetadata/stream_metadata.cs b/test/EventStore.Client.Streams.Tests/StreamMetadata/stream_metadata.cs index 7815ac4fe..c3f28f330 100644 --- a/test/EventStore.Client.Streams.Tests/StreamMetadata/stream_metadata.cs +++ b/test/EventStore.Client.Streams.Tests/StreamMetadata/stream_metadata.cs @@ -1,15 +1,11 @@ using System.Text.Json; +using Grpc.Core; namespace EventStore.Client.Streams.Tests; [Trait("Category", "LongRunning")] [Trait("Category", "StreamMetadata")] -public class stream_metadata : IClassFixture { - public stream_metadata(ITestOutputHelper output, EventStoreFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - EventStoreFixture Fixture { get; } - +public class stream_metadata(ITestOutputHelper output, EventStoreFixture fixture) : EventStoreTests(output, fixture) { [Fact] public async Task getting_for_an_existing_stream_and_no_metadata_exists() { var stream = Fixture.GetStreamName(); @@ -155,4 +151,45 @@ 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(); + var rpcException = await Assert.ThrowsAsync( + () => + Fixture.Streams.SetStreamMetadataAsync( + stream, + StreamState.Any, + new(), + deadline: TimeSpan.Zero + ) + ); + + Assert.Equal(StatusCode.DeadlineExceeded, rpcException.StatusCode); + } + + [Fact] + public async Task with_timeout_set_with_stream_revision_fails_when_operation_expired() { + var stream = Fixture.GetStreamName(); + + var rpcException = await Assert.ThrowsAsync( + () => + Fixture.Streams.SetStreamMetadataAsync( + stream, + new StreamRevision(0), + new(), + deadline: TimeSpan.Zero + ) + ); + + Assert.Equal(StatusCode.DeadlineExceeded, rpcException.StatusCode); + } + + [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) + ); + } } \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/StreamMetadata/stream_metadata_with_timeout.cs b/test/EventStore.Client.Streams.Tests/StreamMetadata/stream_metadata_with_timeout.cs deleted file mode 100644 index faf66d61b..000000000 --- a/test/EventStore.Client.Streams.Tests/StreamMetadata/stream_metadata_with_timeout.cs +++ /dev/null @@ -1,54 +0,0 @@ -using Grpc.Core; - -namespace EventStore.Client.Streams.Tests; - -[Trait("Category", "Network")] -[Trait("Category", "StreamMetadata")] -public class stream_metadata_with_timeout : IClassFixture { - public stream_metadata_with_timeout(ITestOutputHelper output, EventStoreFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - EventStoreFixture Fixture { get; } - - [Fact] - public async Task set_with_any_stream_revision_fails_when_operation_expired() { - var stream = Fixture.GetStreamName(); - var rpcException = await Assert.ThrowsAsync( - () => - Fixture.Streams.SetStreamMetadataAsync( - stream, - StreamState.Any, - new(), - deadline: TimeSpan.Zero - ) - ); - - Assert.Equal(StatusCode.DeadlineExceeded, rpcException.StatusCode); - } - - [Fact] - public async Task set_with_stream_revision_fails_when_operation_expired() { - var stream = Fixture.GetStreamName(); - - var rpcException = await Assert.ThrowsAsync( - () => - Fixture.Streams.SetStreamMetadataAsync( - stream, - new StreamRevision(0), - new(), - deadline: TimeSpan.Zero - ) - ); - - Assert.Equal(StatusCode.DeadlineExceeded, rpcException.StatusCode); - } - - [Fact] - public async Task get_fails_when_operation_expired() { - 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/FilterTestCase.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/FilterTestCase.cs deleted file mode 100644 index 1e0381587..000000000 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/FilterTestCase.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System.Reflection; - -namespace EventStore.Client.Streams.Tests; - -public static class Filters { - const string StreamNamePrefix = nameof(StreamNamePrefix); - const string StreamNameRegex = nameof(StreamNameRegex); - const string EventTypePrefix = nameof(EventTypePrefix); - const string EventTypeRegex = nameof(EventTypeRegex); - - static readonly SubscriptionFilter StreamNamePrefixSubscriptionFilter = new(StreamNamePrefix, StreamFilter.Prefix, (_, evt) => evt); - static readonly SubscriptionFilter StreamNameRegexSubscriptionFilter = new(StreamNameRegex, f => StreamFilter.RegularExpression(f), (_, evt) => evt); - static readonly SubscriptionFilter EventTypePrefixSubscriptionFilter = new(EventTypePrefix, EventTypeFilter.Prefix, (term, evt) => new(evt.EventId, term, evt.Data, evt.Metadata, evt.ContentType)); - static readonly SubscriptionFilter EventTypeRegexSubscriptionFilter = new(EventTypeRegex, f => EventTypeFilter.RegularExpression(f), (term, evt) => new(evt.EventId, term, evt.Data, evt.Metadata, evt.ContentType)); - - static Filters() { - EventFilters = new Dictionary { - [StreamNamePrefix] = new(StreamNamePrefix, StreamFilter.Prefix, (_, evt) => evt), - [StreamNameRegex] = new(StreamNameRegex, f => StreamFilter.RegularExpression(f), (_, evt) => evt), - [EventTypePrefix] = new(EventTypePrefix, EventTypeFilter.Prefix, (term, evt) => new(evt.EventId, term, evt.Data, evt.Metadata, evt.ContentType)), - [EventTypeRegex] = new(EventTypeRegex, f => EventTypeFilter.RegularExpression(f), (term, evt) => new(evt.EventId, term, evt.Data, evt.Metadata, evt.ContentType)) - }; - - TestCases = EventFilters.Select(x => new object[] { x.Value }); - } - - public static IDictionary EventFilters { get; } - public static IEnumerable TestCases { get; } - - public static readonly IEnumerable All = typeof(Filters) - .GetFields(BindingFlags.NonPublic | BindingFlags.Static) - .Where(fi => fi.IsLiteral && !fi.IsInitOnly) - .Select(fi => (string)fi.GetRawConstantValue()!); - - public static (Func GetFilter, Func PrepareEvent) GetFilterDefinition(string name) { - var result = EventFilters[name]; - return (result.Create, result.PrepareEvent); - } -} \ 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 index 6a5030b5a..0c969f079 100644 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionsFixture.cs +++ b/test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionsFixture.cs @@ -1,5 +1,7 @@ namespace EventStore.Client.Streams.Tests; +[Trait("Category", "LongRunning")] +[Trait("Category", "Subscriptions")] public class SubscriptionsFixture : EventStoreFixture { public SubscriptionsFixture(): base(x => x.RunProjections()) { OnSetup = async () => { diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/reconnection.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/reconnection.cs index 175e85457..e532135f3 100644 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/reconnection.cs +++ b/test/EventStore.Client.Streams.Tests/Subscriptions/reconnection.cs @@ -4,11 +4,7 @@ namespace EventStore.Client.Streams.Tests; [Trait("Category", "Subscriptions")] -public class @reconnection : IClassFixture { - public reconnection(ITestOutputHelper output, ReconnectionFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); - - ReconnectionFixture Fixture { get; } - +public class @reconnection(ITestOutputHelper output, ReconnectionFixture fixture) : EventStoreTests(output, fixture) { [Theory] [InlineData(4, 1000, 0, 15000)] public async Task when_the_connection_is_lost(int expectedNumberOfEvents, int reconnectDelayMs, int serviceRestartDelayMs, int testTimeoutMs) { @@ -45,8 +41,8 @@ public class ReconnectionFixture() 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 { diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all.cs index 650dcd78d..3bf58469f 100644 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all.cs +++ b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all.cs @@ -1,12 +1,7 @@ namespace EventStore.Client.Streams.Tests; -[Trait("Category", "Subscriptions")] [Trait("Category", "AllStream")] -public class subscribe_to_all : IClassFixture { - public subscribe_to_all(ITestOutputHelper output, SubscriptionsFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); - - SubscriptionsFixture Fixture { get; } - +public class subscribe_to_all(ITestOutputHelper output, SubscriptionsFixture fixture) : EventStoreTests(output, fixture) { [Fact] public async Task receives_all_events_from_start() { var receivedAllEvents = new TaskCompletionSource(); @@ -590,7 +585,6 @@ public async Task drops_when_subscriber_error() { await Fixture.Streams.AppendToStreamAsync(Fixture.GetStreamName(), StreamState.NoStream, Fixture.CreateTestEvents()); var result = await subscriptionDropped.Task.WithTimeout(); - result.ShouldBe(expectedResult); } } \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream.cs index 799b23bbf..034bf111c 100644 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream.cs +++ b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream.cs @@ -1,490 +1,254 @@ namespace EventStore.Client.Streams.Tests; -[Trait("Category", "LongRunning")] -[Trait("Category", "Subscriptions")] [Trait("Category", "Stream")] -public class subscribe_to_stream : IClassFixture { - public subscribe_to_stream(ITestOutputHelper output, SubscriptionsFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); - - SubscriptionsFixture Fixture { get; } - +public class subscribe_to_stream (ITestOutputHelper output, SubscriptionsFixture fixture) : EventStoreTests(output, fixture) { [Fact] - public async Task subscribe_to_non_existing_stream() { - var stream = Fixture.GetStreamName(); - var appeared = new TaskCompletionSource(); - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - - using var subscription = await Fixture.Streams - .SubscribeToStreamAsync( - stream, - FromStream.Start, - EventAppeared, - false, - SubscriptionDropped - ) - .WithTimeout(); - - Assert.False(appeared.Task.IsCompleted); - - if (dropped.Task.IsCompleted) - Assert.False(dropped.Task.IsCompleted, dropped.Task.Result.ToString()); - - subscription.Dispose(); - - var (reason, ex) = await dropped.Task.WithTimeout(); - Assert.Equal(SubscriptionDroppedReason.Disposed, reason); - Assert.Null(ex); - - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) { - appeared.TrySetResult(true); - return Task.CompletedTask; - } + public async Task receives_all_events_from_start() { + var streamName = Fixture.GetStreamName(); - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => - dropped.SetResult((reason, ex)); - } + var receivedAllEvents = new TaskCompletionSource(); + var subscriptionDropped = new TaskCompletionSource(); - [Fact] - public async Task subscribe_to_non_existing_stream_then_get_event() { - var stream = Fixture.GetStreamName(); - var appeared = new TaskCompletionSource(); - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); + 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( - stream, - FromStream.Start, - EventAppeared, - false, - SubscriptionDropped - ) + .SubscribeToStreamAsync(streamName, FromStream.Start, OnReceived, false, OnDropped) .WithTimeout(); + + await Fixture.Streams.AppendToStreamAsync(streamName, StreamState.StreamExists, seedEvents.Skip(pageSize)); - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents()); - - Assert.True(await appeared.Task.WithTimeout()); + await receivedAllEvents.Task.WithTimeout(); - if (dropped.Task.IsCompleted) - Assert.False(dropped.Task.IsCompleted, dropped.Task.Result.ToString()); + // 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; - var (reason, ex) = await dropped.Task.WithTimeout(); - Assert.Equal(SubscriptionDroppedReason.Disposed, reason); - Assert.Null(ex); - - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) { - appeared.TrySetResult(true); + 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 SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => - dropped.SetResult((reason, ex)); - } - - [Fact] - public async Task allow_multiple_subscriptions_to_same_stream() { - var stream = Fixture.GetStreamName(); - - var appeared = new TaskCompletionSource(); - - var appearedCount = 0; - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents()); - using var s1 = await Fixture.Streams - .SubscribeToStreamAsync(stream, FromStream.Start, EventAppeared).WithTimeout(); - - using var s2 = await Fixture.Streams - .SubscribeToStreamAsync(stream, FromStream.Start, EventAppeared).WithTimeout(); - - Assert.True(await appeared.Task.WithTimeout()); - - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) { - if (++appearedCount == 2) - appeared.TrySetResult(true); - - return Task.CompletedTask; - } + void OnDropped(StreamSubscription sub, SubscriptionDroppedReason reason, Exception? ex) => + subscriptionDropped.SetResult(new(reason, ex)); } - + [Fact] - public async Task calls_subscription_dropped_when_disposed() { - var stream = Fixture.GetStreamName(); - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - - using var subscription = await Fixture.Streams - .SubscribeToStreamAsync( - stream, - FromStream.Start, - EventAppeared, - false, - SubscriptionDropped - ) - .WithTimeout(); - - if (dropped.Task.IsCompleted) - Assert.False(dropped.Task.IsCompleted, dropped.Task.Result.ToString()); - - subscription.Dispose(); - - var (reason, ex) = await dropped.Task.WithTimeout(); - - Assert.Equal(SubscriptionDroppedReason.Disposed, reason); - Assert.Null(ex); - - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) => Task.CompletedTask; - - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => - dropped.SetResult((reason, ex)); - } + public async Task receives_all_events_from_position() { + var streamName = Fixture.GetStreamName(); + + var receivedAllEvents = new TaskCompletionSource(); + var subscriptionDropped = new TaskCompletionSource(); - [Fact] - public async Task calls_subscription_dropped_when_error_processing_event() { - var stream = Fixture.GetStreamName(); - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - var expectedException = new Exception("Error"); + 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( - stream, - FromStream.Start, - EventAppeared, - false, - SubscriptionDropped - ) + .SubscribeToStreamAsync(streamName, checkpoint, OnReceived, false, OnDropped) .WithTimeout(); - if (dropped.Task.IsCompleted) - Assert.False(dropped.Task.IsCompleted, dropped.Task.Result.ToString()); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents()); - - var (reason, ex) = await dropped.Task.WithTimeout(); - - Assert.Equal(SubscriptionDroppedReason.SubscriberError, reason); - Assert.Same(expectedException, ex); - - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) => - Task.FromException(expectedException); - - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => - dropped.SetResult((reason, ex)); - } - - [Fact] - public async Task reads_all_existing_events_and_keep_listening_to_new_ones() { - var stream = Fixture.GetStreamName(); - - var events = Fixture.CreateTestEvents(20).ToArray(); - - var appeared = new TaskCompletionSource(); - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - - var beforeEvents = events.Take(10); - var afterEvents = events.Skip(10); + await Fixture.Streams.AppendToStreamAsync(streamName, writeResult.NextExpectedStreamRevision, seedEvents.Skip(pageSize)); - using var enumerator = events.AsEnumerable().GetEnumerator(); - - enumerator.MoveNext(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, beforeEvents) - .WithTimeout(); - - using var subscription = await Fixture.Streams - .SubscribeToStreamAsync( - stream, - FromStream.Start, - EventAppeared, - false, - SubscriptionDropped - ) - .WithTimeout(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, afterEvents) - .WithTimeout(); + await receivedAllEvents.Task.WithTimeout(); - await appeared.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; - var (reason, ex) = await dropped.Task.WithTimeout(); - - Assert.Equal(SubscriptionDroppedReason.Disposed, reason); - Assert.Null(ex); - - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) { - try { - Assert.Equal(enumerator.Current.EventId, e.OriginalEvent.EventId); - if (!enumerator.MoveNext()) - appeared.TrySetResult(true); - } - catch (Exception ex) { - appeared.TrySetException(ex); - throw; + 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 SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => - dropped.SetResult((reason, ex)); + void OnDropped(StreamSubscription sub, SubscriptionDroppedReason reason, Exception? ex) => + subscriptionDropped.SetResult(new(reason, ex)); } - + [Fact] - public async Task catches_deletions() { - var stream = Fixture.GetStreamName(); - - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - - using var _ = await Fixture.Streams - .SubscribeToStreamAsync( - stream, - FromStream.Start, - EventAppeared, - false, - SubscriptionDropped - ) - .WithTimeout(); - - await Fixture.Streams.TombstoneAsync(stream, StreamState.NoStream); - var (reason, ex) = await dropped.Task.WithTimeout(); - - Assert.Equal(SubscriptionDroppedReason.ServerError, reason); - var sdex = Assert.IsType(ex); - Assert.Equal(stream, sdex.Stream); - - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) => Task.CompletedTask; - - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => - dropped.SetResult((reason, ex)); - } + public async Task receives_all_events_from_non_existing_stream() { + var streamName = Fixture.GetStreamName(); - [Fact] - public async Task with_revision_subscribe_to_non_existing_stream() { - var stream = Fixture.GetStreamName(); - var appeared = new TaskCompletionSource(); - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); + 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( - stream, - FromStream.Start, - EventAppeared, - false, - SubscriptionDropped - ) + .SubscribeToStreamAsync(streamName, FromStream.Start, OnReceived, false, OnDropped) .WithTimeout(); + + await Fixture.Streams.AppendToStreamAsync(streamName, StreamState.NoStream, seedEvents); - Assert.False(appeared.Task.IsCompleted); + await receivedAllEvents.Task.WithTimeout(); - if (dropped.Task.IsCompleted) - Assert.False(dropped.Task.IsCompleted, dropped.Task.Result.ToString()); + // 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; - var (reason, ex) = await dropped.Task.WithTimeout(); - Assert.Equal(SubscriptionDroppedReason.Disposed, reason); - Assert.Null(ex); - - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) { - appeared.TrySetResult(true); + 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 SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); + void OnDropped(StreamSubscription sub, SubscriptionDroppedReason reason, Exception? ex) => + subscriptionDropped.SetResult(new(reason, ex)); } [Fact] - public async Task with_revision_subscribe_to_non_existing_stream_then_get_event() { - var stream = Fixture.GetStreamName(); - var appeared = new TaskCompletionSource(); - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - - using var subscription = await Fixture.Streams - .SubscribeToStreamAsync( - stream, - FromStream.After(StreamPosition.Start), - EventAppeared, - false, - SubscriptionDropped - ) - .WithTimeout(); - - await Fixture.Streams.AppendToStreamAsync( - stream, - StreamState.NoStream, - Fixture.CreateTestEvents(2) - ); - - Assert.True(await appeared.Task.WithTimeout()); - - if (dropped.Task.IsCompleted) - Assert.False(dropped.Task.IsCompleted, dropped.Task.Result.ToString()); - - subscription.Dispose(); - - var (reason, ex) = await dropped.Task.WithTimeout(); - Assert.Equal(SubscriptionDroppedReason.Disposed, reason); - Assert.Null(ex); - - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) { - if (e.OriginalEvent.EventNumber == StreamPosition.Start) - appeared.TrySetException(new Exception()); - else - appeared.TrySetResult(true); - - return Task.CompletedTask; - } - - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); - } + public async Task allow_multiple_subscriptions_to_same_stream() { + var streamName = Fixture.GetStreamName(); - [Fact] - public async Task with_revision_allow_multiple_subscriptions_to_same_stream() { - var stream = Fixture.GetStreamName(); + var receivedAllEvents = new TaskCompletionSource(); - var appeared = new TaskCompletionSource(); + var seedEvents = Fixture.CreateTestEvents(5).ToArray(); - var appearedCount = 0; + var targetEventsCount = seedEvents.Length*2; - using var s1 = await Fixture.Streams - .SubscribeToStreamAsync(stream, FromStream.After(StreamPosition.Start), EventAppeared) + await Fixture.Streams.AppendToStreamAsync(streamName, StreamState.NoStream, seedEvents); + + using var subscription1 = await Fixture.Streams + .SubscribeToStreamAsync(streamName, FromStream.Start, OnReceived) .WithTimeout(); - using var s2 = await Fixture.Streams - .SubscribeToStreamAsync(stream, FromStream.After(StreamPosition.Start), EventAppeared) + using var subscription2 = await Fixture.Streams + .SubscribeToStreamAsync(streamName, FromStream.Start, OnReceived) .WithTimeout(); + + await receivedAllEvents.Task.WithTimeout(); - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents(2)); - - Assert.True(await appeared.Task.WithTimeout()); - - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) { - if (e.OriginalEvent.EventNumber == StreamPosition.Start) { - appeared.TrySetException(new Exception()); - return Task.CompletedTask; + Task OnReceived(StreamSubscription sub, ResolvedEvent re, CancellationToken ct) { + if (--targetEventsCount == 0) { + receivedAllEvents.TrySetResult(true); + Fixture.Log.Information("Received all {TotalEventsCount} expected events", seedEvents.Length); } - if (++appearedCount == 2) - appeared.TrySetResult(true); - return Task.CompletedTask; } } [Fact] - public async Task with_revision_calls_subscription_dropped_when_disposed() { - var stream = Fixture.GetStreamName(); - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - + public async Task drops_when_disposed() { + var streamName = Fixture.GetStreamName(); + + var subscriptionDropped = new TaskCompletionSource(); + using var subscription = await Fixture.Streams .SubscribeToStreamAsync( - stream, + streamName, FromStream.Start, - EventAppeared, + (sub, re, ct) => Task.CompletedTask, false, - SubscriptionDropped + (sub, reason, ex) => subscriptionDropped.SetResult(new(reason, ex)) ) .WithTimeout(); - if (dropped.Task.IsCompleted) - Assert.False(dropped.Task.IsCompleted, dropped.Task.Result.ToString()); - + // 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 (reason, ex) = await dropped.Task.WithTimeout(); - - Assert.Equal(SubscriptionDroppedReason.Disposed, reason); - Assert.Null(ex); - - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) => Task.CompletedTask; - - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); + var result = await subscriptionDropped.Task.WithTimeout(); + result.ShouldBe(SubscriptionDroppedResult.Disposed()); } [Fact] - public async Task with_revision_calls_subscription_dropped_when_error_processing_event() { - var stream = Fixture.GetStreamName(); - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - var expectedException = new Exception("Error"); + public async Task drops_when_subscriber_error() { + var streamName = Fixture.GetStreamName(); + + var expectedResult = SubscriptionDroppedResult.SubscriberError(); - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents(2)); + var subscriptionDropped = new TaskCompletionSource(); - using var subscription = await Fixture.Streams.SubscribeToStreamAsync( - stream, + using var subscription = await Fixture.Streams + .SubscribeToStreamAsync( + streamName, FromStream.Start, - EventAppeared, + (sub, re, ct) => expectedResult.Throw(), false, - SubscriptionDropped + (sub, reason, ex) => subscriptionDropped.SetResult(new(reason, ex)) ) .WithTimeout(); - var (reason, ex) = await dropped.Task.WithTimeout(); - - Assert.Equal(SubscriptionDroppedReason.SubscriberError, reason); - Assert.Same(expectedException, ex); + await Fixture.Streams.AppendToStreamAsync(streamName, StreamState.NoStream, Fixture.CreateTestEvents()); - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) => Task.FromException(expectedException); - - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); + var result = await subscriptionDropped.Task.WithTimeout(); + result.ShouldBe(expectedResult); } [Fact] - public async Task with_revision_reads_all_existing_events_and_keep_listening_to_new_ones() { - var stream = Fixture.GetStreamName(); - - var events = Fixture.CreateTestEvents(20).ToArray(); - - var appeared = new TaskCompletionSource(); - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - - var beforeEvents = events.Take(10); - var afterEvents = events.Skip(10); - - using var enumerator = events.AsEnumerable().GetEnumerator(); - - enumerator.MoveNext(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents()); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, beforeEvents); - + public async Task drops_when_stream_tombstoned() { + var streamName = Fixture.GetStreamName(); + + var subscriptionDropped = new TaskCompletionSource(); + using var subscription = await Fixture.Streams .SubscribeToStreamAsync( - stream, - FromStream.After(StreamPosition.Start), - EventAppeared, + streamName, + FromStream.Start, + (sub, re, ct) => Task.CompletedTask, false, - SubscriptionDropped + (sub, reason, ex) => { subscriptionDropped.SetResult(new(reason, ex)); } ) .WithTimeout(); - var writeResult = await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, afterEvents); - - await appeared.Task.WithTimeout(); - - subscription.Dispose(); - - var (reason, ex) = await dropped.Task.WithTimeout(); - - Assert.Equal(SubscriptionDroppedReason.Disposed, reason); - Assert.Null(ex); + // rest in peace + await Fixture.Streams.TombstoneAsync(streamName, StreamState.NoStream); - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) { - try { - Assert.Equal(enumerator.Current.EventId, e.OriginalEvent.EventId); - if (!enumerator.MoveNext()) - appeared.TrySetResult(true); - } - catch (Exception ex) { - appeared.TrySetException(ex); - throw; - } - - return Task.CompletedTask; - } - - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); + var result = await subscriptionDropped.Task.WithTimeout(); + result.Error.ShouldBeOfType().Stream.ShouldBe(streamName); } [Fact] @@ -534,153 +298,4 @@ Task OnReceived(StreamSubscription sub, ResolvedEvent re, CancellationToken ct) void OnDropped(StreamSubscription sub, SubscriptionDroppedReason reason, Exception? ex) => subscriptionDropped.SetResult(new(reason, ex)); } - - [Fact] - public async Task live_does_not_read_existing_events_but_keep_listening_to_new_ones() { - var stream = Fixture.GetStreamName(); - var appeared = new TaskCompletionSource(); - var dropped = new TaskCompletionSource(); - - await Fixture.Streams.AppendToStreamAsync( - stream, - StreamState.NoStream, - Fixture.CreateTestEvents() - ); - - using var _ = await Fixture.Streams - .SubscribeToStreamAsync( - stream, - FromStream.End, - (_, e, _) => { - appeared.TrySetResult(e.OriginalEventNumber); - return Task.CompletedTask; - }, - false, - (s, reason, ex) => dropped.TrySetResult(true) - ) - .WithTimeout(); - - await Fixture.Streams.AppendToStreamAsync( - stream, - new StreamRevision(0), - Fixture.CreateTestEvents() - ); - - Assert.Equal(new(1), await appeared.Task.WithTimeout()); - } - - [Fact] - public async Task live_subscribe_to_non_existing_stream_and_then_catch_new_event() { - var stream = Fixture.GetStreamName(); - var appeared = new TaskCompletionSource(); - var dropped = new TaskCompletionSource(); - - using var _ = await Fixture.Streams - .SubscribeToStreamAsync( - stream, - FromStream.End, - (_, _, _) => { - appeared.TrySetResult(true); - return Task.CompletedTask; - }, - false, - (s, reason, ex) => dropped.TrySetResult(true) - ) - .WithTimeout(); - - await Fixture.Streams.AppendToStreamAsync( - stream, - StreamState.NoStream, - Fixture.CreateTestEvents() - ); - - Assert.True(await appeared.Task.WithTimeout()); - } - - [Fact] - public async Task live_allow_multiple_subscriptions_to_same_stream() { - var stream = Fixture.GetStreamName(); - - var appeared = new TaskCompletionSource(); - - var appearedCount = 0; - - using var s1 = await Fixture.Streams - .SubscribeToStreamAsync(stream, FromStream.End, EventAppeared) - .WithTimeout(); - - using var s2 = await Fixture.Streams - .SubscribeToStreamAsync(stream, FromStream.End, EventAppeared) - .WithTimeout(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents()); - - Assert.True(await appeared.Task.WithTimeout()); - - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) { - if (++appearedCount == 2) - appeared.TrySetResult(true); - - return Task.CompletedTask; - } - } - - [Fact] - public async Task live_calls_subscription_dropped_when_disposed() { - var stream = Fixture.GetStreamName(); - - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - - using var _ = await Fixture.Streams - .SubscribeToStreamAsync( - stream, - FromStream.End, - EventAppeared, - false, - SubscriptionDropped - ) - .WithTimeout(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents()); - - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) { - s.Dispose(); - return Task.CompletedTask; - } - - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); - - var (reason, ex) = await dropped.Task.WithTimeout(); - - Assert.Null(ex); - Assert.Equal(SubscriptionDroppedReason.Disposed, reason); - } - - [Fact] - public async Task live_catches_deletions() { - var stream = Fixture.GetStreamName(); - - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - - using var _ = await Fixture.Streams - .SubscribeToStreamAsync( - stream, - FromStream.End, - EventAppeared, - false, - SubscriptionDropped - ) - .WithTimeout(); - - await Fixture.Streams.TombstoneAsync(stream, StreamState.NoStream); - var (reason, ex) = await dropped.Task.WithTimeout(); - - Assert.Equal(SubscriptionDroppedReason.ServerError, reason); - var sdex = Assert.IsType(ex); - Assert.Equal(stream, sdex.Stream); - - Task EventAppeared(StreamSubscription s, ResolvedEvent e, CancellationToken ct) => Task.CompletedTask; - - void SubscriptionDropped(StreamSubscription s, SubscriptionDroppedReason reason, Exception? ex) => dropped.SetResult((reason, ex)); - } } \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/TestEventExtensions.cs b/test/EventStore.Client.Streams.Tests/TestEventExtensions.cs index 1dfa8f298..be6269d4d 100644 --- a/test/EventStore.Client.Streams.Tests/TestEventExtensions.cs +++ b/test/EventStore.Client.Streams.Tests/TestEventExtensions.cs @@ -1,10 +1,10 @@ -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests; public static class TestEventExtensions { public static IEnumerable AsResolvedTestEvents(this IEnumerable events) { if (events == null) throw new ArgumentNullException(nameof(events)); - return events.Where(x => x.Event.EventType == EventStoreClientFixtureBase.TestEventType).Select(x => x.Event); + return events.Where(x => x.Event.EventType == EventStoreFixture.TestEventType).Select(x => x.Event); } } \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/is_json.cs b/test/EventStore.Client.Streams.Tests/is_json.cs index 53eb73762..d9d8b3828 100644 --- a/test/EventStore.Client.Streams.Tests/is_json.cs +++ b/test/EventStore.Client.Streams.Tests/is_json.cs @@ -4,13 +4,8 @@ namespace EventStore.Client.Streams.Tests; [Trait("Category", "Network")] -[LongRunning] -public class is_json : IClassFixture { - public is_json(ITestOutputHelper output, EventStoreFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - EventStoreFixture Fixture { get; } - +[Trait("Category", "LongRunning")] +public class is_json(ITestOutputHelper output, EventStoreFixture fixture) : EventStoreTests(output, fixture) { public static IEnumerable TestCases() { var json = @"{""some"":""json""}"; diff --git a/test/EventStore.Client.Tests.Common/Extensions/TaskExtensions.cs b/test/EventStore.Client.Tests.Common/Extensions/TaskExtensions.cs index 5404ad684..b02d5ef2a 100644 --- a/test/EventStore.Client.Tests.Common/Extensions/TaskExtensions.cs +++ b/test/EventStore.Client.Tests.Common/Extensions/TaskExtensions.cs @@ -6,7 +6,7 @@ public static class TaskExtensions { public static Task WithTimeout(this Task task, TimeSpan timeout) => task.WithTimeout(Convert.ToInt32(timeout.TotalMilliseconds)); - public static async Task WithTimeout(this Task task, int timeoutMs = 10000, string? message = null) { + public static async Task WithTimeout(this Task task, int timeoutMs = 15000, string? message = null) { if (Debugger.IsAttached) timeoutMs = -1; if (await Task.WhenAny(task, Task.Delay(timeoutMs)) != task) @@ -18,7 +18,7 @@ public static async Task WithTimeout(this Task task, int timeoutMs = 10000, stri public static Task WithTimeout(this Task task, TimeSpan timeout) => task.WithTimeout(Convert.ToInt32(timeout.TotalMilliseconds)); - public static async Task WithTimeout(this Task task, int timeoutMs = 10000, string? message = null) { + public static async Task WithTimeout(this Task task, int timeoutMs = 15000, string? message = null) { if (Debugger.IsAttached) timeoutMs = -1; if (await Task.WhenAny(task, Task.Delay(timeoutMs)) == task) diff --git a/test/EventStore.Client.Tests.Common/Fixtures/EventStoreFixture.cs b/test/EventStore.Client.Tests.Common/Fixtures/EventStoreFixture.cs index a59125751..e59e7149d 100644 --- a/test/EventStore.Client.Tests.Common/Fixtures/EventStoreFixture.cs +++ b/test/EventStore.Client.Tests.Common/Fixtures/EventStoreFixture.cs @@ -188,4 +188,21 @@ public async Task DisposeAsync() { } async ValueTask IAsyncDisposable.DisposeAsync() => await DisposeAsync(); -} \ No newline at end of file +} + +[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 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; \ 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 new file mode 100644 index 000000000..9dcda959a --- /dev/null +++ b/test/EventStore.Client.Tests.Common/Shouldly/ShouldThrowAsyncExtensions.cs @@ -0,0 +1,13 @@ +using System.Diagnostics; +using EventStore.Client; + +namespace Shouldly; + +[DebuggerStepThrough] +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/XUnit/Categories.cs b/test/EventStore.Client.Tests.Common/XUnit/Categories.cs deleted file mode 100644 index 36068cb6b..000000000 --- a/test/EventStore.Client.Tests.Common/XUnit/Categories.cs +++ /dev/null @@ -1,49 +0,0 @@ -// ReSharper disable CheckNamespace - -using Xunit.Sdk; - -namespace Xunit.Categories; - -class TraitDiscoverer { - internal const string AssemblyName = "Xunit.Categories"; -} - -[PublicAPI] -[TraitDiscoverer(DedicatedDatabaseDiscoverer.DiscovererTypeName, TraitDiscoverer.AssemblyName)] -[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)] -public class DedicatedDatabaseAttribute : Attribute, ITraitAttribute { - public class DedicatedDatabaseDiscoverer : ITraitDiscoverer { - internal const string DiscovererTypeName = $"{TraitDiscoverer.AssemblyName}.{nameof(DedicatedDatabaseAttribute)}{nameof(DedicatedDatabaseDiscoverer)}"; - - public IEnumerable> GetTraits(IAttributeInfo traitAttribute) { - yield return new("Category", "DedicatedDatabase"); - } - } -} - -[PublicAPI] -[TraitDiscoverer(LongRunningDiscoverer.DiscovererTypeName, TraitDiscoverer.AssemblyName)] -[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)] -public class LongRunningAttribute : Attribute, ITraitAttribute { - public class LongRunningDiscoverer : ITraitDiscoverer { - internal const string DiscovererTypeName = $"{TraitDiscoverer.AssemblyName}.{nameof(LongRunningAttribute)}{nameof(LongRunningDiscoverer)}"; - - public IEnumerable> GetTraits(IAttributeInfo traitAttribute) { - yield return new("Category", "LongRunning"); - } - } -} - -[PublicAPI] -[TraitDiscoverer(NetworkDiscoverer.DiscovererTypeName, TraitDiscoverer.AssemblyName)] -[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)] -public class NetworkAttribute : Attribute, ITraitAttribute { - public class NetworkDiscoverer : ITraitDiscoverer { - internal const string DiscovererTypeName = $"{TraitDiscoverer.AssemblyName}.{nameof(NetworkAttribute)}{nameof(NetworkDiscoverer)}"; - - public IEnumerable> GetTraits(IAttributeInfo traitAttribute) { - yield return new("Category", "Network"); - } - } -} - From 9085fd717c5acf73588b027f76920028c48d60be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Silveira?= Date: Thu, 7 Dec 2023 16:48:26 +0100 Subject: [PATCH 12/22] modified the secure-with-tls sample connstring --- samples/secure-with-tls/Program.cs | 2 +- .../secure-with-tls/docker-compose.app.yml | 2 +- .../Subscriptions/subscribe_to_stream.cs | 78 +++++++++---------- .../Fixtures/EventStoreTestNode.cs | 1 - 4 files changed, 41 insertions(+), 42 deletions(-) diff --git a/samples/secure-with-tls/Program.cs b/samples/secure-with-tls/Program.cs index 0b17cc9f4..621ee46b1 100644 --- a/samples/secure-with-tls/Program.cs +++ b/samples/secure-with-tls/Program.cs @@ -2,7 +2,7 @@ // take the address from environment variable (when run with Docker) or use localhost by default var connectionString = Environment.GetEnvironmentVariable("ESDB__CONNECTION__STRING") - ?? "esdb://admin:changeit@localhost:2113?tls=true"; + ?? "esdb://admin:changeit@localhost:2113?tls=true&tlsVerifyCert=false"; Console.WriteLine($"Connecting to EventStoreDB at: {connectionString}"); diff --git a/samples/secure-with-tls/docker-compose.app.yml b/samples/secure-with-tls/docker-compose.app.yml index 34fbfa433..b96f84ae8 100644 --- a/samples/secure-with-tls/docker-compose.app.yml +++ b/samples/secure-with-tls/docker-compose.app.yml @@ -11,7 +11,7 @@ services: build: ./ environment: # URL should match the DNS name in certificate and container name - - ESDB__CONNECTION__STRING=esdb://admin:changeit@eventstore:2113?Tls=true + - ESDB__CONNECTION__STRING=esdb://admin:changeit@eventstore:2113?Tls=true&tlsVerifyCert=false depends_on: eventstore: condition: service_healthy diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream.cs index 034bf111c..9edced793 100644 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream.cs +++ b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream.cs @@ -1,7 +1,7 @@ namespace EventStore.Client.Streams.Tests; [Trait("Category", "Stream")] -public class subscribe_to_stream (ITestOutputHelper output, SubscriptionsFixture fixture) : EventStoreTests(output, fixture) { +public class subscribe_to_stream(ITestOutputHelper output, SubscriptionsFixture fixture) : EventStoreTests(output, fixture) { [Fact] public async Task receives_all_events_from_start() { var streamName = Fixture.GetStreamName(); @@ -11,15 +11,15 @@ 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)); - + 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(); @@ -32,41 +32,41 @@ public async Task receives_all_events_from_start() { 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(); @@ -83,24 +83,24 @@ public async Task receives_all_events_from_position() { 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(); @@ -109,13 +109,13 @@ public async Task receives_all_events_from_non_existing_stream() { 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(); @@ -128,17 +128,17 @@ public async Task receives_all_events_from_non_existing_stream() { 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; } @@ -154,10 +154,10 @@ public async Task allow_multiple_subscriptions_to_same_stream() { var seedEvents = Fixture.CreateTestEvents(5).ToArray(); - var targetEventsCount = seedEvents.Length*2; + 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(); @@ -165,12 +165,12 @@ public async Task allow_multiple_subscriptions_to_same_stream() { 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); + receivedAllEvents.TrySetResult(true); Fixture.Log.Information("Received all {TotalEventsCount} expected events", seedEvents.Length); } @@ -180,10 +180,10 @@ Task OnReceived(StreamSubscription sub, ResolvedEvent re, CancellationToken ct) [Fact] public async Task drops_when_disposed() { - var streamName = Fixture.GetStreamName(); - + var streamName = Fixture.GetStreamName(); + var subscriptionDropped = new TaskCompletionSource(); - + using var subscription = await Fixture.Streams .SubscribeToStreamAsync( streamName, @@ -197,7 +197,7 @@ public async Task drops_when_disposed() { // 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(); @@ -207,7 +207,7 @@ public async Task drops_when_disposed() { [Fact] public async Task drops_when_subscriber_error() { var streamName = Fixture.GetStreamName(); - + var expectedResult = SubscriptionDroppedResult.SubscriberError(); var subscriptionDropped = new TaskCompletionSource(); @@ -231,9 +231,9 @@ public async Task drops_when_subscriber_error() { [Fact] public async Task drops_when_stream_tombstoned() { var streamName = Fixture.GetStreamName(); - + var subscriptionDropped = new TaskCompletionSource(); - + using var subscription = await Fixture.Streams .SubscribeToStreamAsync( streamName, @@ -250,7 +250,7 @@ public async Task drops_when_stream_tombstoned() { 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(); @@ -260,13 +260,13 @@ public async Task receives_all_events_with_resolved_links() { 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();; - + .WithTimeout(); + await receivedAllEvents.Task.WithTimeout(); // if the subscription dropped before time, raise the reason why @@ -277,7 +277,7 @@ public async Task receives_all_events_with_resolved_links() { subscription.Dispose(); var result = await subscriptionDropped.Task.WithTimeout(); result.ShouldBe(SubscriptionDroppedResult.Disposed()); - + return; Task OnReceived(StreamSubscription sub, ResolvedEvent re, CancellationToken ct) { @@ -286,12 +286,12 @@ Task OnReceived(StreamSubscription sub, ResolvedEvent re, CancellationToken ct) 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; } diff --git a/test/EventStore.Client.Tests.Common/Fixtures/EventStoreTestNode.cs b/test/EventStore.Client.Tests.Common/Fixtures/EventStoreTestNode.cs index cfe7688cc..a84af081a 100644 --- a/test/EventStore.Client.Tests.Common/Fixtures/EventStoreTestNode.cs +++ b/test/EventStore.Client.Tests.Common/Fixtures/EventStoreTestNode.cs @@ -73,7 +73,6 @@ protected override ContainerBuilder Configure() { .WithEnvironment(env) .MountVolume(certsPath, "/etc/eventstore/certs", MountType.ReadOnly) .ExposePort(port, 2113); - //.WaitForMessageInLog("'admin' user added to $users.", FromSeconds(60)); } /// From af5e987a42b2947239ed5459157522f914dd68a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Silveira?= Date: Thu, 7 Dec 2023 16:57:27 +0100 Subject: [PATCH 13/22] quick-start sample lacked a valid connstring --- samples/quick-start/Program.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/samples/quick-start/Program.cs b/samples/quick-start/Program.cs index 7ffb748c7..18d6ce80e 100644 --- a/samples/quick-start/Program.cs +++ b/samples/quick-start/Program.cs @@ -5,8 +5,9 @@ #region createClient -var settings = EventStoreClientSettings - .Create("{connectionString}"); +const string connectionString = "esdb://admin:changeit@localhost:2113?tls=true&tlsVerifyCert=false"; + +var settings = EventStoreClientSettings.Create(connectionString); var client = new EventStoreClient(settings); From 27667d060586a2f1fa88aaeafbe13b5636d0ef4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Silveira?= Date: Thu, 7 Dec 2023 17:10:47 +0100 Subject: [PATCH 14/22] connstring issues on samples again --- samples/persistent-subscriptions/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/persistent-subscriptions/Program.cs b/samples/persistent-subscriptions/Program.cs index e49b6e42d..ea275719b 100644 --- a/samples/persistent-subscriptions/Program.cs +++ b/samples/persistent-subscriptions/Program.cs @@ -1,5 +1,5 @@ await using var client = new EventStorePersistentSubscriptionsClient( - EventStoreClientSettings.Create("esdb://localhost:2113?tls=false") + EventStoreClientSettings.Create("esdb://admin:changeit@localhost:2113?tls=true&tlsVerifyCert=false") ); await CreatePersistentSubscription(client); From 7af63f554dc2ce74c349daa86b0072edda66cdc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Silveira?= Date: Fri, 8 Dec 2023 10:43:32 +0100 Subject: [PATCH 15/22] trying out something --- .github/workflows/publish.yml | 6 +- .../PersistentSubscription.cs | 3 +- .../Interceptors/TypedExceptionInterceptor.cs | 132 ++++++++++++- test/EventStore.Client.Tests.Common/.env | 9 + .../docker-compose.certs.yml | 35 ++++ .../docker-compose.cluster.yml | 176 ++++++++++++++++++ .../docker-compose.node.yml | 37 ++++ 7 files changed, 391 insertions(+), 7 deletions(-) create mode 100644 test/EventStore.Client.Tests.Common/docker-compose.certs.yml create mode 100644 test/EventStore.Client.Tests.Common/docker-compose.cluster.yml create mode 100644 test/EventStore.Client.Tests.Common/docker-compose.node.yml diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 25cdd67f6..274fd27bc 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -43,13 +43,13 @@ jobs: strategy: fail-fast: false matrix: - framework: [ net8.0 ] + framework: [ net6.0, net7.0, net8.0 ] services: esdb: image: ghcr.io/eventstore/eventstore:lts env: EVENTSTORE_INSECURE: true - EVENTSTORE_MEM_DB: true + EVENTSTORE_RUN_PROJECTIONS: all EVENTSTORE_START_STANDARD_PROJECTIONS: true ports: @@ -62,6 +62,8 @@ jobs: uses: actions/setup-dotnet@v3 with: dotnet-version: | + 6.0.x + 7.0.x 8.0.x - name: Compile shell: bash diff --git a/src/EventStore.Client.PersistentSubscriptions/PersistentSubscription.cs b/src/EventStore.Client.PersistentSubscriptions/PersistentSubscription.cs index 87969c677..0047e1c73 100644 --- a/src/EventStore.Client.PersistentSubscriptions/PersistentSubscription.cs +++ b/src/EventStore.Client.PersistentSubscriptions/PersistentSubscription.cs @@ -141,8 +141,7 @@ private async Task Subscribe() { _log.LogDebug("Persistent Subscription {subscriptionId} confirmed.", SubscriptionId); try { - await foreach (var response in - _call.ResponseStream.ReadAllAsync(_cancellationToken).ConfigureAwait(false)) { + await foreach (var response in _call.ResponseStream.ReadAllAsync(_cancellationToken).ConfigureAwait(false)) { if (response.ContentCase != ReadResp.ContentOneofCase.Event) { continue; } diff --git a/src/EventStore.Client/Interceptors/TypedExceptionInterceptor.cs b/src/EventStore.Client/Interceptors/TypedExceptionInterceptor.cs index bc640f795..41d16460c 100644 --- a/src/EventStore.Client/Interceptors/TypedExceptionInterceptor.cs +++ b/src/EventStore.Client/Interceptors/TypedExceptionInterceptor.cs @@ -1,3 +1,4 @@ + using System.Diagnostics.CodeAnalysis; using Grpc.Core; using Grpc.Core.Interceptors; @@ -100,13 +101,19 @@ public static IAsyncStreamReader Apply(this IAsyncStreamRead // public static Task Apply(this Task task, Func convertException) => // task.ContinueWith(t => t.Exception?.InnerException is RpcException ex ? throw convertException(ex) : t.Result); - + // public static async Task Apply(this Task task, Func convertException) { try { return await task.ConfigureAwait(false); } - catch (RpcException ex) { - throw convertException(ex); + catch (Exception ex) { + if (ex is RpcException rpcex) + throw convertException(rpcex); + + if(ex is not OperationCanceledException) + throw new Exception($"WTF!? {ex.Message}", ex); + + throw; } } @@ -148,3 +155,122 @@ public async Task MoveNext(CancellationToken cancellationToken) { } } } + + +internal class TypedExceptionInterceptorOld : Interceptor { + private static readonly IDictionary> DefaultExceptionMap = + new Dictionary> { + [Constants.Exceptions.AccessDenied] = ex => new AccessDeniedException(ex.Message, ex), + [Constants.Exceptions.NotLeader] = ex => new NotLeaderException( + ex.Trailers.FirstOrDefault(x => x.Key == Constants.Exceptions.LeaderEndpointHost)?.Value!, + ex.Trailers.GetIntValueOrDefault(Constants.Exceptions.LeaderEndpointPort), ex) + }; + + private readonly IDictionary> _exceptionMap; + + public TypedExceptionInterceptorOld(IDictionary> exceptionMap) { + _exceptionMap = new Dictionary>(DefaultExceptionMap); + foreach (var pair in exceptionMap) { + _exceptionMap.Add(pair); + } + } + + public override AsyncServerStreamingCall AsyncServerStreamingCall( + TRequest request, + ClientInterceptorContext context, + AsyncServerStreamingCallContinuation continuation) { + var response = continuation(request, context); + + return new AsyncServerStreamingCall( + new AsyncStreamReader(_exceptionMap, response.ResponseStream), + response.ResponseHeadersAsync, response.GetStatus, response.GetTrailers, response.Dispose); + } + + public override AsyncClientStreamingCall AsyncClientStreamingCall( + ClientInterceptorContext context, + AsyncClientStreamingCallContinuation continuation) { + var response = continuation(context); + + return new AsyncClientStreamingCall( + response.RequestStream, + response.ResponseAsync.ContinueWith(t => t.Exception?.InnerException is RpcException ex + ? throw ConvertRpcException(ex, _exceptionMap) + : t.Result), + response.ResponseHeadersAsync, + response.GetStatus, + response.GetTrailers, + response.Dispose); + } + + public override AsyncUnaryCall AsyncUnaryCall( + TRequest request, + ClientInterceptorContext context, + AsyncUnaryCallContinuation continuation) { + var response = continuation(request, context); + + return new AsyncUnaryCall( + response.ResponseAsync.ContinueWith( + t => + t.Exception?.InnerException is RpcException ex + ? throw ConvertRpcException(ex, _exceptionMap) + : t.Result + ), + response.ResponseHeadersAsync, + response.GetStatus, + response.GetTrailers, + response.Dispose + ); + } + + public override AsyncDuplexStreamingCall AsyncDuplexStreamingCall( + ClientInterceptorContext context, + AsyncDuplexStreamingCallContinuation continuation) { + var response = continuation(context); + + return new AsyncDuplexStreamingCall( + response.RequestStream, + new AsyncStreamReader(_exceptionMap, response.ResponseStream), + response.ResponseHeadersAsync, + response.GetStatus, + response.GetTrailers, + response.Dispose); + } + + private static Exception ConvertRpcException(RpcException ex, + IDictionary> exceptionMap) { + Func? factory = null; + return (ex.Trailers.TryGetValue(Constants.Exceptions.ExceptionKey, out var key) && + exceptionMap.TryGetValue(key!, out factory)) switch { + true => factory!.Invoke(ex), + false => (ex.StatusCode, ex.Status.Detail) switch { + (StatusCode.Unavailable, "Deadline Exceeded") => new RpcException(new Status( + StatusCode.DeadlineExceeded, ex.Status.Detail, ex.Status.DebugException)), + (StatusCode.DeadlineExceeded, _) => ex, + (StatusCode.Unauthenticated, _) => new NotAuthenticatedException(ex.Message, ex), + _ => ex + } + }; + } + + private class AsyncStreamReader : IAsyncStreamReader { + private readonly IDictionary> _exceptionMap; + private readonly IAsyncStreamReader _inner; + + public AsyncStreamReader(IDictionary> exceptionMap, + IAsyncStreamReader inner) { + _exceptionMap = exceptionMap; + _inner = inner; + } + + public async Task MoveNext(CancellationToken cancellationToken) { + try { + return await _inner.MoveNext(cancellationToken).ConfigureAwait(false); + } catch (RpcException ex) { + throw ConvertRpcException(ex, _exceptionMap); + } + } + + public TResponse Current => _inner.Current; + } +} + diff --git a/test/EventStore.Client.Tests.Common/.env b/test/EventStore.Client.Tests.Common/.env index bfbcbf3ab..9bed84298 100644 --- a/test/EventStore.Client.Tests.Common/.env +++ b/test/EventStore.Client.Tests.Common/.env @@ -1,2 +1,11 @@ ES_CERTS_CLUSTER=./certs-cluster ES_DOCKER_TAG=ci + +EVENTSTORE_MEM_DB=true +EVENTSTORE_HTTP_PORT=2113 +EVENTSTORE_LOG_LEVEL=Information +EVENTSTORE_DISABLE_LOG_FILE=true +EVENTSTORE_RUN_PROJECTIONS=None +EVENTSTORE_START_STANDARD_PROJECTIONS=true +EVENTSTORE_TRUSTED_ROOT_CERTIFICATES_PATH=/etc/eventstore/certs/ca +EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP=false diff --git a/test/EventStore.Client.Tests.Common/docker-compose.certs.yml b/test/EventStore.Client.Tests.Common/docker-compose.certs.yml new file mode 100644 index 000000000..4ff518f6a --- /dev/null +++ b/test/EventStore.Client.Tests.Common/docker-compose.certs.yml @@ -0,0 +1,35 @@ +version: "3.5" + +networks: + default: + name: eventstore-network + +services: + + volumes-provisioner: + image: hasnat/volumes-provisioner + container_name: volumes-provisioner + environment: + PROVISION_DIRECTORIES: "1000:1000:0755:/tmp/certs" + volumes: + - "${ES_CERTS_CLUSTER}:/tmp/certs" + network_mode: none + + cert-gen: + image: eventstore/es-gencert-cli:1.0.2 + container_name: cert-gen + user: "1000:1000" + entrypoint: [ "/bin/sh","-c" ] + command: + - | + es-gencert-cli create-ca -out /tmp/certs/ca + es-gencert-cli create-node -ca-certificate /tmp/certs/ca/ca.crt -ca-key /tmp/certs/ca/ca.key -out /tmp/certs/node -ip-addresses 127.0.0.1 -dns-names localhost,eventstore + + es-gencert-cli create-node -ca-certificate /tmp/certs/ca/ca.crt -ca-key /tmp/certs/ca/ca.key -out /tmp/certs/node1 -ip-addresses 127.0.0.1,172.30.240.11 -dns-names localhost,esdb-node1 + es-gencert-cli create-node -ca-certificate /tmp/certs/ca/ca.crt -ca-key /tmp/certs/ca/ca.key -out /tmp/certs/node2 -ip-addresses 127.0.0.1,172.30.240.12 -dns-names localhost,esdb-node2 + es-gencert-cli create-node -ca-certificate /tmp/certs/ca/ca.crt -ca-key /tmp/certs/ca/ca.key -out /tmp/certs/node3 -ip-addresses 127.0.0.1,172.30.240.13 -dns-names localhost,esdb-node3 + es-gencert-cli create-node -ca-certificate /tmp/certs/ca/ca.crt -ca-key /tmp/certs/ca/ca.key -out /tmp/certs/node4 -ip-addresses 127.0.0.1,172.30.240.14 -dns-names localhost,esdb-node4 + volumes: + - "${ES_CERTS_CLUSTER}:/tmp/certs" + depends_on: + - volumes-provisioner \ No newline at end of file diff --git a/test/EventStore.Client.Tests.Common/docker-compose.cluster.yml b/test/EventStore.Client.Tests.Common/docker-compose.cluster.yml new file mode 100644 index 000000000..2c92d5162 --- /dev/null +++ b/test/EventStore.Client.Tests.Common/docker-compose.cluster.yml @@ -0,0 +1,176 @@ +version: "3.5" + +services: + volumes-provisioner: + image: hasnat/volumes-provisioner + container_name: volumes-provisioner + environment: + PROVISION_DIRECTORIES: "1000:1000:0755:/tmp/certs" + volumes: + - "${ES_CERTS_CLUSTER}:/tmp/certs" + network_mode: none + + cert-gen: + image: eventstore/es-gencert-cli:1.0.2 + container_name: cert-gen + user: "1000:1000" + entrypoint: [ "/bin/sh","-c" ] + # rm -rf /tmp/certs/** + command: + - | + es-gencert-cli create-ca -out /tmp/certs/ca + es-gencert-cli create-node -ca-certificate /tmp/certs/ca/ca.crt -ca-key /tmp/certs/ca/ca.key -out /tmp/certs/node1 -ip-addresses 127.0.0.1,172.30.240.11 -dns-names localhost + es-gencert-cli create-node -ca-certificate /tmp/certs/ca/ca.crt -ca-key /tmp/certs/ca/ca.key -out /tmp/certs/node2 -ip-addresses 127.0.0.1,172.30.240.12 -dns-names localhost + es-gencert-cli create-node -ca-certificate /tmp/certs/ca/ca.crt -ca-key /tmp/certs/ca/ca.key -out /tmp/certs/node3 -ip-addresses 127.0.0.1,172.30.240.13 -dns-names localhost + es-gencert-cli create-node -ca-certificate /tmp/certs/ca/ca.crt -ca-key /tmp/certs/ca/ca.key -out /tmp/certs/node4 -ip-addresses 127.0.0.1,172.30.240.14 -dns-names localhost + volumes: + - "${ES_CERTS_CLUSTER}:/tmp/certs" + depends_on: + - volumes-provisioner + + seq: + image: datalust/seq:latest + container_name: seq + environment: + ACCEPT_EULA: Y + ports: + - "5341:80" + depends_on: + - volumes-provisioner + - cert-gen + + esdb-node1: + image: ghcr.io/eventstore/eventstore:${ES_DOCKER_TAG} + container_name: esdb-node1 + env_file: + - shared.env + environment: + - EVENTSTORE_GOSSIP_SEED=172.30.240.12:2113,172.30.240.13:2113 + - EVENTSTORE_INT_IP=172.30.240.11 + - EVENTSTORE_CERTIFICATE_FILE=/etc/eventstore/certs/node1/node.crt + - EVENTSTORE_CERTIFICATE_PRIVATE_KEY_FILE=/etc/eventstore/certs/node1/node.key + - EVENTSTORE_ADVERTISE_HOST_TO_CLIENT_AS=127.0.0.1 + - EVENTSTORE_ADVERTISE_HTTP_PORT_TO_CLIENT_AS=2111 + ports: + - "2111:2113" + networks: + clusternetwork: + ipv4_address: 172.30.240.11 + volumes: + - ${ES_CERTS_CLUSTER}:/etc/eventstore/certs + - type: volume + source: eventstore-volume-data1 + target: /var/lib/eventstore + - type: volume + source: eventstore-volume-logs1 + target: /var/log/eventstore + restart: unless-stopped + depends_on: + - cert-gen + + esdb-node2: + image: ghcr.io/eventstore/eventstore:${ES_DOCKER_TAG} + container_name: esdb-node2 + env_file: + - shared.env + environment: + - EVENTSTORE_GOSSIP_SEED=172.30.240.11:2113,172.30.240.13:2113 + - EVENTSTORE_INT_IP=172.30.240.12 + - EVENTSTORE_CERTIFICATE_FILE=/etc/eventstore/certs/node2/node.crt + - EVENTSTORE_CERTIFICATE_PRIVATE_KEY_FILE=/etc/eventstore/certs/node2/node.key + - EVENTSTORE_ADVERTISE_HOST_TO_CLIENT_AS=127.0.0.1 + - EVENTSTORE_ADVERTISE_HTTP_PORT_TO_CLIENT_AS=2112 + ports: + - "2112:2113" + networks: + clusternetwork: + ipv4_address: 172.30.240.12 + volumes: + - ${ES_CERTS_CLUSTER}:/etc/eventstore/certs + - type: volume + source: eventstore-volume-data2 + target: /var/lib/eventstore + - type: volume + source: eventstore-volume-logs2 + target: /var/log/eventstore + restart: unless-stopped + depends_on: + - cert-gen + + esdb-node3: + image: ghcr.io/eventstore/eventstore:${ES_DOCKER_TAG} + container_name: esdb-node3 + env_file: + - shared.env + environment: + - EVENTSTORE_GOSSIP_SEED=172.30.240.11:2113,172.30.240.12:2113 + - EVENTSTORE_INT_IP=172.30.240.13 + - EVENTSTORE_CERTIFICATE_FILE=/etc/eventstore/certs/node3/node.crt + - EVENTSTORE_CERTIFICATE_PRIVATE_KEY_FILE=/etc/eventstore/certs/node3/node.key + - EVENTSTORE_ADVERTISE_HOST_TO_CLIENT_AS=127.0.0.1 + - EVENTSTORE_ADVERTISE_HTTP_PORT_TO_CLIENT_AS=2113 + ports: + - "2113:2113" + networks: + clusternetwork: + ipv4_address: 172.30.240.13 + volumes: + - ${ES_CERTS_CLUSTER}:/etc/eventstore/certs + - type: volume + source: eventstore-volume-data3 + target: /var/lib/eventstore + - type: volume + source: eventstore-volume-logs3 + target: /var/log/eventstore + restart: unless-stopped + depends_on: + - cert-gen + + esdb-node4: + image: ghcr.io/eventstore/eventstore:${ES_DOCKER_TAG} + container_name: esdb-node4 + env_file: + - shared.env + environment: + - EVENTSTORE_READ_ONLY_REPLICA=true + - EVENTSTORE_GOSSIP_SEED=172.30.240.11:2113,172.30.240.12:2113,172.30.240.13:2113 + - EVENTSTORE_INT_IP=172.30.240.14 + - EVENTSTORE_CERTIFICATE_FILE=/etc/eventstore/certs/node4/node.crt + - EVENTSTORE_CERTIFICATE_PRIVATE_KEY_FILE=/etc/eventstore/certs/node4/node.key + - EVENTSTORE_ADVERTISE_HOST_TO_CLIENT_AS=127.0.0.1 + - EVENTSTORE_ADVERTISE_HTTP_PORT_TO_CLIENT_AS=2114 + ports: + - "2114:2113" + networks: + clusternetwork: + ipv4_address: 172.30.240.14 + volumes: + - ${ES_CERTS_CLUSTER}:/etc/eventstore/certs + - type: volume + source: eventstore-volume-data4 + target: /var/lib/eventstore + - type: volume + source: eventstore-volume-logs4 + target: /var/log/eventstore + restart: unless-stopped + depends_on: + - cert-gen + +networks: + clusternetwork: + name: eventstoredb.local + driver: bridge + ipam: + driver: default + config: + - subnet: 172.30.240.0/24 + +volumes: + eventstore-volume-data1: + eventstore-volume-logs1: + eventstore-volume-data2: + eventstore-volume-logs2: + eventstore-volume-data3: + eventstore-volume-logs3: + eventstore-volume-data4: + eventstore-volume-logs4: diff --git a/test/EventStore.Client.Tests.Common/docker-compose.node.yml b/test/EventStore.Client.Tests.Common/docker-compose.node.yml new file mode 100644 index 000000000..a6997819a --- /dev/null +++ b/test/EventStore.Client.Tests.Common/docker-compose.node.yml @@ -0,0 +1,37 @@ +version: "3.5" + +networks: + default: + name: eventstore-network + +services: + + eventstore: + image: ghcr.io/eventstore/eventstore:${ES_DOCKER_TAG} + container_name: eventstore + environment: + - EVENTSTORE_MEM_DB=true + - EVENTSTORE_HTTP_PORT=2113 + - EVENTSTORE_LOG_LEVEL=Information + - EVENTSTORE_RUN_PROJECTIONS=None + - EVENTSTORE_START_STANDARD_PROJECTIONS=true + + # set certificates location + - 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 + ports: + - "2113:2113" + volumes: + - ${ES_CERTS_CLUSTER}:/etc/eventstore/certs + - type: volume + source: eventstore-volume-data1 + target: /var/lib/eventstore + - type: volume + source: eventstore-volume-logs1 + target: /var/log/eventstore + restart: unless-stopped + +volumes: + eventstore-volume-data1: + eventstore-volume-logs1: From 0724dc9e35cce2105f1d368bd37d6181b8b6ce8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Silveira?= Date: Fri, 8 Dec 2023 11:52:26 +0100 Subject: [PATCH 16/22] minor changes --- .github/workflows/publish.yml | 6 +- Directory.Build.props | 8 +- samples/persistent-subscriptions/Program.cs | 118 ++++++++++++++---- samples/quick-start/docker-compose.yml | 7 +- src/Directory.Build.props | 8 +- .../EventStore.Client.csproj | 6 +- test/EventStore.Client.Tests.Common/.env | 16 +-- .../appsettings.json | 5 +- 8 files changed, 122 insertions(+), 52 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 274fd27bc..239ea739a 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -43,13 +43,13 @@ jobs: strategy: fail-fast: false matrix: - framework: [ net6.0, net7.0, net8.0 ] + framework: [ net8.0 ] services: esdb: image: ghcr.io/eventstore/eventstore:lts env: EVENTSTORE_INSECURE: true - + EVENTSTORE_MEM_DB: false EVENTSTORE_RUN_PROJECTIONS: all EVENTSTORE_START_STANDARD_PROJECTIONS: true ports: @@ -62,8 +62,6 @@ jobs: uses: actions/setup-dotnet@v3 with: dotnet-version: | - 6.0.x - 7.0.x 8.0.x - name: Compile shell: bash diff --git a/Directory.Build.props b/Directory.Build.props index 21cacfc24..ac609fab3 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -13,9 +13,9 @@ pdbonly true - 2.49.0 - 2.50.0 - - + + + 2.59.0 + 2.59.0 diff --git a/samples/persistent-subscriptions/Program.cs b/samples/persistent-subscriptions/Program.cs index ea275719b..890d32e49 100644 --- a/samples/persistent-subscriptions/Program.cs +++ b/samples/persistent-subscriptions/Program.cs @@ -1,7 +1,10 @@ await using var client = new EventStorePersistentSubscriptionsClient( - EventStoreClientSettings.Create("esdb://admin:changeit@localhost:2113?tls=true&tlsVerifyCert=false") + EventStoreClientSettings.Create("esdb://localhost:2113?tls=false&tlsVerifyCert=false") ); +await TryDeletePersistentSubscription(client); +await TryDeletePersistentSubscriptionToAll(client); + await CreatePersistentSubscription(client); await UpdatePersistentSubscription(client); await ConnectToPersistentSubscriptionToStream(client); @@ -16,7 +19,9 @@ await ListPersistentSubscriptionsToAll(client); await ListAllPersistentSubscriptions(client); await RestartPersistentSubscriptionSubsystem(client); -await DeletePersistentSubscription(client); + +await TryDeletePersistentSubscription(client); +await TryDeletePersistentSubscriptionToAll(client); return; @@ -33,6 +38,7 @@ await client.CreateToStreamAsync( userCredentials: userCredentials ); + Console.WriteLine("Subscription to stream created"); #endregion create-persistent-subscription-to-stream } @@ -47,10 +53,11 @@ static async Task ConnectToPersistentSubscriptionToStream(EventStorePersistentSu await subscription.Ack(evnt); }, (subscription, dropReason, exception) => { - Console.WriteLine($"Subscription was dropped due to {dropReason}. {exception}"); + Console.WriteLine($"Subscription to stream was dropped due to {dropReason}. {exception?.Message}"); } ); + Console.WriteLine("Subscription to stream started"); #endregion subscribe-to-persistent-subscription-to-stream } @@ -68,6 +75,7 @@ await client.CreateToAllAsync( userCredentials: userCredentials ); + Console.WriteLine("Subscription to all created"); #endregion create-persistent-subscription-to-all } @@ -78,10 +86,11 @@ await client.SubscribeToAllAsync( "subscription-group", async (subscription, evnt, retryCount, cancellationToken) => { await HandleEvent(evnt); }, (subscription, dropReason, exception) => { - Console.WriteLine($"Subscription was dropped due to {dropReason}. {exception}"); + Console.WriteLine($"Subscription to all was dropped due to {dropReason}. {exception?.Message}"); } ); + Console.WriteLine("Subscription to all started"); #endregion subscribe-to-persistent-subscription-to-all } @@ -101,10 +110,11 @@ static async Task ConnectToPersistentSubscriptionWithManualAcks(EventStorePersis } }, (subscription, dropReason, exception) => { - Console.WriteLine($"Subscription was dropped due to {dropReason}. {exception}"); + Console.WriteLine($"Subscription to stream with manual acks was dropped due to {dropReason}. {exception?.Message}"); } ); + Console.WriteLine("Subscription to stream with manual acks started"); #endregion subscribe-to-persistent-subscription-with-manual-acks } @@ -112,10 +122,7 @@ static async Task UpdatePersistentSubscription(EventStorePersistentSubscriptions #region update-persistent-subscription var userCredentials = new UserCredentials("admin", "changeit"); - var settings = new PersistentSubscriptionSettings( - true, - checkPointLowerBound: 20 - ); + var settings = new PersistentSubscriptionSettings(true, checkPointLowerBound: 20); await client.UpdateToStreamAsync( "test-stream", @@ -124,22 +131,70 @@ await client.UpdateToStreamAsync( userCredentials: userCredentials ); + Console.WriteLine("Subscription updated"); #endregion update-persistent-subscription } -static async Task DeletePersistentSubscription(EventStorePersistentSubscriptionsClient client) { +// static async Task DeletePersistentSubscription(EventStorePersistentSubscriptionsClient client) { +// #region delete-persistent-subscription +// +// var userCredentials = new UserCredentials("admin", "changeit"); +// +// await client.DeleteToStreamAsync( +// "test-stream", +// "subscription-group", +// userCredentials: userCredentials +// ); +// +// Console.WriteLine("Subscription deleted"); +// #endregion delete-persistent-subscription +// } + +static async Task TryDeletePersistentSubscription(EventStorePersistentSubscriptionsClient client) { #region delete-persistent-subscription - var userCredentials = new UserCredentials("admin", "changeit"); - await client.DeleteToStreamAsync( - "test-stream", - "subscription-group", - userCredentials: userCredentials - ); - + try { + var userCredentials = new UserCredentials("admin", "changeit"); + await client.DeleteToStreamAsync( + "test-stream", + "subscription-group", + userCredentials: userCredentials + ); + + Console.WriteLine("Subscription to stream deleted"); + } + catch (PersistentSubscriptionNotFoundException) { + // ignore + } + catch (Exception ex) { + Console.WriteLine($"Subscription to stream delete error: {ex.GetType()} {ex.Message}"); + } + #endregion delete-persistent-subscription } +static async Task TryDeletePersistentSubscriptionToAll(EventStorePersistentSubscriptionsClient client) { + #region delete-persistent-subscription-to-all + + try { + var userCredentials = new UserCredentials("admin", "changeit"); + await client.DeleteToAllAsync( + "subscription-group", + userCredentials: userCredentials + ); + + Console.WriteLine("Subscription to all deleted"); + } + catch (PersistentSubscriptionNotFoundException) { + // ignore + } + catch (Exception ex) { + Console.WriteLine($"Subscription to all delete error: {ex.GetType()} {ex.Message}"); + } + + #endregion delete-persistent-subscription-to-all +} + static async Task GetPersistentSubscriptionToStreamInfo(EventStorePersistentSubscriptionsClient client) { #region get-persistent-subscription-to-stream-info @@ -150,7 +205,7 @@ static async Task GetPersistentSubscriptionToStreamInfo(EventStorePersistentSubs userCredentials: userCredentials ); - Console.WriteLine($"GroupName: {info.GroupName}, EventSource: {info.EventSource}, Status: {info.Status}"); + Console.WriteLine($"GroupName: {info.GroupName} EventSource: {info.EventSource} Status: {info.Status}"); #endregion get-persistent-subscription-to-stream-info } @@ -164,7 +219,7 @@ static async Task GetPersistentSubscriptionToAllInfo(EventStorePersistentSubscri userCredentials: userCredentials ); - Console.WriteLine($"GroupName: {info.GroupName}, EventSource: {info.EventSource}, Status: {info.Status}"); + Console.WriteLine($"GroupName: {info.GroupName} EventSource: {info.EventSource} Status: {info.Status}"); #endregion get-persistent-subscription-to-all-info } @@ -180,6 +235,7 @@ await client.ReplayParkedMessagesToStreamAsync( userCredentials: userCredentials ); + Console.WriteLine("Replay of parked messages to stream requested"); #endregion persistent-subscription-replay-parked-to-stream } @@ -193,6 +249,7 @@ await client.ReplayParkedMessagesToAllAsync( userCredentials: userCredentials ); + Console.WriteLine("Replay of parked messages to all requested"); #endregion replay-parked-of-persistent-subscription-to-all } @@ -205,8 +262,10 @@ static async Task ListPersistentSubscriptionsToStream(EventStorePersistentSubscr userCredentials: userCredentials ); - foreach (var s in subscriptions) - Console.WriteLine($"GroupName: {s.GroupName}, EventSource: {s.EventSource}, Status: {s.Status}"); + var entries = subscriptions + .Select(s => $"GroupName: {s.GroupName} EventSource: {s.EventSource} Status: {s.Status}"); + + Console.WriteLine($"Subscriptions to stream: [ {string.Join(", ", entries)} ]"); #endregion list-persistent-subscriptions-to-stream } @@ -217,9 +276,11 @@ static async Task ListPersistentSubscriptionsToAll(EventStorePersistentSubscript var userCredentials = new UserCredentials("admin", "changeit"); var subscriptions = await client.ListToAllAsync(userCredentials: userCredentials); - foreach (var s in subscriptions) - Console.WriteLine($"GroupName: {s.GroupName}, EventSource: {s.EventSource}, Status: {s.Status}"); - + var entries = subscriptions + .Select(s => $"GroupName: {s.GroupName} EventSource: {s.EventSource} Status: {s.Status}"); + + Console.WriteLine($"Subscriptions to all: [ {string.Join(", ", entries)} ]"); + #endregion list-persistent-subscriptions-to-all } @@ -229,9 +290,11 @@ static async Task ListAllPersistentSubscriptions(EventStorePersistentSubscriptio var userCredentials = new UserCredentials("admin", "changeit"); var subscriptions = await client.ListAllAsync(userCredentials: userCredentials); - foreach (var s in subscriptions) - Console.WriteLine($"GroupName: {s.GroupName}, EventSource: {s.EventSource}, Status: {s.Status}"); - + var entries = subscriptions + .Select(s => $"GroupName: {s.GroupName} EventSource: {s.EventSource} Status: {s.Status}"); + + Console.WriteLine($"Subscriptions: [{string.Join(", ", entries)} ]"); + #endregion list-persistent-subscriptions } @@ -241,6 +304,7 @@ static async Task RestartPersistentSubscriptionSubsystem(EventStorePersistentSub var userCredentials = new UserCredentials("admin", "changeit"); await client.RestartSubsystemAsync(userCredentials: userCredentials); + Console.WriteLine("Persistent subscription subsystem restarted"); #endregion restart-persistent-subscription-subsystem } diff --git a/samples/quick-start/docker-compose.yml b/samples/quick-start/docker-compose.yml index 003ef97d4..d98e8b298 100644 --- a/samples/quick-start/docker-compose.yml +++ b/samples/quick-start/docker-compose.yml @@ -1,8 +1,11 @@ -version: '3' +version: '3.5' services: eventstore: image: eventstore/eventstore:latest environment: - - EVENTSTORE_INSECURE=true + EVENTSTORE_INSECURE: true + EVENTSTORE_MEM_DB: false + EVENTSTORE_RUN_PROJECTIONS: all + EVENTSTORE_START_STANDARD_PROJECTIONS: true ports: - "2113:2113" \ No newline at end of file diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 85db7ad50..1921131a9 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -35,10 +35,10 @@ - - - - + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + all runtime; build; native; contentfiles; analyzers diff --git a/src/EventStore.Client/EventStore.Client.csproj b/src/EventStore.Client/EventStore.Client.csproj index 2bbe5b29e..045d738fc 100644 --- a/src/EventStore.Client/EventStore.Client.csproj +++ b/src/EventStore.Client/EventStore.Client.csproj @@ -7,9 +7,11 @@ - + + - + + diff --git a/test/EventStore.Client.Tests.Common/.env b/test/EventStore.Client.Tests.Common/.env index 9bed84298..81d6ca0c4 100644 --- a/test/EventStore.Client.Tests.Common/.env +++ b/test/EventStore.Client.Tests.Common/.env @@ -1,11 +1,11 @@ ES_CERTS_CLUSTER=./certs-cluster ES_DOCKER_TAG=ci -EVENTSTORE_MEM_DB=true -EVENTSTORE_HTTP_PORT=2113 -EVENTSTORE_LOG_LEVEL=Information -EVENTSTORE_DISABLE_LOG_FILE=true -EVENTSTORE_RUN_PROJECTIONS=None -EVENTSTORE_START_STANDARD_PROJECTIONS=true -EVENTSTORE_TRUSTED_ROOT_CERTIFICATES_PATH=/etc/eventstore/certs/ca -EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP=false +#EVENTSTORE_MEM_DB=true +#EVENTSTORE_HTTP_PORT=2113 +#EVENTSTORE_LOG_LEVEL=Information +#EVENTSTORE_DISABLE_LOG_FILE=true +#EVENTSTORE_RUN_PROJECTIONS=None +#EVENTSTORE_START_STANDARD_PROJECTIONS=true +#EVENTSTORE_TRUSTED_ROOT_CERTIFICATES_PATH=/etc/eventstore/certs/ca +#EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP=false diff --git a/test/EventStore.Client.Tests.Common/appsettings.json b/test/EventStore.Client.Tests.Common/appsettings.json index b3e5fa22f..7de897122 100644 --- a/test/EventStore.Client.Tests.Common/appsettings.json +++ b/test/EventStore.Client.Tests.Common/appsettings.json @@ -5,7 +5,10 @@ "Override": { "Microsoft": "Warning", "Grpc": "Information", - "EventStore.Client.EventStoreClient": "Information" + "Grpc.Net.Client.Internal.GrpcCall": "Fatal", + "EventStore.Client.SharingProvider": "Information", + "EventStore.Client.EventStoreClient": "Information", + "EventStore.Client.SingleNodeChannelSelector": "Warning" } }, "Enrich": ["FromLogContext", "WithThreadId"], From 57f928c65216c8eb3c98a334e334aa46a98965f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Silveira?= Date: Fri, 8 Dec 2023 12:17:23 +0100 Subject: [PATCH 17/22] clean up and re-organizing categories and folders --- samples/persistent-subscriptions/Program.cs | 27 +++++-------------- .../Append/ShouldThrowAsyncExtensions.cs | 15 +++++++++++ .../append_to_stream.cs | 20 ++------------ .../append_to_stream_limits.cs | 4 +-- .../append_to_stream_retry.cs | 6 ++--- .../appending_to_implicitly_created_stream.cs | 5 ++-- .../sending_and_receiving_large_messages.cs | 4 +-- .../deleting_stream.cs | 3 +-- .../soft_deleted_stream.cs | 3 +-- .../DependencyInjectionTests.cs | 1 + .../EventDataTests.cs | 1 + ...re.Client.Streams.Tests.csproj.DotSettings | 3 +++ .../stream_metadata.cs | 3 +-- .../ReadAll/read_all_events_backward.cs | 10 +++---- .../ReadAll/read_all_events_forward.cs | 9 ++++--- .../ReadStream/read_stream_backward.cs | 6 ++--- ...stream_events_linked_to_deleted_stream.cs} | 13 +++++---- .../ReadStream/read_stream_forward.cs | 6 ++--- ...m_when_having_max_count_set_for_stream.cs} | 8 +++--- .../Subscriptions/SubscriptionsFixture.cs | 2 +- .../Subscriptions/subscribe_to_all.cs | 3 ++- .../Subscriptions/subscribe_to_stream.cs | 3 ++- .../is_json.cs | 3 +-- 23 files changed, 73 insertions(+), 85 deletions(-) create mode 100644 test/EventStore.Client.Streams.Tests/Append/ShouldThrowAsyncExtensions.cs rename test/EventStore.Client.Streams.Tests/{AppendToStream => Append}/append_to_stream.cs (96%) rename test/EventStore.Client.Streams.Tests/{AppendToStream => Append}/append_to_stream_limits.cs (95%) rename test/EventStore.Client.Streams.Tests/{AppendToStream => Append}/append_to_stream_retry.cs (90%) rename test/EventStore.Client.Streams.Tests/{AppendToStream => Append}/appending_to_implicitly_created_stream.cs (98%) rename test/EventStore.Client.Streams.Tests/{AppendToStream => Append}/sending_and_receiving_large_messages.cs (92%) rename test/EventStore.Client.Streams.Tests/{DeleteStream => Delete}/deleting_stream.cs (98%) rename test/EventStore.Client.Streams.Tests/{DeleteStream => Delete}/soft_deleted_stream.cs (99%) rename test/EventStore.Client.Streams.Tests/{StreamMetadata => Metadata}/stream_metadata.cs (98%) rename test/EventStore.Client.Streams.Tests/ReadStream/{read_events_linked_to_deleted_stream.cs => read_stream_events_linked_to_deleted_stream.cs} (77%) rename test/EventStore.Client.Streams.Tests/ReadStream/{when_having_max_count_set_for_stream.cs => read_stream_when_having_max_count_set_for_stream.cs} (94%) diff --git a/samples/persistent-subscriptions/Program.cs b/samples/persistent-subscriptions/Program.cs index 890d32e49..6ea61fa67 100644 --- a/samples/persistent-subscriptions/Program.cs +++ b/samples/persistent-subscriptions/Program.cs @@ -2,8 +2,8 @@ EventStoreClientSettings.Create("esdb://localhost:2113?tls=false&tlsVerifyCert=false") ); -await TryDeletePersistentSubscription(client); -await TryDeletePersistentSubscriptionToAll(client); +await DeletePersistentSubscription(client); +await DeletePersistentSubscriptionToAll(client); await CreatePersistentSubscription(client); await UpdatePersistentSubscription(client); @@ -20,8 +20,8 @@ await ListAllPersistentSubscriptions(client); await RestartPersistentSubscriptionSubsystem(client); -await TryDeletePersistentSubscription(client); -await TryDeletePersistentSubscriptionToAll(client); +await DeletePersistentSubscription(client); +await DeletePersistentSubscriptionToAll(client); return; @@ -135,22 +135,7 @@ await client.UpdateToStreamAsync( #endregion update-persistent-subscription } -// static async Task DeletePersistentSubscription(EventStorePersistentSubscriptionsClient client) { -// #region delete-persistent-subscription -// -// var userCredentials = new UserCredentials("admin", "changeit"); -// -// await client.DeleteToStreamAsync( -// "test-stream", -// "subscription-group", -// userCredentials: userCredentials -// ); -// -// Console.WriteLine("Subscription deleted"); -// #endregion delete-persistent-subscription -// } - -static async Task TryDeletePersistentSubscription(EventStorePersistentSubscriptionsClient client) { +static async Task DeletePersistentSubscription(EventStorePersistentSubscriptionsClient client) { #region delete-persistent-subscription try { @@ -173,7 +158,7 @@ await client.DeleteToStreamAsync( #endregion delete-persistent-subscription } -static async Task TryDeletePersistentSubscriptionToAll(EventStorePersistentSubscriptionsClient client) { +static async Task DeletePersistentSubscriptionToAll(EventStorePersistentSubscriptionsClient client) { #region delete-persistent-subscription-to-all try { diff --git a/test/EventStore.Client.Streams.Tests/Append/ShouldThrowAsyncExtensions.cs b/test/EventStore.Client.Streams.Tests/Append/ShouldThrowAsyncExtensions.cs new file mode 100644 index 000000000..075afe533 --- /dev/null +++ b/test/EventStore.Client.Streams.Tests/Append/ShouldThrowAsyncExtensions.cs @@ -0,0 +1,15 @@ +namespace EventStore.Client.Streams.Tests; + +public static class ShouldThrowAsyncExtensions { + + public static Task ShouldThrowAsync(this EventStoreClient.ReadStreamResult source) where TException : Exception => + source + .ToArrayAsync() + .AsTask() + .ShouldThrowAsync(); + + public static async Task ShouldThrowAsync(this EventStoreClient.ReadStreamResult source, Action handler) where TException : Exception { + var ex = await source.ShouldThrowAsync(); + handler(ex); + } +} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream.cs b/test/EventStore.Client.Streams.Tests/Append/append_to_stream.cs similarity index 96% rename from test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream.cs rename to test/EventStore.Client.Streams.Tests/Append/append_to_stream.cs index e0eeef8b9..23d25b3b3 100644 --- a/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream.cs +++ b/test/EventStore.Client.Streams.Tests/Append/append_to_stream.cs @@ -2,24 +2,8 @@ namespace EventStore.Client.Streams.Tests; -public static class ShouldThrowAsyncExtensions { - - public static Task ShouldThrowAsync(this EventStoreClient.ReadStreamResult source) where TException : Exception => - source - .ToArrayAsync() - .AsTask() - .ShouldThrowAsync(); - - public static async Task ShouldThrowAsync(this EventStoreClient.ReadStreamResult source, Action handler) where TException : Exception { - var ex = await source.ShouldThrowAsync(); - handler(ex); - } -} - - -[Trait("Category", "Network")] -[Trait("Category", "Stream")] -[Trait("Category", "Append")] +[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 }; diff --git a/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_limits.cs b/test/EventStore.Client.Streams.Tests/Append/append_to_stream_limits.cs similarity index 95% rename from test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_limits.cs rename to test/EventStore.Client.Streams.Tests/Append/append_to_stream_limits.cs index b3d0099e3..3d4aaf2bf 100644 --- a/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_limits.cs +++ b/test/EventStore.Client.Streams.Tests/Append/append_to_stream_limits.cs @@ -1,7 +1,7 @@ namespace EventStore.Client.Streams.Tests; -[Trait("Category", "Stream")] -[Trait("Category", "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() { diff --git a/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_retry.cs b/test/EventStore.Client.Streams.Tests/Append/append_to_stream_retry.cs similarity index 90% rename from test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_retry.cs rename to test/EventStore.Client.Streams.Tests/Append/append_to_stream_retry.cs index a12367774..04725593c 100644 --- a/test/EventStore.Client.Streams.Tests/AppendToStream/append_to_stream_retry.cs +++ b/test/EventStore.Client.Streams.Tests/Append/append_to_stream_retry.cs @@ -3,10 +3,8 @@ namespace EventStore.Client.Streams.Tests; -[Trait("Category", "Network")] -[Trait("Category", "DedicatedDatabase")] -[Trait("Category", "Stream")] -[Trait("Category", "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() { diff --git a/test/EventStore.Client.Streams.Tests/AppendToStream/appending_to_implicitly_created_stream.cs b/test/EventStore.Client.Streams.Tests/Append/appending_to_implicitly_created_stream.cs similarity index 98% rename from test/EventStore.Client.Streams.Tests/AppendToStream/appending_to_implicitly_created_stream.cs rename to test/EventStore.Client.Streams.Tests/Append/appending_to_implicitly_created_stream.cs index 5a15a4d64..f0285b430 100644 --- a/test/EventStore.Client.Streams.Tests/AppendToStream/appending_to_implicitly_created_stream.cs +++ b/test/EventStore.Client.Streams.Tests/Append/appending_to_implicitly_created_stream.cs @@ -1,8 +1,7 @@ namespace EventStore.Client.Streams.Tests; -[Trait("Category", "LongRunning")] -[Trait("Category", "Stream")] -[Trait("Category", "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() { diff --git a/test/EventStore.Client.Streams.Tests/AppendToStream/sending_and_receiving_large_messages.cs b/test/EventStore.Client.Streams.Tests/Append/sending_and_receiving_large_messages.cs similarity index 92% rename from test/EventStore.Client.Streams.Tests/AppendToStream/sending_and_receiving_large_messages.cs rename to test/EventStore.Client.Streams.Tests/Append/sending_and_receiving_large_messages.cs index 51c4200ce..512430630 100644 --- a/test/EventStore.Client.Streams.Tests/AppendToStream/sending_and_receiving_large_messages.cs +++ b/test/EventStore.Client.Streams.Tests/Append/sending_and_receiving_large_messages.cs @@ -2,8 +2,8 @@ namespace EventStore.Client.Streams.Tests; -[Trait("Category", "Stream")] -[Trait("Category", "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] diff --git a/test/EventStore.Client.Streams.Tests/DeleteStream/deleting_stream.cs b/test/EventStore.Client.Streams.Tests/Delete/deleting_stream.cs similarity index 98% rename from test/EventStore.Client.Streams.Tests/DeleteStream/deleting_stream.cs rename to test/EventStore.Client.Streams.Tests/Delete/deleting_stream.cs index c036861ea..535e41cee 100644 --- a/test/EventStore.Client.Streams.Tests/DeleteStream/deleting_stream.cs +++ b/test/EventStore.Client.Streams.Tests/Delete/deleting_stream.cs @@ -2,8 +2,7 @@ namespace EventStore.Client.Streams.Tests; -[Trait("Category", "Network")] -[Trait("Category", "Delete")] +[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) }; diff --git a/test/EventStore.Client.Streams.Tests/DeleteStream/soft_deleted_stream.cs b/test/EventStore.Client.Streams.Tests/Delete/soft_deleted_stream.cs similarity index 99% rename from test/EventStore.Client.Streams.Tests/DeleteStream/soft_deleted_stream.cs rename to test/EventStore.Client.Streams.Tests/Delete/soft_deleted_stream.cs index c27ece1cd..3f1ec9ed0 100644 --- a/test/EventStore.Client.Streams.Tests/DeleteStream/soft_deleted_stream.cs +++ b/test/EventStore.Client.Streams.Tests/Delete/soft_deleted_stream.cs @@ -2,8 +2,7 @@ namespace EventStore.Client.Streams.Tests; -[Trait("Category", "LongRunning")] -[Trait("Category", "Delete")] +[Trait("Category", "Operation:Delete")] public class deleted_stream(ITestOutputHelper output, EventStoreFixture fixture) : EventStoreTests(output, fixture) { static JsonDocument CustomMetadata { get; } diff --git a/test/EventStore.Client.Streams.Tests/DependencyInjectionTests.cs b/test/EventStore.Client.Streams.Tests/DependencyInjectionTests.cs index 6f5ea952f..96512557b 100644 --- a/test/EventStore.Client.Streams.Tests/DependencyInjectionTests.cs +++ b/test/EventStore.Client.Streams.Tests/DependencyInjectionTests.cs @@ -3,6 +3,7 @@ namespace EventStore.Client.Streams.Tests; +[Trait("Category", "UnitTest")] public class DependencyInjectionTests { [Fact] public void Register() => diff --git a/test/EventStore.Client.Streams.Tests/EventDataTests.cs b/test/EventStore.Client.Streams.Tests/EventDataTests.cs index 6c661ae59..87ed00191 100644 --- a/test/EventStore.Client.Streams.Tests/EventDataTests.cs +++ b/test/EventStore.Client.Streams.Tests/EventDataTests.cs @@ -1,5 +1,6 @@ namespace EventStore.Client.Streams.Tests; +[Trait("Category", "UnitTest")] public class EventDataTests { [Fact] public void EmptyEventIdThrows() { 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 index b40879498..8386c4cec 100644 --- a/test/EventStore.Client.Streams.Tests/EventStore.Client.Streams.Tests.csproj.DotSettings +++ b/test/EventStore.Client.Streams.Tests/EventStore.Client.Streams.Tests.csproj.DotSettings @@ -1,7 +1,10 @@  + True True True + True True + True True True True diff --git a/test/EventStore.Client.Streams.Tests/StreamMetadata/stream_metadata.cs b/test/EventStore.Client.Streams.Tests/Metadata/stream_metadata.cs similarity index 98% rename from test/EventStore.Client.Streams.Tests/StreamMetadata/stream_metadata.cs rename to test/EventStore.Client.Streams.Tests/Metadata/stream_metadata.cs index c3f28f330..241eb7416 100644 --- a/test/EventStore.Client.Streams.Tests/StreamMetadata/stream_metadata.cs +++ b/test/EventStore.Client.Streams.Tests/Metadata/stream_metadata.cs @@ -3,8 +3,7 @@ namespace EventStore.Client.Streams.Tests; -[Trait("Category", "LongRunning")] -[Trait("Category", "StreamMetadata")] +[Trait("Category", "Metadata")] public class stream_metadata(ITestOutputHelper output, EventStoreFixture fixture) : EventStoreTests(output, fixture) { [Fact] public async Task getting_for_an_existing_stream_and_no_metadata_exists() { diff --git a/test/EventStore.Client.Streams.Tests/ReadAll/read_all_events_backward.cs b/test/EventStore.Client.Streams.Tests/ReadAll/read_all_events_backward.cs index daf2024d1..7a48d432a 100644 --- a/test/EventStore.Client.Streams.Tests/ReadAll/read_all_events_backward.cs +++ b/test/EventStore.Client.Streams.Tests/ReadAll/read_all_events_backward.cs @@ -2,11 +2,11 @@ namespace EventStore.Client.Streams.Tests; -[Trait("Category", "LongRunning")] -[Trait("Category", "AllStream")] -[Trait("Category", "Read")] -[Trait("Category", "ReadBackwards")] -[Trait("Category", "DedicatedDatabase")] + +[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) { [Fact] public async Task return_empty_if_reading_from_start() { diff --git a/test/EventStore.Client.Streams.Tests/ReadAll/read_all_events_forward.cs b/test/EventStore.Client.Streams.Tests/ReadAll/read_all_events_forward.cs index 025fbff87..ab592a62e 100644 --- a/test/EventStore.Client.Streams.Tests/ReadAll/read_all_events_forward.cs +++ b/test/EventStore.Client.Streams.Tests/ReadAll/read_all_events_forward.cs @@ -2,10 +2,11 @@ namespace EventStore.Client.Streams.Tests; -[Trait("Category", "LongRunning")] -[Trait("Category", "AllStream")] -[Trait("Category", "Read")] -[Trait("Category", "ReadForwards")] + +[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) { [Fact] public async Task return_empty_if_reading_from_end() { diff --git a/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_backward.cs b/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_backward.cs index 228931560..67cfdeae7 100644 --- a/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_backward.cs +++ b/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_backward.cs @@ -2,9 +2,9 @@ namespace EventStore.Client.Streams.Tests; -[Trait("Category", "Network")] -[Trait("Category", "Stream")] -[Trait("Category", "Read")] +[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) { [Theory] [InlineData(0)] diff --git a/test/EventStore.Client.Streams.Tests/ReadStream/read_events_linked_to_deleted_stream.cs b/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_events_linked_to_deleted_stream.cs similarity index 77% rename from test/EventStore.Client.Streams.Tests/ReadStream/read_events_linked_to_deleted_stream.cs rename to test/EventStore.Client.Streams.Tests/ReadStream/read_stream_events_linked_to_deleted_stream.cs index 453bce219..530526763 100644 --- a/test/EventStore.Client.Streams.Tests/ReadStream/read_events_linked_to_deleted_stream.cs +++ b/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_events_linked_to_deleted_stream.cs @@ -2,9 +2,8 @@ namespace EventStore.Client.Streams.Tests; -[Trait("Category", "Stream")] -[Trait("Category", "Read")] -public abstract class read_events_linked_to_deleted_stream(ReadEventsLinkedToDeletedStreamFixture fixture) { +[Trait("Category", "Target:Stream")] +public abstract class read_stream_events_linked_to_deleted_stream(ReadEventsLinkedToDeletedStreamFixture fixture) { ReadEventsLinkedToDeletedStreamFixture Fixture { get; } = fixture; [Fact] @@ -19,14 +18,18 @@ public abstract class read_events_linked_to_deleted_stream(ReadEventsLinkedToDel [Fact] public void the_event_is_not_resolved() => Assert.False(Fixture.Events![0].IsResolved); + [Trait("Category", "Operation:Read")] + [Trait("Category", "Operation:Read:Forwards")] public class @forwards(forwards.CustomFixture fixture) - : read_events_linked_to_deleted_stream(fixture), IClassFixture { + : read_stream_events_linked_to_deleted_stream(fixture), IClassFixture { public class CustomFixture() : ReadEventsLinkedToDeletedStreamFixture(Direction.Forwards); } + [Trait("Category", "Operation:Read")] + [Trait("Category", "Operation:Read:Backwards")] public class @backwards(backwards.CustomFixture fixture) - : read_events_linked_to_deleted_stream(fixture), IClassFixture { + : read_stream_events_linked_to_deleted_stream(fixture), IClassFixture { public class CustomFixture() : ReadEventsLinkedToDeletedStreamFixture(Direction.Backwards); } diff --git a/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_forward.cs b/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_forward.cs index 68820922e..dc1ef5220 100644 --- a/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_forward.cs +++ b/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_forward.cs @@ -1,8 +1,8 @@ namespace EventStore.Client.Streams.Tests; -[Trait("Category", "Network")] -[Trait("Category", "Stream")] -[Trait("Category", "Read")] +[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) { [Theory] [InlineData(0)] diff --git a/test/EventStore.Client.Streams.Tests/ReadStream/when_having_max_count_set_for_stream.cs b/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_when_having_max_count_set_for_stream.cs similarity index 94% rename from test/EventStore.Client.Streams.Tests/ReadStream/when_having_max_count_set_for_stream.cs rename to test/EventStore.Client.Streams.Tests/ReadStream/read_stream_when_having_max_count_set_for_stream.cs index 041b4a27b..51d9c7113 100644 --- a/test/EventStore.Client.Streams.Tests/ReadStream/when_having_max_count_set_for_stream.cs +++ b/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_when_having_max_count_set_for_stream.cs @@ -1,9 +1,9 @@ namespace EventStore.Client.Streams.Tests; -[Trait("Category", "LongRunning")] -[Trait("Category", "Stream")] -[Trait("Category", "Read")] -public class when_having_max_count_set_for_stream (ITestOutputHelper output, EventStoreFixture fixture) : EventStoreTests(output, fixture) { + +[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) { [Fact] public async Task read_stream_forwards_respects_max_count() { var stream = Fixture.GetStreamName(); diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionsFixture.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionsFixture.cs index 0c969f079..375225ea5 100644 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionsFixture.cs +++ b/test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionsFixture.cs @@ -1,6 +1,6 @@ namespace EventStore.Client.Streams.Tests; -[Trait("Category", "LongRunning")] + [Trait("Category", "Subscriptions")] public class SubscriptionsFixture : EventStoreFixture { public SubscriptionsFixture(): base(x => x.RunProjections()) { diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all.cs index 3bf58469f..a48c9eb59 100644 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all.cs +++ b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all.cs @@ -1,6 +1,7 @@ namespace EventStore.Client.Streams.Tests; -[Trait("Category", "AllStream")] +[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() { diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream.cs index 9edced793..8041c671f 100644 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream.cs +++ b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream.cs @@ -1,6 +1,7 @@ namespace EventStore.Client.Streams.Tests; -[Trait("Category", "Stream")] +[Trait("Category", "Subscriptions")] +[Trait("Category", "Target:Stream")] public class subscribe_to_stream(ITestOutputHelper output, SubscriptionsFixture fixture) : EventStoreTests(output, fixture) { [Fact] public async Task receives_all_events_from_start() { diff --git a/test/EventStore.Client.Streams.Tests/is_json.cs b/test/EventStore.Client.Streams.Tests/is_json.cs index d9d8b3828..3ea483e48 100644 --- a/test/EventStore.Client.Streams.Tests/is_json.cs +++ b/test/EventStore.Client.Streams.Tests/is_json.cs @@ -3,8 +3,7 @@ namespace EventStore.Client.Streams.Tests; -[Trait("Category", "Network")] -[Trait("Category", "LongRunning")] +[Trait("Category", "Serialization")] public class is_json(ITestOutputHelper output, EventStoreFixture fixture) : EventStoreTests(output, fixture) { public static IEnumerable TestCases() { var json = @"{""some"":""json""}"; From 2dd50e56caed0abe34e06887dfdd336d5ce19724 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Silveira?= Date: Fri, 8 Dec 2023 12:24:28 +0100 Subject: [PATCH 18/22] more re-org stuff killed zombie code --- .../Interceptors/TypedExceptionInterceptor.cs | 151 ++---------------- .../EventStore.Client.Streams.Tests.csproj | 4 + .../{ReadAll => Read}/EventBinaryData.cs | 0 .../{ReadAll => Read}/ReadAllEventsFixture.cs | 0 .../read_all_events_backward.cs | 0 .../read_all_events_forward.cs | 0 .../read_stream_backward.cs | 0 ..._stream_events_linked_to_deleted_stream.cs | 0 .../read_stream_forward.cs | 0 ...am_when_having_max_count_set_for_stream.cs | 0 .../{ => Serialization}/is_json.cs | 0 11 files changed, 20 insertions(+), 135 deletions(-) rename test/EventStore.Client.Streams.Tests/{ReadAll => Read}/EventBinaryData.cs (100%) rename test/EventStore.Client.Streams.Tests/{ReadAll => Read}/ReadAllEventsFixture.cs (100%) rename test/EventStore.Client.Streams.Tests/{ReadAll => Read}/read_all_events_backward.cs (100%) rename test/EventStore.Client.Streams.Tests/{ReadAll => Read}/read_all_events_forward.cs (100%) rename test/EventStore.Client.Streams.Tests/{ReadStream => Read}/read_stream_backward.cs (100%) rename test/EventStore.Client.Streams.Tests/{ReadStream => Read}/read_stream_events_linked_to_deleted_stream.cs (100%) rename test/EventStore.Client.Streams.Tests/{ReadStream => Read}/read_stream_forward.cs (100%) rename test/EventStore.Client.Streams.Tests/{ReadStream => Read}/read_stream_when_having_max_count_set_for_stream.cs (100%) rename test/EventStore.Client.Streams.Tests/{ => Serialization}/is_json.cs (100%) diff --git a/src/EventStore.Client/Interceptors/TypedExceptionInterceptor.cs b/src/EventStore.Client/Interceptors/TypedExceptionInterceptor.cs index 41d16460c..dedc554a2 100644 --- a/src/EventStore.Client/Interceptors/TypedExceptionInterceptor.cs +++ b/src/EventStore.Client/Interceptors/TypedExceptionInterceptor.cs @@ -99,23 +99,23 @@ static class RpcExceptionConversionExtensions { public static IAsyncStreamReader Apply(this IAsyncStreamReader reader, Func convertException) => new ExceptionConverterStreamReader(reader, convertException); - // public static Task Apply(this Task task, Func convertException) => - // task.ContinueWith(t => t.Exception?.InnerException is RpcException ex ? throw convertException(ex) : t.Result); + public static Task Apply(this Task task, Func convertException) => + task.ContinueWith(t => t.Exception?.InnerException is RpcException ex ? throw convertException(ex) : t.Result); + + // public static async Task Apply(this Task task, Func convertException) { + // try { + // return await task.ConfigureAwait(false); + // } + // catch (Exception ex) { + // if (ex is RpcException rpcex) + // throw convertException(rpcex); // - public static async Task Apply(this Task task, Func convertException) { - try { - return await task.ConfigureAwait(false); - } - catch (Exception ex) { - if (ex is RpcException rpcex) - throw convertException(rpcex); - - if(ex is not OperationCanceledException) - throw new Exception($"WTF!? {ex.Message}", ex); - - throw; - } - } + // if(ex is not OperationCanceledException) + // throw new Exception($"WTF!? {ex.Message}", ex); + // + // throw; + // } + // } public static AccessDeniedException ToAccessDeniedException(this RpcException exception) => new(exception.Message, exception); @@ -155,122 +155,3 @@ public async Task MoveNext(CancellationToken cancellationToken) { } } } - - -internal class TypedExceptionInterceptorOld : Interceptor { - private static readonly IDictionary> DefaultExceptionMap = - new Dictionary> { - [Constants.Exceptions.AccessDenied] = ex => new AccessDeniedException(ex.Message, ex), - [Constants.Exceptions.NotLeader] = ex => new NotLeaderException( - ex.Trailers.FirstOrDefault(x => x.Key == Constants.Exceptions.LeaderEndpointHost)?.Value!, - ex.Trailers.GetIntValueOrDefault(Constants.Exceptions.LeaderEndpointPort), ex) - }; - - private readonly IDictionary> _exceptionMap; - - public TypedExceptionInterceptorOld(IDictionary> exceptionMap) { - _exceptionMap = new Dictionary>(DefaultExceptionMap); - foreach (var pair in exceptionMap) { - _exceptionMap.Add(pair); - } - } - - public override AsyncServerStreamingCall AsyncServerStreamingCall( - TRequest request, - ClientInterceptorContext context, - AsyncServerStreamingCallContinuation continuation) { - var response = continuation(request, context); - - return new AsyncServerStreamingCall( - new AsyncStreamReader(_exceptionMap, response.ResponseStream), - response.ResponseHeadersAsync, response.GetStatus, response.GetTrailers, response.Dispose); - } - - public override AsyncClientStreamingCall AsyncClientStreamingCall( - ClientInterceptorContext context, - AsyncClientStreamingCallContinuation continuation) { - var response = continuation(context); - - return new AsyncClientStreamingCall( - response.RequestStream, - response.ResponseAsync.ContinueWith(t => t.Exception?.InnerException is RpcException ex - ? throw ConvertRpcException(ex, _exceptionMap) - : t.Result), - response.ResponseHeadersAsync, - response.GetStatus, - response.GetTrailers, - response.Dispose); - } - - public override AsyncUnaryCall AsyncUnaryCall( - TRequest request, - ClientInterceptorContext context, - AsyncUnaryCallContinuation continuation) { - var response = continuation(request, context); - - return new AsyncUnaryCall( - response.ResponseAsync.ContinueWith( - t => - t.Exception?.InnerException is RpcException ex - ? throw ConvertRpcException(ex, _exceptionMap) - : t.Result - ), - response.ResponseHeadersAsync, - response.GetStatus, - response.GetTrailers, - response.Dispose - ); - } - - public override AsyncDuplexStreamingCall AsyncDuplexStreamingCall( - ClientInterceptorContext context, - AsyncDuplexStreamingCallContinuation continuation) { - var response = continuation(context); - - return new AsyncDuplexStreamingCall( - response.RequestStream, - new AsyncStreamReader(_exceptionMap, response.ResponseStream), - response.ResponseHeadersAsync, - response.GetStatus, - response.GetTrailers, - response.Dispose); - } - - private static Exception ConvertRpcException(RpcException ex, - IDictionary> exceptionMap) { - Func? factory = null; - return (ex.Trailers.TryGetValue(Constants.Exceptions.ExceptionKey, out var key) && - exceptionMap.TryGetValue(key!, out factory)) switch { - true => factory!.Invoke(ex), - false => (ex.StatusCode, ex.Status.Detail) switch { - (StatusCode.Unavailable, "Deadline Exceeded") => new RpcException(new Status( - StatusCode.DeadlineExceeded, ex.Status.Detail, ex.Status.DebugException)), - (StatusCode.DeadlineExceeded, _) => ex, - (StatusCode.Unauthenticated, _) => new NotAuthenticatedException(ex.Message, ex), - _ => ex - } - }; - } - - private class AsyncStreamReader : IAsyncStreamReader { - private readonly IDictionary> _exceptionMap; - private readonly IAsyncStreamReader _inner; - - public AsyncStreamReader(IDictionary> exceptionMap, - IAsyncStreamReader inner) { - _exceptionMap = exceptionMap; - _inner = inner; - } - - public async Task MoveNext(CancellationToken cancellationToken) { - try { - return await _inner.MoveNext(cancellationToken).ConfigureAwait(false); - } catch (RpcException ex) { - throw ConvertRpcException(ex, _exceptionMap); - } - } - - public TResponse Current => _inner.Current; - } -} - diff --git a/test/EventStore.Client.Streams.Tests/EventStore.Client.Streams.Tests.csproj b/test/EventStore.Client.Streams.Tests/EventStore.Client.Streams.Tests.csproj index d32b56a43..31f454592 100644 --- a/test/EventStore.Client.Streams.Tests/EventStore.Client.Streams.Tests.csproj +++ b/test/EventStore.Client.Streams.Tests/EventStore.Client.Streams.Tests.csproj @@ -6,4 +6,8 @@ + + + + \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/ReadAll/EventBinaryData.cs b/test/EventStore.Client.Streams.Tests/Read/EventBinaryData.cs similarity index 100% rename from test/EventStore.Client.Streams.Tests/ReadAll/EventBinaryData.cs rename to test/EventStore.Client.Streams.Tests/Read/EventBinaryData.cs diff --git a/test/EventStore.Client.Streams.Tests/ReadAll/ReadAllEventsFixture.cs b/test/EventStore.Client.Streams.Tests/Read/ReadAllEventsFixture.cs similarity index 100% rename from test/EventStore.Client.Streams.Tests/ReadAll/ReadAllEventsFixture.cs rename to test/EventStore.Client.Streams.Tests/Read/ReadAllEventsFixture.cs diff --git a/test/EventStore.Client.Streams.Tests/ReadAll/read_all_events_backward.cs b/test/EventStore.Client.Streams.Tests/Read/read_all_events_backward.cs similarity index 100% rename from test/EventStore.Client.Streams.Tests/ReadAll/read_all_events_backward.cs rename to test/EventStore.Client.Streams.Tests/Read/read_all_events_backward.cs diff --git a/test/EventStore.Client.Streams.Tests/ReadAll/read_all_events_forward.cs b/test/EventStore.Client.Streams.Tests/Read/read_all_events_forward.cs similarity index 100% rename from test/EventStore.Client.Streams.Tests/ReadAll/read_all_events_forward.cs rename to test/EventStore.Client.Streams.Tests/Read/read_all_events_forward.cs diff --git a/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_backward.cs b/test/EventStore.Client.Streams.Tests/Read/read_stream_backward.cs similarity index 100% rename from test/EventStore.Client.Streams.Tests/ReadStream/read_stream_backward.cs rename to test/EventStore.Client.Streams.Tests/Read/read_stream_backward.cs diff --git a/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_events_linked_to_deleted_stream.cs b/test/EventStore.Client.Streams.Tests/Read/read_stream_events_linked_to_deleted_stream.cs similarity index 100% rename from test/EventStore.Client.Streams.Tests/ReadStream/read_stream_events_linked_to_deleted_stream.cs rename to test/EventStore.Client.Streams.Tests/Read/read_stream_events_linked_to_deleted_stream.cs diff --git a/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_forward.cs b/test/EventStore.Client.Streams.Tests/Read/read_stream_forward.cs similarity index 100% rename from test/EventStore.Client.Streams.Tests/ReadStream/read_stream_forward.cs rename to test/EventStore.Client.Streams.Tests/Read/read_stream_forward.cs diff --git a/test/EventStore.Client.Streams.Tests/ReadStream/read_stream_when_having_max_count_set_for_stream.cs b/test/EventStore.Client.Streams.Tests/Read/read_stream_when_having_max_count_set_for_stream.cs similarity index 100% rename from test/EventStore.Client.Streams.Tests/ReadStream/read_stream_when_having_max_count_set_for_stream.cs rename to test/EventStore.Client.Streams.Tests/Read/read_stream_when_having_max_count_set_for_stream.cs diff --git a/test/EventStore.Client.Streams.Tests/is_json.cs b/test/EventStore.Client.Streams.Tests/Serialization/is_json.cs similarity index 100% rename from test/EventStore.Client.Streams.Tests/is_json.cs rename to test/EventStore.Client.Streams.Tests/Serialization/is_json.cs From 6c4f6acc5bfde449e26175deeb36d1cc956600f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Silveira?= Date: Fri, 8 Dec 2023 12:30:38 +0100 Subject: [PATCH 19/22] fixed namespaces killed zombie code --- .../Append/ShouldThrowAsyncExtensions.cs | 2 +- .../Append/append_to_stream.cs | 2 +- .../Append/append_to_stream_limits.cs | 2 +- .../Append/append_to_stream_retry.cs | 2 +- .../Append/appending_to_implicitly_created_stream.cs | 2 +- .../Append/sending_and_receiving_large_messages.cs | 2 +- .../Delete/deleting_stream.cs | 2 +- .../Delete/soft_deleted_stream.cs | 2 +- .../EventStore.Client.Streams.Tests.csproj | 4 ---- .../Metadata/stream_metadata.cs | 2 +- .../Read/EventBinaryData.cs | 2 +- .../{ => Read}/EventDataComparer.cs | 2 +- .../Read/ReadAllEventsFixture.cs | 2 +- .../Read/read_all_events_backward.cs | 3 +-- .../Read/read_all_events_forward.cs | 3 +-- .../Read/read_stream_backward.cs | 2 +- .../read_stream_events_linked_to_deleted_stream.cs | 2 +- .../Read/read_stream_forward.cs | 2 +- ...read_stream_when_having_max_count_set_for_stream.cs | 3 +-- .../Security/SecurityFixture.cs | 2 +- .../Security/all_stream_with_no_acl_security.cs | 2 +- .../Security/delete_stream_security.cs | 2 +- .../Security/multiple_role_security.cs | 2 +- .../Security/overriden_system_stream_security.cs | 2 +- .../overriden_system_stream_security_for_all.cs | 2 +- .../Security/overriden_user_stream_security.cs | 2 +- .../Security/read_all_security.cs | 2 +- .../Security/read_stream_meta_security.cs | 2 +- .../Security/read_stream_security.cs | 2 +- .../Security/stream_security_inheritance.cs | 2 +- .../Security/subscribe_to_all_security.cs | 2 +- .../Security/subscribe_to_stream_security.cs | 2 +- .../Security/system_stream_security.cs | 2 +- .../Security/write_stream_meta_security.cs | 2 +- .../Security/write_stream_security.cs | 2 +- .../Serialization/is_json.cs | 2 +- .../Subscriptions/SubscriptionDroppedResult.cs | 2 +- .../Subscriptions/SubscriptionFilter.cs | 2 +- .../Subscriptions/SubscriptionsFixture.cs | 2 +- .../Subscriptions/reconnection.cs | 2 +- .../Subscriptions/subscribe_to_all.cs | 2 +- .../Subscriptions/subscribe_to_stream.cs | 2 +- .../TestEventExtensions.cs | 10 ---------- 43 files changed, 41 insertions(+), 58 deletions(-) rename test/EventStore.Client.Streams.Tests/{ => Read}/EventDataComparer.cs (92%) delete mode 100644 test/EventStore.Client.Streams.Tests/TestEventExtensions.cs diff --git a/test/EventStore.Client.Streams.Tests/Append/ShouldThrowAsyncExtensions.cs b/test/EventStore.Client.Streams.Tests/Append/ShouldThrowAsyncExtensions.cs index 075afe533..eeab3862e 100644 --- a/test/EventStore.Client.Streams.Tests/Append/ShouldThrowAsyncExtensions.cs +++ b/test/EventStore.Client.Streams.Tests/Append/ShouldThrowAsyncExtensions.cs @@ -1,4 +1,4 @@ -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests.Append; public static class ShouldThrowAsyncExtensions { diff --git a/test/EventStore.Client.Streams.Tests/Append/append_to_stream.cs b/test/EventStore.Client.Streams.Tests/Append/append_to_stream.cs index 23d25b3b3..b4ad7d49e 100644 --- a/test/EventStore.Client.Streams.Tests/Append/append_to_stream.cs +++ b/test/EventStore.Client.Streams.Tests/Append/append_to_stream.cs @@ -1,6 +1,6 @@ using Grpc.Core; -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests.Append; [Trait("Category", "Target:Stream")] [Trait("Category", "Operation:Append")] 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 index 3d4aaf2bf..6bdd3fbb8 100644 --- a/test/EventStore.Client.Streams.Tests/Append/append_to_stream_limits.cs +++ b/test/EventStore.Client.Streams.Tests/Append/append_to_stream_limits.cs @@ -1,4 +1,4 @@ -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests.Append; [Trait("Category", "Target:Stream")] [Trait("Category", "Operation:Append")] 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 index 04725593c..d67240c49 100644 --- a/test/EventStore.Client.Streams.Tests/Append/append_to_stream_retry.cs +++ b/test/EventStore.Client.Streams.Tests/Append/append_to_stream_retry.cs @@ -1,7 +1,7 @@ using Polly; using Polly.Contrib.WaitAndRetry; -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests.Append; [Trait("Category", "Target:Stream")] [Trait("Category", "Operation:Append")] 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 index f0285b430..59ab89df0 100644 --- 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 @@ -1,4 +1,4 @@ -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests.Append; [Trait("Category", "Target:Stream")] [Trait("Category", "Operation:Append")] 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 index 512430630..099ece45c 100644 --- 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 @@ -1,6 +1,6 @@ using Grpc.Core; -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests.Append; [Trait("Category", "Target:Stream")] [Trait("Category", "Operation:Append")] diff --git a/test/EventStore.Client.Streams.Tests/Delete/deleting_stream.cs b/test/EventStore.Client.Streams.Tests/Delete/deleting_stream.cs index 535e41cee..552a8a4b9 100644 --- a/test/EventStore.Client.Streams.Tests/Delete/deleting_stream.cs +++ b/test/EventStore.Client.Streams.Tests/Delete/deleting_stream.cs @@ -1,6 +1,6 @@ using Grpc.Core; -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests.Delete; [Trait("Category", "Operation:Delete")] public class deleting_stream(ITestOutputHelper output, EventStoreFixture fixture) : EventStoreTests(output, fixture) { diff --git a/test/EventStore.Client.Streams.Tests/Delete/soft_deleted_stream.cs b/test/EventStore.Client.Streams.Tests/Delete/soft_deleted_stream.cs index 3f1ec9ed0..25877d2ee 100644 --- a/test/EventStore.Client.Streams.Tests/Delete/soft_deleted_stream.cs +++ b/test/EventStore.Client.Streams.Tests/Delete/soft_deleted_stream.cs @@ -1,6 +1,6 @@ using System.Text.Json; -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests.Delete; [Trait("Category", "Operation:Delete")] public class deleted_stream(ITestOutputHelper output, EventStoreFixture fixture) : EventStoreTests(output, fixture) { diff --git a/test/EventStore.Client.Streams.Tests/EventStore.Client.Streams.Tests.csproj b/test/EventStore.Client.Streams.Tests/EventStore.Client.Streams.Tests.csproj index 31f454592..d32b56a43 100644 --- a/test/EventStore.Client.Streams.Tests/EventStore.Client.Streams.Tests.csproj +++ b/test/EventStore.Client.Streams.Tests/EventStore.Client.Streams.Tests.csproj @@ -6,8 +6,4 @@ - - - - \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/Metadata/stream_metadata.cs b/test/EventStore.Client.Streams.Tests/Metadata/stream_metadata.cs index 241eb7416..706d5e2b6 100644 --- a/test/EventStore.Client.Streams.Tests/Metadata/stream_metadata.cs +++ b/test/EventStore.Client.Streams.Tests/Metadata/stream_metadata.cs @@ -1,7 +1,7 @@ using System.Text.Json; using Grpc.Core; -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests.Metadata; [Trait("Category", "Metadata")] public class stream_metadata(ITestOutputHelper output, EventStoreFixture fixture) : EventStoreTests(output, fixture) { diff --git a/test/EventStore.Client.Streams.Tests/Read/EventBinaryData.cs b/test/EventStore.Client.Streams.Tests/Read/EventBinaryData.cs index 1f7d3bf3b..923a40cd1 100644 --- a/test/EventStore.Client.Streams.Tests/Read/EventBinaryData.cs +++ b/test/EventStore.Client.Streams.Tests/Read/EventBinaryData.cs @@ -1,4 +1,4 @@ -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests.Read; public readonly record struct EventBinaryData(Uuid Id, byte[] Data, byte[] Metadata) { public bool Equals(EventBinaryData other) => diff --git a/test/EventStore.Client.Streams.Tests/EventDataComparer.cs b/test/EventStore.Client.Streams.Tests/Read/EventDataComparer.cs similarity index 92% rename from test/EventStore.Client.Streams.Tests/EventDataComparer.cs rename to test/EventStore.Client.Streams.Tests/Read/EventDataComparer.cs index 48a5e8977..cd9c6f41a 100644 --- a/test/EventStore.Client.Streams.Tests/EventDataComparer.cs +++ b/test/EventStore.Client.Streams.Tests/Read/EventDataComparer.cs @@ -1,4 +1,4 @@ -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests.Read; static class EventDataComparer { public static bool Equal(EventData expected, EventRecord actual) { diff --git a/test/EventStore.Client.Streams.Tests/Read/ReadAllEventsFixture.cs b/test/EventStore.Client.Streams.Tests/Read/ReadAllEventsFixture.cs index 2579e4260..297a79b70 100644 --- a/test/EventStore.Client.Streams.Tests/Read/ReadAllEventsFixture.cs +++ b/test/EventStore.Client.Streams.Tests/Read/ReadAllEventsFixture.cs @@ -1,4 +1,4 @@ -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests.Read; public class ReadAllEventsFixture : EventStoreFixture { public ReadAllEventsFixture() { diff --git a/test/EventStore.Client.Streams.Tests/Read/read_all_events_backward.cs b/test/EventStore.Client.Streams.Tests/Read/read_all_events_backward.cs index 7a48d432a..63135ec82 100644 --- a/test/EventStore.Client.Streams.Tests/Read/read_all_events_backward.cs +++ b/test/EventStore.Client.Streams.Tests/Read/read_all_events_backward.cs @@ -1,7 +1,6 @@ using Grpc.Core; -namespace EventStore.Client.Streams.Tests; - +namespace EventStore.Client.Streams.Tests.Read; [Trait("Category", "Target:All")] [Trait("Category", "Operation:Read")] diff --git a/test/EventStore.Client.Streams.Tests/Read/read_all_events_forward.cs b/test/EventStore.Client.Streams.Tests/Read/read_all_events_forward.cs index ab592a62e..ab93da29a 100644 --- a/test/EventStore.Client.Streams.Tests/Read/read_all_events_forward.cs +++ b/test/EventStore.Client.Streams.Tests/Read/read_all_events_forward.cs @@ -1,7 +1,6 @@ using System.Text; -namespace EventStore.Client.Streams.Tests; - +namespace EventStore.Client.Streams.Tests.Read; [Trait("Category", "Target:All")] [Trait("Category", "Operation:Read")] diff --git a/test/EventStore.Client.Streams.Tests/Read/read_stream_backward.cs b/test/EventStore.Client.Streams.Tests/Read/read_stream_backward.cs index 67cfdeae7..4101ef3b6 100644 --- a/test/EventStore.Client.Streams.Tests/Read/read_stream_backward.cs +++ b/test/EventStore.Client.Streams.Tests/Read/read_stream_backward.cs @@ -1,6 +1,6 @@ using Grpc.Core; -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests.Read; [Trait("Category", "Target:Stream")] [Trait("Category", "Operation:Read")] diff --git a/test/EventStore.Client.Streams.Tests/Read/read_stream_events_linked_to_deleted_stream.cs b/test/EventStore.Client.Streams.Tests/Read/read_stream_events_linked_to_deleted_stream.cs index 530526763..ba11b75f0 100644 --- a/test/EventStore.Client.Streams.Tests/Read/read_stream_events_linked_to_deleted_stream.cs +++ b/test/EventStore.Client.Streams.Tests/Read/read_stream_events_linked_to_deleted_stream.cs @@ -1,6 +1,6 @@ using System.Text; -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests.Read; [Trait("Category", "Target:Stream")] public abstract class read_stream_events_linked_to_deleted_stream(ReadEventsLinkedToDeletedStreamFixture fixture) { diff --git a/test/EventStore.Client.Streams.Tests/Read/read_stream_forward.cs b/test/EventStore.Client.Streams.Tests/Read/read_stream_forward.cs index dc1ef5220..b8571b121 100644 --- a/test/EventStore.Client.Streams.Tests/Read/read_stream_forward.cs +++ b/test/EventStore.Client.Streams.Tests/Read/read_stream_forward.cs @@ -1,4 +1,4 @@ -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests.Read; [Trait("Category", "Target:Stream")] [Trait("Category", "Operation:Read")] diff --git a/test/EventStore.Client.Streams.Tests/Read/read_stream_when_having_max_count_set_for_stream.cs b/test/EventStore.Client.Streams.Tests/Read/read_stream_when_having_max_count_set_for_stream.cs index 51d9c7113..0142ebd9a 100644 --- a/test/EventStore.Client.Streams.Tests/Read/read_stream_when_having_max_count_set_for_stream.cs +++ b/test/EventStore.Client.Streams.Tests/Read/read_stream_when_having_max_count_set_for_stream.cs @@ -1,5 +1,4 @@ -namespace EventStore.Client.Streams.Tests; - +namespace EventStore.Client.Streams.Tests.Read; [Trait("Category", "Target:Stream")] [Trait("Category", "Operation:Read")] diff --git a/test/EventStore.Client.Streams.Tests/Security/SecurityFixture.cs b/test/EventStore.Client.Streams.Tests/Security/SecurityFixture.cs index bcc6e8b15..c472581bf 100644 --- a/test/EventStore.Client.Streams.Tests/Security/SecurityFixture.cs +++ b/test/EventStore.Client.Streams.Tests/Security/SecurityFixture.cs @@ -1,6 +1,6 @@ using System.Runtime.CompilerServices; -namespace EventStore.Client.Streams.Tests.Security; +namespace EventStore.Client.Streams.Tests; public class SecurityFixture : EventStoreFixture { public const string NoAclStream = nameof(NoAclStream); diff --git a/test/EventStore.Client.Streams.Tests/Security/all_stream_with_no_acl_security.cs b/test/EventStore.Client.Streams.Tests/Security/all_stream_with_no_acl_security.cs index c87f2e1df..215e0f05d 100644 --- a/test/EventStore.Client.Streams.Tests/Security/all_stream_with_no_acl_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/all_stream_with_no_acl_security.cs @@ -1,4 +1,4 @@ -namespace EventStore.Client.Streams.Tests.Security; +namespace EventStore.Client.Streams.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) { diff --git a/test/EventStore.Client.Streams.Tests/Security/delete_stream_security.cs b/test/EventStore.Client.Streams.Tests/Security/delete_stream_security.cs index 85bec14c8..61e6253ce 100644 --- a/test/EventStore.Client.Streams.Tests/Security/delete_stream_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/delete_stream_security.cs @@ -1,4 +1,4 @@ -namespace EventStore.Client.Streams.Tests.Security; +namespace EventStore.Client.Streams.Tests; [Trait("Category", "Security")] public class delete_stream_security(ITestOutputHelper output, SecurityFixture fixture) : EventStoreTests(output, fixture) { diff --git a/test/EventStore.Client.Streams.Tests/Security/multiple_role_security.cs b/test/EventStore.Client.Streams.Tests/Security/multiple_role_security.cs index 9ac1d775a..3195c22df 100644 --- a/test/EventStore.Client.Streams.Tests/Security/multiple_role_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/multiple_role_security.cs @@ -1,4 +1,4 @@ -namespace EventStore.Client.Streams.Tests.Security; +namespace EventStore.Client.Streams.Tests; [Trait("Category", "Security")] public class multiple_role_security(ITestOutputHelper output, multiple_role_security.CustomFixture fixture) : EventStoreTests(output, fixture) { diff --git a/test/EventStore.Client.Streams.Tests/Security/overriden_system_stream_security.cs b/test/EventStore.Client.Streams.Tests/Security/overriden_system_stream_security.cs index 795c2bc46..0d41c4450 100644 --- a/test/EventStore.Client.Streams.Tests/Security/overriden_system_stream_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/overriden_system_stream_security.cs @@ -1,4 +1,4 @@ -namespace EventStore.Client.Streams.Tests.Security; +namespace EventStore.Client.Streams.Tests; [Trait("Category", "Security")] public class overriden_system_stream_security(ITestOutputHelper output, overriden_system_stream_security.CustomFixture fixture) : EventStoreTests(output, fixture) { diff --git a/test/EventStore.Client.Streams.Tests/Security/overriden_system_stream_security_for_all.cs b/test/EventStore.Client.Streams.Tests/Security/overriden_system_stream_security_for_all.cs index fcc33c1f0..8324451ef 100644 --- a/test/EventStore.Client.Streams.Tests/Security/overriden_system_stream_security_for_all.cs +++ b/test/EventStore.Client.Streams.Tests/Security/overriden_system_stream_security_for_all.cs @@ -1,4 +1,4 @@ -namespace EventStore.Client.Streams.Tests.Security; +namespace EventStore.Client.Streams.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) { diff --git a/test/EventStore.Client.Streams.Tests/Security/overriden_user_stream_security.cs b/test/EventStore.Client.Streams.Tests/Security/overriden_user_stream_security.cs index 708b5a8aa..ce1ebe1e9 100644 --- a/test/EventStore.Client.Streams.Tests/Security/overriden_user_stream_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/overriden_user_stream_security.cs @@ -1,4 +1,4 @@ -namespace EventStore.Client.Streams.Tests.Security; +namespace EventStore.Client.Streams.Tests; [Trait("Category", "Security")] public class overriden_user_stream_security(ITestOutputHelper output, overriden_user_stream_security.CustomFixture fixture) : EventStoreTests(output, fixture) { diff --git a/test/EventStore.Client.Streams.Tests/Security/read_all_security.cs b/test/EventStore.Client.Streams.Tests/Security/read_all_security.cs index ab510761e..01089db2e 100644 --- a/test/EventStore.Client.Streams.Tests/Security/read_all_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/read_all_security.cs @@ -1,4 +1,4 @@ -namespace EventStore.Client.Streams.Tests.Security; +namespace EventStore.Client.Streams.Tests; [Trait("Category", "Security")] public class read_all_security(ITestOutputHelper output, SecurityFixture fixture) : EventStoreTests(output, fixture) { diff --git a/test/EventStore.Client.Streams.Tests/Security/read_stream_meta_security.cs b/test/EventStore.Client.Streams.Tests/Security/read_stream_meta_security.cs index 0e396080a..b3a7e7afa 100644 --- a/test/EventStore.Client.Streams.Tests/Security/read_stream_meta_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/read_stream_meta_security.cs @@ -1,4 +1,4 @@ -namespace EventStore.Client.Streams.Tests.Security; +namespace EventStore.Client.Streams.Tests; [Trait("Category", "Security")] public class read_stream_meta_security(ITestOutputHelper output, SecurityFixture fixture) : EventStoreTests(output, fixture) { diff --git a/test/EventStore.Client.Streams.Tests/Security/read_stream_security.cs b/test/EventStore.Client.Streams.Tests/Security/read_stream_security.cs index 20b512dc6..206627128 100644 --- a/test/EventStore.Client.Streams.Tests/Security/read_stream_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/read_stream_security.cs @@ -1,4 +1,4 @@ -namespace EventStore.Client.Streams.Tests.Security; +namespace EventStore.Client.Streams.Tests; [Trait("Category", "Security")] public class read_stream_security(ITestOutputHelper output, SecurityFixture fixture) : EventStoreTests(output, fixture) { diff --git a/test/EventStore.Client.Streams.Tests/Security/stream_security_inheritance.cs b/test/EventStore.Client.Streams.Tests/Security/stream_security_inheritance.cs index 729e6b463..1e1221e16 100644 --- a/test/EventStore.Client.Streams.Tests/Security/stream_security_inheritance.cs +++ b/test/EventStore.Client.Streams.Tests/Security/stream_security_inheritance.cs @@ -1,4 +1,4 @@ -namespace EventStore.Client.Streams.Tests.Security; +namespace EventStore.Client.Streams.Tests; [Trait("Category", "Security")] public class stream_security_inheritance(ITestOutputHelper output, stream_security_inheritance.CustomFixture fixture) : EventStoreTests(output, fixture) { diff --git a/test/EventStore.Client.Streams.Tests/Security/subscribe_to_all_security.cs b/test/EventStore.Client.Streams.Tests/Security/subscribe_to_all_security.cs index 0de1f764a..48b62a52d 100644 --- a/test/EventStore.Client.Streams.Tests/Security/subscribe_to_all_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/subscribe_to_all_security.cs @@ -1,4 +1,4 @@ -namespace EventStore.Client.Streams.Tests.Security; +namespace EventStore.Client.Streams.Tests; [Trait("Category", "Security")] public class subscribe_to_all_security(ITestOutputHelper output, SecurityFixture fixture) : EventStoreTests(output, fixture) { diff --git a/test/EventStore.Client.Streams.Tests/Security/subscribe_to_stream_security.cs b/test/EventStore.Client.Streams.Tests/Security/subscribe_to_stream_security.cs index cc08d400d..1bcb43ae1 100644 --- a/test/EventStore.Client.Streams.Tests/Security/subscribe_to_stream_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/subscribe_to_stream_security.cs @@ -1,4 +1,4 @@ -namespace EventStore.Client.Streams.Tests.Security; +namespace EventStore.Client.Streams.Tests; [Trait("Category", "Security")] public class subscribe_to_stream_security(ITestOutputHelper output, SecurityFixture fixture) : EventStoreTests(output, fixture) { diff --git a/test/EventStore.Client.Streams.Tests/Security/system_stream_security.cs b/test/EventStore.Client.Streams.Tests/Security/system_stream_security.cs index 303711d40..bbf482cbe 100644 --- a/test/EventStore.Client.Streams.Tests/Security/system_stream_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/system_stream_security.cs @@ -1,4 +1,4 @@ -namespace EventStore.Client.Streams.Tests.Security; +namespace EventStore.Client.Streams.Tests; [Trait("Category", "Security")] public class system_stream_security(ITestOutputHelper output, SecurityFixture fixture) : EventStoreTests(output, fixture) { diff --git a/test/EventStore.Client.Streams.Tests/Security/write_stream_meta_security.cs b/test/EventStore.Client.Streams.Tests/Security/write_stream_meta_security.cs index 591b5d61e..9b003795c 100644 --- a/test/EventStore.Client.Streams.Tests/Security/write_stream_meta_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/write_stream_meta_security.cs @@ -1,4 +1,4 @@ -namespace EventStore.Client.Streams.Tests.Security; +namespace EventStore.Client.Streams.Tests; [Trait("Category", "Security")] public class write_stream_meta_security(ITestOutputHelper output, SecurityFixture fixture) : EventStoreTests(output, fixture) { diff --git a/test/EventStore.Client.Streams.Tests/Security/write_stream_security.cs b/test/EventStore.Client.Streams.Tests/Security/write_stream_security.cs index 3061b96e7..d002d37c9 100644 --- a/test/EventStore.Client.Streams.Tests/Security/write_stream_security.cs +++ b/test/EventStore.Client.Streams.Tests/Security/write_stream_security.cs @@ -1,4 +1,4 @@ -namespace EventStore.Client.Streams.Tests.Security; +namespace EventStore.Client.Streams.Tests; [Trait("Category", "Security")] public class write_stream_security : IClassFixture { diff --git a/test/EventStore.Client.Streams.Tests/Serialization/is_json.cs b/test/EventStore.Client.Streams.Tests/Serialization/is_json.cs index 3ea483e48..d2b44a918 100644 --- a/test/EventStore.Client.Streams.Tests/Serialization/is_json.cs +++ b/test/EventStore.Client.Streams.Tests/Serialization/is_json.cs @@ -1,7 +1,7 @@ using System.Runtime.CompilerServices; using System.Text; -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests.Serialization; [Trait("Category", "Serialization")] public class is_json(ITestOutputHelper output, EventStoreFixture fixture) : EventStoreTests(output, fixture) { diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionDroppedResult.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionDroppedResult.cs index 6b3887a78..40df3eb52 100644 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionDroppedResult.cs +++ b/test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionDroppedResult.cs @@ -1,4 +1,4 @@ -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests.Subscriptions; public record SubscriptionDroppedResult(SubscriptionDroppedReason Reason, Exception? Error) { public Task Throw() => Task.FromException(Error!); diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionFilter.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionFilter.cs index b7d4d76dc..e670b69c9 100644 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionFilter.cs +++ b/test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionFilter.cs @@ -1,4 +1,4 @@ -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests.Subscriptions; public record SubscriptionFilter(string Name, Func Create, Func PrepareEvent) { public override string ToString() => Name; diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionsFixture.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionsFixture.cs index 375225ea5..582344f98 100644 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionsFixture.cs +++ b/test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionsFixture.cs @@ -1,4 +1,4 @@ -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests.Subscriptions; [Trait("Category", "Subscriptions")] diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/reconnection.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/reconnection.cs index e532135f3..df9162130 100644 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/reconnection.cs +++ b/test/EventStore.Client.Streams.Tests/Subscriptions/reconnection.cs @@ -1,7 +1,7 @@ using Grpc.Core; using static System.TimeSpan; -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests.Subscriptions; [Trait("Category", "Subscriptions")] public class @reconnection(ITestOutputHelper output, ReconnectionFixture fixture) : EventStoreTests(output, fixture) { diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all.cs index a48c9eb59..0217521d5 100644 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all.cs +++ b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all.cs @@ -1,4 +1,4 @@ -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests.Subscriptions; [Trait("Category", "Subscriptions")] [Trait("Category", "Target:All")] diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream.cs index 8041c671f..ca5dc122e 100644 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream.cs +++ b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream.cs @@ -1,4 +1,4 @@ -namespace EventStore.Client.Streams.Tests; +namespace EventStore.Client.Streams.Tests.Subscriptions; [Trait("Category", "Subscriptions")] [Trait("Category", "Target:Stream")] diff --git a/test/EventStore.Client.Streams.Tests/TestEventExtensions.cs b/test/EventStore.Client.Streams.Tests/TestEventExtensions.cs deleted file mode 100644 index be6269d4d..000000000 --- a/test/EventStore.Client.Streams.Tests/TestEventExtensions.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace EventStore.Client.Streams.Tests; - -public static class TestEventExtensions { - public static IEnumerable AsResolvedTestEvents(this IEnumerable events) { - if (events == null) - throw new ArgumentNullException(nameof(events)); - - return events.Where(x => x.Event.EventType == EventStoreFixture.TestEventType).Select(x => x.Event); - } -} \ No newline at end of file From b5949b8850fc9ea8b15a251dc89cbcd06abe20fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Silveira?= Date: Fri, 8 Dec 2023 12:33:41 +0100 Subject: [PATCH 20/22] fixed quickstart samples connstring --- samples/quick-start/Program.cs | 2 +- .../EventStore.Client.Streams.Tests.csproj.DotSettings | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/samples/quick-start/Program.cs b/samples/quick-start/Program.cs index 18d6ce80e..0cd070137 100644 --- a/samples/quick-start/Program.cs +++ b/samples/quick-start/Program.cs @@ -5,7 +5,7 @@ #region createClient -const string connectionString = "esdb://admin:changeit@localhost:2113?tls=true&tlsVerifyCert=false"; +const string connectionString = "esdb://admin:changeit@localhost:2113?tls=false&tlsVerifyCert=false"; var settings = EventStoreClientSettings.Create(connectionString); 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 index 8386c4cec..9176e378d 100644 --- a/test/EventStore.Client.Streams.Tests/EventStore.Client.Streams.Tests.csproj.DotSettings +++ b/test/EventStore.Client.Streams.Tests/EventStore.Client.Streams.Tests.csproj.DotSettings @@ -1,12 +1,12 @@  - True + False True - True - True + False + False True - True + False True True True True - True \ No newline at end of file + False \ No newline at end of file From 83c67554f18819845166c328c4a73f019bab7ab6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Silveira?= Date: Wed, 20 Dec 2023 16:16:34 +0100 Subject: [PATCH 21/22] fixed PR --- Directory.Build.props | 2 -- EventStore.Client.sln.DotSettings | 1 + samples/quick-start/docker-compose.yml | 1 + samples/secure-with-tls/docker-compose.yml | 1 + src/EventStore.Client/ChannelCache.cs | 1 - src/EventStore.Client/EventStore.Client.csproj | 4 +--- .../Append/ShouldThrowAsyncExtensions.cs | 1 - .../Subscriptions/subscribe_to_all.cs | 2 +- .../Fixtures/EventStoreTestNode.cs | 2 +- test/EventStore.Client.Tests.Common/GlobalEnvironment.cs | 2 +- .../Shouldly/ShouldThrowAsyncExtensions.cs | 7 +++---- 11 files changed, 10 insertions(+), 14 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index ac609fab3..eecbb8220 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -13,8 +13,6 @@ pdbonly true - - 2.59.0 2.59.0 diff --git a/EventStore.Client.sln.DotSettings b/EventStore.Client.sln.DotSettings index 671c31c8a..f97c72463 100644 --- a/EventStore.Client.sln.DotSettings +++ b/EventStore.Client.sln.DotSettings @@ -402,4 +402,5 @@ True True True + True True \ No newline at end of file diff --git a/samples/quick-start/docker-compose.yml b/samples/quick-start/docker-compose.yml index d98e8b298..f6621fd78 100644 --- a/samples/quick-start/docker-compose.yml +++ b/samples/quick-start/docker-compose.yml @@ -7,5 +7,6 @@ services: EVENTSTORE_MEM_DB: false EVENTSTORE_RUN_PROJECTIONS: all EVENTSTORE_START_STANDARD_PROJECTIONS: true + EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP: true ports: - "2113:2113" \ No newline at end of file diff --git a/samples/secure-with-tls/docker-compose.yml b/samples/secure-with-tls/docker-compose.yml index 61336df7a..f1078440f 100644 --- a/samples/secure-with-tls/docker-compose.yml +++ b/samples/secure-with-tls/docker-compose.yml @@ -15,6 +15,7 @@ services: - EVENTSTORE_LOG_LEVEL=Information - EVENTSTORE_RUN_PROJECTIONS=None - EVENTSTORE_START_STANDARD_PROJECTIONS=true + - EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP=true # set certificates location - EVENTSTORE_CERTIFICATE_FILE=/etc/eventstore/certs/node/node.crt diff --git a/src/EventStore.Client/ChannelCache.cs b/src/EventStore.Client/ChannelCache.cs index f61654cee..a3369e25f 100644 --- a/src/EventStore.Client/ChannelCache.cs +++ b/src/EventStore.Client/ChannelCache.cs @@ -6,7 +6,6 @@ namespace EventStore.Client { // Deals with the disposal difference between grpc.net and grpc.core // Thread safe. internal class ChannelCache : - //IDisposable, // for grpc.net we can dispose synchronously, but not for grpc.core IAsyncDisposable { private readonly EventStoreClientSettings _settings; diff --git a/src/EventStore.Client/EventStore.Client.csproj b/src/EventStore.Client/EventStore.Client.csproj index 045d738fc..92a14142f 100644 --- a/src/EventStore.Client/EventStore.Client.csproj +++ b/src/EventStore.Client/EventStore.Client.csproj @@ -7,10 +7,8 @@ - - + - diff --git a/test/EventStore.Client.Streams.Tests/Append/ShouldThrowAsyncExtensions.cs b/test/EventStore.Client.Streams.Tests/Append/ShouldThrowAsyncExtensions.cs index eeab3862e..80f983ce0 100644 --- a/test/EventStore.Client.Streams.Tests/Append/ShouldThrowAsyncExtensions.cs +++ b/test/EventStore.Client.Streams.Tests/Append/ShouldThrowAsyncExtensions.cs @@ -1,7 +1,6 @@ namespace EventStore.Client.Streams.Tests.Append; public static class ShouldThrowAsyncExtensions { - public static Task ShouldThrowAsync(this EventStoreClient.ReadStreamResult source) where TException : Exception => source .ToArrayAsync() diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all.cs index 0217521d5..9ea4add2b 100644 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all.cs +++ b/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all.cs @@ -573,7 +573,7 @@ public async Task drops_when_subscriber_error() { var expectedResult = SubscriptionDroppedResult.SubscriberError(); var subscriptionDropped = new TaskCompletionSource(); - + using var subscription = await Fixture.Streams .SubscribeToAllAsync( FromAll.Start, diff --git a/test/EventStore.Client.Tests.Common/Fixtures/EventStoreTestNode.cs b/test/EventStore.Client.Tests.Common/Fixtures/EventStoreTestNode.cs index a84af081a..46ae316da 100644 --- a/test/EventStore.Client.Tests.Common/Fixtures/EventStoreTestNode.cs +++ b/test/EventStore.Client.Tests.Common/Fixtures/EventStoreTestNode.cs @@ -38,7 +38,7 @@ public static EventStoreFixtureOptions DefaultOptions() { ["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"] = "false", + ["EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP"] = "true", ["EVENTSTORE_DISABLE_LOG_FILE"] = "true", ["EVENTSTORE_ADVERTISE_HTTP_PORT_TO_CLIENT_AS"] = $"{NetworkPortProvider.DefaultEsdbPort}" }; diff --git a/test/EventStore.Client.Tests.Common/GlobalEnvironment.cs b/test/EventStore.Client.Tests.Common/GlobalEnvironment.cs index 3ecc3c859..f2e1e69eb 100644 --- a/test/EventStore.Client.Tests.Common/GlobalEnvironment.cs +++ b/test/EventStore.Client.Tests.Common/GlobalEnvironment.cs @@ -32,7 +32,7 @@ static void EnsureDefaults(IConfiguration configuration) { configuration.EnsureValue("EVENTSTORE_LOG_LEVEL", "Information"); 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", "false"); + configuration.EnsureValue("EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP", "true"); } } diff --git a/test/EventStore.Client.Tests.Common/Shouldly/ShouldThrowAsyncExtensions.cs b/test/EventStore.Client.Tests.Common/Shouldly/ShouldThrowAsyncExtensions.cs index 9dcda959a..b75778b47 100644 --- a/test/EventStore.Client.Tests.Common/Shouldly/ShouldThrowAsyncExtensions.cs +++ b/test/EventStore.Client.Tests.Common/Shouldly/ShouldThrowAsyncExtensions.cs @@ -1,3 +1,5 @@ +// ReSharper disable CheckNamespace + using System.Diagnostics; using EventStore.Client; @@ -6,8 +8,5 @@ namespace Shouldly; [DebuggerStepThrough] public static class ShouldThrowAsyncExtensions { public static Task ShouldThrowAsync(this EventStoreClient.ReadStreamResult source) where TException : Exception => - source - .ToArrayAsync() - .AsTask() - .ShouldThrowAsync(); + source.ToArrayAsync().AsTask().ShouldThrowAsync(); } \ No newline at end of file From e51e87a2ab2cbd7a6c20fba1577106147478f397 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Silveira?= Date: Wed, 20 Dec 2023 16:19:29 +0100 Subject: [PATCH 22/22] removed some commented out code. --- .../Interceptors/TypedExceptionInterceptor.cs | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/EventStore.Client/Interceptors/TypedExceptionInterceptor.cs b/src/EventStore.Client/Interceptors/TypedExceptionInterceptor.cs index dedc554a2..75754f95f 100644 --- a/src/EventStore.Client/Interceptors/TypedExceptionInterceptor.cs +++ b/src/EventStore.Client/Interceptors/TypedExceptionInterceptor.cs @@ -102,21 +102,6 @@ public static IAsyncStreamReader Apply(this IAsyncStreamRead public static Task Apply(this Task task, Func convertException) => task.ContinueWith(t => t.Exception?.InnerException is RpcException ex ? throw convertException(ex) : t.Result); - // public static async Task Apply(this Task task, Func convertException) { - // try { - // return await task.ConfigureAwait(false); - // } - // catch (Exception ex) { - // if (ex is RpcException rpcex) - // throw convertException(rpcex); - // - // if(ex is not OperationCanceledException) - // throw new Exception($"WTF!? {ex.Message}", ex); - // - // throw; - // } - // } - public static AccessDeniedException ToAccessDeniedException(this RpcException exception) => new(exception.Message, exception);